Skip to content

Commit 913e879

Browse files
author
georgiy.rusanov
committed
chore: added more tests
1 parent ab92387 commit 913e879

File tree

7 files changed

+892
-0
lines changed

7 files changed

+892
-0
lines changed

test/extensions.test.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,115 @@ describe('server/routes/extensions', () => {
3030
expect(Array.isArray(JSON.parse(response.body))).toBe(true)
3131
await app.close()
3232
})
33+
34+
test('should return 404 for non-existent extension', async () => {
35+
const app = build()
36+
const response = await app.inject({
37+
method: 'GET',
38+
url: '/extensions/non-existent-extension',
39+
headers: {
40+
pg: TEST_CONNECTION_STRING,
41+
},
42+
})
43+
expect(response.statusCode).toBe(404)
44+
await app.close()
45+
})
46+
47+
test('should create extension, retrieve, update, delete', async () => {
48+
const app = build()
49+
const response = await app.inject({
50+
method: 'POST',
51+
url: '/extensions',
52+
headers: {
53+
pg: TEST_CONNECTION_STRING,
54+
},
55+
payload: { name: 'pgcrypto', version: '1.3' },
56+
})
57+
expect(response.statusCode).toBe(200)
58+
expect(response.json()).toMatchInlineSnapshot(`
59+
{
60+
"comment": "cryptographic functions",
61+
"default_version": "1.3",
62+
"installed_version": "1.3",
63+
"name": "pgcrypto",
64+
"schema": "public",
65+
}
66+
`)
67+
68+
const retrieveResponse = await app.inject({
69+
method: 'GET',
70+
url: '/extensions/pgcrypto',
71+
headers: {
72+
pg: TEST_CONNECTION_STRING,
73+
},
74+
})
75+
expect(retrieveResponse.statusCode).toBe(200)
76+
expect(retrieveResponse.json()).toMatchInlineSnapshot(`
77+
{
78+
"comment": "cryptographic functions",
79+
"default_version": "1.3",
80+
"installed_version": "1.3",
81+
"name": "pgcrypto",
82+
"schema": "public",
83+
}
84+
`)
85+
86+
const updateResponse = await app.inject({
87+
method: 'PATCH',
88+
url: '/extensions/pgcrypto',
89+
headers: {
90+
pg: TEST_CONNECTION_STRING,
91+
},
92+
payload: { schema: 'public' },
93+
})
94+
expect(updateResponse.statusCode).toBe(200)
95+
expect(updateResponse.json()).toMatchInlineSnapshot(`
96+
{
97+
"comment": "cryptographic functions",
98+
"default_version": "1.3",
99+
"installed_version": "1.3",
100+
"name": "pgcrypto",
101+
"schema": "public",
102+
}
103+
`)
104+
105+
const deleteResponse = await app.inject({
106+
method: 'DELETE',
107+
url: '/extensions/pgcrypto',
108+
headers: {
109+
pg: TEST_CONNECTION_STRING,
110+
},
111+
})
112+
expect(deleteResponse.statusCode).toBe(200)
113+
expect(deleteResponse.json()).toMatchInlineSnapshot(`
114+
{
115+
"comment": "cryptographic functions",
116+
"default_version": "1.3",
117+
"installed_version": "1.3",
118+
"name": "pgcrypto",
119+
"schema": "public",
120+
}
121+
`)
122+
123+
await app.close()
124+
})
125+
126+
test('should return 400 for invalid extension name', async () => {
127+
const app = build()
128+
const response = await app.inject({
129+
method: 'POST',
130+
url: '/extensions',
131+
headers: {
132+
pg: TEST_CONNECTION_STRING,
133+
},
134+
payload: { name: 'invalid-extension', version: '1.3' },
135+
})
136+
expect(response.statusCode).toBe(400)
137+
expect(response.json()).toMatchInlineSnapshot(`
138+
{
139+
"error": "could not open extension control file "/usr/share/postgresql/14/extension/invalid-extension.control": No such file or directory",
140+
}
141+
`)
142+
await app.close()
143+
})
33144
})

test/functions.test.ts

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,188 @@ describe('server/routes/functions', () => {
3030
expect(Array.isArray(JSON.parse(response.body))).toBe(true)
3131
await app.close()
3232
})
33+
34+
test('should return 404 for non-existent function', async () => {
35+
const app = build()
36+
const response = await app.inject({
37+
method: 'GET',
38+
url: '/functions/non-existent-function',
39+
headers: {
40+
pg: TEST_CONNECTION_STRING,
41+
},
42+
})
43+
expect(response.statusCode).toBe(404)
44+
await app.close()
45+
})
46+
47+
test('should create function, retrieve, update, delete', async () => {
48+
const app = build()
49+
const response = await app.inject({
50+
method: 'POST',
51+
url: '/functions',
52+
headers: {
53+
pg: TEST_CONNECTION_STRING,
54+
},
55+
payload: {
56+
name: 'test_function',
57+
schema: 'public',
58+
language: 'plpgsql',
59+
definition: 'BEGIN RETURN 42; END;',
60+
return_type: 'integer',
61+
},
62+
})
63+
expect(response.statusCode).toBe(200)
64+
expect(response.json()).toMatchInlineSnapshot(`
65+
{
66+
"args": [],
67+
"argument_types": "",
68+
"behavior": "VOLATILE",
69+
"complete_statement": "CREATE OR REPLACE FUNCTION public.test_function()
70+
RETURNS integer
71+
LANGUAGE plpgsql
72+
AS $function$BEGIN RETURN 42; END;$function$
73+
",
74+
"config_params": null,
75+
"definition": "BEGIN RETURN 42; END;",
76+
"id": expect.any(Number),
77+
"identity_argument_types": "",
78+
"is_set_returning_function": false,
79+
"language": "plpgsql",
80+
"name": "test_function",
81+
"return_type": "integer",
82+
"return_type_id": 23,
83+
"return_type_relation_id": null,
84+
"schema": "public",
85+
"security_definer": false,
86+
}
87+
`)
88+
89+
const { id } = response.json()
90+
91+
const retrieveResponse = await app.inject({
92+
method: 'GET',
93+
url: `/functions/${id}`,
94+
headers: {
95+
pg: TEST_CONNECTION_STRING,
96+
},
97+
})
98+
expect(retrieveResponse.statusCode).toBe(200)
99+
expect(retrieveResponse.json()).toMatchInlineSnapshot(`
100+
{
101+
"args": [],
102+
"argument_types": "",
103+
"behavior": "VOLATILE",
104+
"complete_statement": "CREATE OR REPLACE FUNCTION public.test_function()
105+
RETURNS integer
106+
LANGUAGE plpgsql
107+
AS $function$BEGIN RETURN 42; END;$function$
108+
",
109+
"config_params": null,
110+
"definition": "BEGIN RETURN 42; END;",
111+
"id": ${id},
112+
"identity_argument_types": "",
113+
"is_set_returning_function": false,
114+
"language": "plpgsql",
115+
"name": "test_function",
116+
"return_type": "integer",
117+
"return_type_id": 23,
118+
"return_type_relation_id": null,
119+
"schema": "public",
120+
"security_definer": false,
121+
}
122+
`)
123+
124+
const updateResponse = await app.inject({
125+
method: 'PATCH',
126+
url: `/functions/${id}`,
127+
headers: {
128+
pg: TEST_CONNECTION_STRING,
129+
},
130+
payload: {
131+
name: 'test_function',
132+
schema: 'public',
133+
language: 'plpgsql',
134+
definition: 'BEGIN RETURN 50; END;',
135+
return_type: 'integer',
136+
},
137+
})
138+
expect(updateResponse.statusCode).toBe(200)
139+
expect(updateResponse.json()).toMatchInlineSnapshot(`
140+
{
141+
"args": [],
142+
"argument_types": "",
143+
"behavior": "VOLATILE",
144+
"complete_statement": "CREATE OR REPLACE FUNCTION public.test_function()
145+
RETURNS integer
146+
LANGUAGE plpgsql
147+
AS $function$BEGIN RETURN 50; END;$function$
148+
",
149+
"config_params": null,
150+
"definition": "BEGIN RETURN 50; END;",
151+
"id": ${id},
152+
"identity_argument_types": "",
153+
"is_set_returning_function": false,
154+
"language": "plpgsql",
155+
"name": "test_function",
156+
"return_type": "integer",
157+
"return_type_id": 23,
158+
"return_type_relation_id": null,
159+
"schema": "public",
160+
"security_definer": false,
161+
}
162+
`)
163+
164+
const deleteResponse = await app.inject({
165+
method: 'DELETE',
166+
url: `/functions/${id}`,
167+
headers: {
168+
pg: TEST_CONNECTION_STRING,
169+
},
170+
})
171+
expect(deleteResponse.statusCode).toBe(200)
172+
expect(deleteResponse.json()).toMatchInlineSnapshot(`
173+
{
174+
"args": [],
175+
"argument_types": "",
176+
"behavior": "VOLATILE",
177+
"complete_statement": "CREATE OR REPLACE FUNCTION public.test_function()
178+
RETURNS integer
179+
LANGUAGE plpgsql
180+
AS $function$BEGIN RETURN 50; END;$function$
181+
",
182+
"config_params": null,
183+
"definition": "BEGIN RETURN 50; END;",
184+
"id": ${id},
185+
"identity_argument_types": "",
186+
"is_set_returning_function": false,
187+
"language": "plpgsql",
188+
"name": "test_function",
189+
"return_type": "integer",
190+
"return_type_id": 23,
191+
"return_type_relation_id": null,
192+
"schema": "public",
193+
"security_definer": false,
194+
}
195+
`)
196+
})
197+
198+
test('should return 400 for invalid payload', async () => {
199+
const app = build()
200+
const response = await app.inject({
201+
method: 'POST',
202+
url: '/functions',
203+
headers: {
204+
pg: TEST_CONNECTION_STRING,
205+
},
206+
payload: {
207+
name: 'test_function12',
208+
},
209+
})
210+
expect(response.statusCode).toBe(400)
211+
expect(response.json()).toMatchInlineSnapshot(`
212+
{
213+
"error": "syntax error at or near "NULL"",
214+
}
215+
`)
216+
})
33217
})

0 commit comments

Comments
 (0)