import { describe, it, expect } from 'vitest' import { PGlite } from '@electric-sql/pglite' import { pgDump } from '../dist/pg_dump.js' import * as fs from 'fs/promises' describe('pgDump', () => { it('should dump an empty database', async () => { const pg = await PGlite.create() const dump = await pgDump({ pg }) expect(dump).toBeInstanceOf(File) expect(dump.name).toBe('dump.sql') const content = await dump.text() expect(content).toContain('PostgreSQL database dump') }) it('should dump an empty database multiple times', async () => { const pg = await PGlite.create() for (let i = 0; i < 5; i++) { const fileName = `dump_${i}.sql` const dump = await pgDump({ pg, fileName }) expect(dump).toBeInstanceOf(File) expect(dump.name).toBe(fileName) const content = await dump.text() expect(content).toContain('PostgreSQL database dump') } }) it('should dump a database with tables and data', async () => { const pg = await PGlite.create() // Create test tables and insert data await pg.exec(` CREATE TABLE test1 ( id SERIAL PRIMARY KEY, name TEXT ); INSERT INTO test1 (name) VALUES ('test1-row1'); CREATE TABLE test2 ( id SERIAL PRIMARY KEY, value INTEGER ); INSERT INTO test2 (value) VALUES (42); `) const dump = await pgDump({ pg }) const content = await dump.text() // Check for table creation expect(content).toContain('CREATE TABLE public.test1') expect(content).toContain('CREATE TABLE public.test2') // Check for data inserts expect(content).toContain('INSERT INTO public.test1') expect(content).toContain("'test1-row1'") expect(content).toContain('INSERT INTO public.test2') expect(content).toContain('42') }) it('should respect custom filename', async () => { const pg = await PGlite.create() const dump = await pgDump({ pg, fileName: 'custom.sql' }) expect(dump.name).toBe('custom.sql') }) it('should handle custom pg_dump arguments', async () => { const pg = await PGlite.create() await pg.exec(` CREATE TABLE test (id SERIAL PRIMARY KEY, name TEXT); INSERT INTO test (name) VALUES ('row1'); `) // Use --schema-only to exclude data const dump = await pgDump({ pg, args: ['--schema-only'] }) const content = await dump.text() expect(content).toContain('CREATE TABLE public.test') expect(content).not.toContain('INSERT INTO public.test') }) it('should be able to restore dumped database', async () => { const pg1 = await PGlite.create() // Create original database await pg1.exec(` CREATE TABLE test (id SERIAL PRIMARY KEY, name TEXT); INSERT INTO test (name) VALUES ('row1'), ('row2'); `) const initialSearchPath = ( await pg1.query<{ search_path: string }>('SHOW SEARCH_PATH;') ).rows[0].search_path // Dump database const dump = await pgDump({ pg: pg1 }) const dumpContent = await dump.text() // Create new database and restore const pg2 = await PGlite.create() await pg2.exec(dumpContent) // after importing, set search path back to the initial one await pg2.exec(`SET search_path TO ${initialSearchPath};`) // Verify data const result = await pg2.query<{ name: string }>( 'SELECT * FROM test ORDER BY id', ) expect(result.rows).toHaveLength(2) expect(result.rows[0].name).toBe('row1') expect(result.rows[1].name).toBe('row2') }) it('pg_dump should not change SEARCH_PATH', async () => { const pg = await PGlite.create() await pg.exec(`SET SEARCH_PATH = amigo;`) const initialSearchPath = await pg.query('SHOW SEARCH_PATH;') const dump = await pgDump({ pg }) await dump.text() const finalSearchPath = await pg.query('SHOW SEARCH_PATH;') expect(initialSearchPath).toEqual(finalSearchPath) }) it('specify datadir: should dump a database with tables and data', async () => { const dataDir = '/tmp/pg_dump_pglite_data_dir' await fs.rm(dataDir, { force: true, recursive: true }) const pg = await PGlite.create({ dataDir: dataDir, }) // Create test tables and insert data await pg.exec(` CREATE TABLE test1 ( id SERIAL PRIMARY KEY, name TEXT ); INSERT INTO test1 (name) VALUES ('test1-row1'); CREATE TABLE test2 ( id SERIAL PRIMARY KEY, value INTEGER ); INSERT INTO test2 (value) VALUES (42); `) const dump = await pgDump({ pg }) const content = await dump.text() // Check for table creation expect(content).toContain('CREATE TABLE public.test1') expect(content).toContain('CREATE TABLE public.test2') // Check for data inserts expect(content).toContain('INSERT INTO public.test1') expect(content).toContain("'test1-row1'") expect(content).toContain('INSERT INTO public.test2') expect(content).toContain('42') }) it('param --quote-all-identifiers should work', async () => { const pg = await PGlite.create() // Create test tables and insert data await pg.exec(` CREATE TABLE test1 ( id SERIAL PRIMARY KEY, name TEXT ); INSERT INTO test1 (name) VALUES ('test1-row1'); CREATE TABLE test2 ( id SERIAL PRIMARY KEY, value INTEGER ); INSERT INTO test2 (value) VALUES (42); `) const dump = await pgDump({ pg, args: ['--quote-all-identifiers'] }) const content = await dump.text() // Check for table creation expect(content).toContain('CREATE TABLE "public"."test1"') expect(content).toContain('CREATE TABLE "public"."test2"') // Check for data inserts expect(content).toContain('INSERT INTO "public"."test1"') expect(content).toContain("'test1-row1'") expect(content).toContain('INSERT INTO "public"."test2"') expect(content).toContain('42') }) })