Files
2026-01-23 01:33:35 +01:00

202 lines
5.9 KiB
TypeScript

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')
})
})