publications.test.ts319 lines · main
1import { afterAll, beforeAll, expect, test } from 'vitest'
2
3import pgMeta from '../src/index'
4import { cleanupRoot, createTestDatabase } from './db/utils'
5
6beforeAll(async () => {
7 // Any global setup if needed
8})
9
10afterAll(async () => {
11 await cleanupRoot()
12})
13
14const withTestDatabase = (
15 name: string,
16 fn: (db: Awaited<ReturnType<typeof createTestDatabase>>) => Promise<void>
17) => {
18 test(name, async () => {
19 const db = await createTestDatabase()
20 try {
21 await fn(db)
22 } finally {
23 await db.cleanup()
24 }
25 })
26}
27const cleanNondet = (res: any) => {
28 if (!res.data?.tables) return res
29 const tables = res.data.tables.map(({ id, ...rest }: any) => rest)
30 return { ...res, data: { ...res.data, tables } }
31}
32
33withTestDatabase('retrieve, create, update, delete', async ({ executeQuery }) => {
34 // Create publication
35 const { sql: createSql } = pgMeta.publications.create({
36 name: 'a',
37 publish_insert: true,
38 publish_update: true,
39 publish_delete: true,
40 publish_truncate: false,
41 tables: ['users'],
42 })
43 await executeQuery(createSql)
44
45 // Retrieve publication
46 const { sql: retrieveSql, zod: retrieveZod } = pgMeta.publications.retrieve({ name: 'a' })
47 const res = retrieveZod.parse((await executeQuery(retrieveSql))[0])
48 expect(cleanNondet({ data: res })).toMatchInlineSnapshot(
49 { data: { id: expect.any(Number) } },
50 `
51 {
52 "data": {
53 "id": Any<Number>,
54 "name": "a",
55 "owner": "postgres",
56 "publish_delete": true,
57 "publish_insert": true,
58 "publish_truncate": false,
59 "publish_update": true,
60 "tables": [
61 {
62 "name": "users",
63 "schema": "public",
64 },
65 ],
66 },
67 }
68 `
69 )
70
71 // Update publication
72 const { sql: updateSql } = pgMeta.publications.update(res!.id, {
73 name: 'b',
74 publish_insert: false,
75 tables: [],
76 })
77 await executeQuery(updateSql)
78
79 // Verify update
80 const { sql: retrieveUpdatedSql, zod: retrieveUpdatedZod } = pgMeta.publications.retrieve({
81 name: 'b',
82 })
83 const updatedRes = retrieveUpdatedZod.parse((await executeQuery(retrieveUpdatedSql))[0])
84 expect(cleanNondet({ data: updatedRes })).toMatchInlineSnapshot(
85 { data: { id: expect.any(Number) } },
86 `
87 {
88 "data": {
89 "id": Any<Number>,
90 "name": "b",
91 "owner": "postgres",
92 "publish_delete": true,
93 "publish_insert": false,
94 "publish_truncate": false,
95 "publish_update": true,
96 "tables": [],
97 },
98 }
99 `
100 )
101
102 // Remove publication
103 const { sql: removeSql } = pgMeta.publications.remove(updatedRes!)
104 await executeQuery(removeSql)
105
106 // Verify removal
107 const { sql: verifyRemoveSql } = pgMeta.publications.retrieve({ id: updatedRes!.id })
108 const finalRes = await executeQuery(verifyRemoveSql)
109 expect(finalRes).toHaveLength(0)
110})
111
112withTestDatabase('tables with uppercase', async ({ executeQuery }) => {
113 // Create table with uppercase name
114 await executeQuery(`
115 CREATE TABLE public."T" (
116 id SERIAL PRIMARY KEY
117 );
118 `)
119
120 // Create publication
121 const { sql: createSql } = pgMeta.publications.create({
122 name: 'pub',
123 tables: ['T'],
124 })
125 await executeQuery(createSql)
126
127 // Verify creation
128 const { sql: retrieveSql, zod: retrieveZod } = pgMeta.publications.retrieve({ name: 'pub' })
129 let res = retrieveZod.parse((await executeQuery(retrieveSql))[0])
130 expect(cleanNondet({ data: res })).toMatchInlineSnapshot(
131 { data: { id: expect.any(Number) } },
132 `
133 {
134 "data": {
135 "id": Any<Number>,
136 "name": "pub",
137 "owner": "postgres",
138 "publish_delete": false,
139 "publish_insert": false,
140 "publish_truncate": false,
141 "publish_update": false,
142 "tables": [
143 {
144 "name": "T",
145 "schema": "public",
146 },
147 ],
148 },
149 }
150 `
151 )
152
153 // Update publication
154 const { sql: updateSql } = pgMeta.publications.update(res!.id, {
155 tables: ['T'],
156 })
157 await executeQuery(updateSql)
158
159 // Verify update
160 const { sql: retrieveUpdatedSql, zod: retrieveUpdatedZod } = pgMeta.publications.retrieve({
161 name: 'pub',
162 })
163 res = retrieveUpdatedZod.parse((await executeQuery(retrieveUpdatedSql))[0])
164 expect(cleanNondet({ data: res })).toMatchInlineSnapshot(
165 { data: { id: expect.any(Number) } },
166 `
167 {
168 "data": {
169 "id": Any<Number>,
170 "name": "pub",
171 "owner": "postgres",
172 "publish_delete": false,
173 "publish_insert": false,
174 "publish_truncate": false,
175 "publish_update": false,
176 "tables": [
177 {
178 "name": "T",
179 "schema": "public",
180 },
181 ],
182 },
183 }
184 `
185 )
186
187 // Remove publication
188 const { sql: removeSql } = pgMeta.publications.remove(res!)
189 await executeQuery(removeSql)
190})
191
192withTestDatabase('FOR ALL TABLES', async ({ executeQuery }) => {
193 // Create publication
194 const { sql: createSql } = pgMeta.publications.create({
195 name: 'for_all',
196 publish_insert: true,
197 publish_update: true,
198 publish_delete: true,
199 publish_truncate: false,
200 })
201 await executeQuery(createSql)
202
203 // Retrieve and verify
204 const { sql: retrieveSql, zod: retrieveZod } = pgMeta.publications.retrieve({ name: 'for_all' })
205 const res = retrieveZod.parse((await executeQuery(retrieveSql))[0])
206 expect(cleanNondet({ data: res })).toMatchInlineSnapshot(
207 { data: { id: expect.any(Number) } },
208 `
209 {
210 "data": {
211 "id": Any<Number>,
212 "name": "for_all",
213 "owner": "postgres",
214 "publish_delete": true,
215 "publish_insert": true,
216 "publish_truncate": false,
217 "publish_update": true,
218 "tables": null,
219 },
220 }
221 `
222 )
223
224 // Remove publication
225 const { sql: removeSql } = pgMeta.publications.remove(res!)
226 await executeQuery(removeSql)
227})
228
229withTestDatabase('update no tables -> all tables', async ({ executeQuery }) => {
230 // Create publication
231 const { sql: createSql } = pgMeta.publications.create({
232 name: 'pub',
233 tables: [],
234 })
235 await executeQuery(createSql)
236
237 // Retrieve created publication
238 const { sql: retrieveSql, zod: retrieveZod } = pgMeta.publications.retrieve({ name: 'pub' })
239 const res = retrieveZod.parse((await executeQuery(retrieveSql))[0])
240
241 // Update publication
242 const { sql: updateSql } = pgMeta.publications.update(res!.id, {
243 tables: null,
244 })
245 await executeQuery(updateSql)
246
247 // Verify update
248 const { sql: verifyRetrieveSql, zod: verifyRetrieveZod } = pgMeta.publications.retrieve({
249 name: 'pub',
250 })
251 const updatedRes = verifyRetrieveZod.parse((await executeQuery(verifyRetrieveSql))[0])
252 expect(cleanNondet({ data: updatedRes })).toMatchInlineSnapshot(
253 { data: { id: expect.any(Number) } },
254 `
255 {
256 "data": {
257 "id": Any<Number>,
258 "name": "pub",
259 "owner": "postgres",
260 "publish_delete": false,
261 "publish_insert": false,
262 "publish_truncate": false,
263 "publish_update": false,
264 "tables": null,
265 },
266 }
267 `
268 )
269
270 // Remove publication
271 const { sql: removeSql } = pgMeta.publications.remove(updatedRes!)
272 await executeQuery(removeSql)
273})
274
275withTestDatabase('update all tables -> no tables', async ({ executeQuery }) => {
276 // Create publication
277 const { sql: createSql } = pgMeta.publications.create({
278 name: 'pub',
279 tables: null,
280 })
281 await executeQuery(createSql)
282
283 // Retrieve created publication
284 const { sql: retrieveSql, zod: retrieveZod } = pgMeta.publications.retrieve({ name: 'pub' })
285 const res = retrieveZod.parse((await executeQuery(retrieveSql))[0])
286
287 // Update publication
288 const { sql: updateSql } = pgMeta.publications.update(res!.id, {
289 tables: [],
290 })
291 await executeQuery(updateSql)
292
293 // Verify update
294 const { sql: verifyRetrieveSql, zod: verifyRetrieveZod } = pgMeta.publications.retrieve({
295 name: 'pub',
296 })
297 const updatedRes = verifyRetrieveZod.parse((await executeQuery(verifyRetrieveSql))[0])
298 expect(cleanNondet({ data: updatedRes })).toMatchInlineSnapshot(
299 { data: { id: expect.any(Number) } },
300 `
301 {
302 "data": {
303 "id": Any<Number>,
304 "name": "pub",
305 "owner": "postgres",
306 "publish_delete": false,
307 "publish_insert": false,
308 "publish_truncate": false,
309 "publish_update": false,
310 "tables": [],
311 },
312 }
313 `
314 )
315
316 // Remove publication
317 const { sql: removeSql } = pgMeta.publications.remove(updatedRes!)
318 await executeQuery(removeSql)
319})