Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.

Commit 583b602

Browse files
committed
chore: split basic.test.ts into smaller ones
1 parent 08ebfa2 commit 583b602

17 files changed

+3248
-2262
lines changed

test/basic.test.ts

Lines changed: 0 additions & 2238 deletions
This file was deleted.

test/client-configuration.test.ts

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import { PostgrestClient } from '../src/index'
2+
import { Database } from './types.override'
3+
4+
const REST_URL = 'http://localhost:3000'
5+
6+
test('custom fetch function', async () => {
7+
const customFetch = jest.fn().mockImplementation(() =>
8+
Promise.resolve({
9+
ok: true,
10+
status: 200,
11+
statusText: 'OK',
12+
text: () => Promise.resolve('[]'),
13+
})
14+
)
15+
16+
const postgrestWithCustomFetch = new PostgrestClient<Database>(REST_URL, {
17+
fetch: customFetch,
18+
})
19+
20+
await postgrestWithCustomFetch.from('users').select()
21+
22+
expect(customFetch).toHaveBeenCalledWith(
23+
expect.stringContaining(REST_URL),
24+
expect.objectContaining({
25+
method: 'GET',
26+
headers: expect.any(Object),
27+
})
28+
)
29+
})
30+
31+
test('handles undefined global fetch', async () => {
32+
// Store original fetch
33+
const originalFetch = globalThis.fetch
34+
// Delete global fetch to simulate environments where it's undefined
35+
delete (globalThis as any).fetch
36+
37+
try {
38+
const postgrestClient = new PostgrestClient<Database>(REST_URL)
39+
const result = await postgrestClient.from('users').select()
40+
expect(result).toMatchInlineSnapshot(`
41+
Object {
42+
"count": null,
43+
"data": Array [
44+
Object {
45+
"age_range": "[1,2)",
46+
"catchphrase": "'cat' 'fat'",
47+
"data": null,
48+
"status": "ONLINE",
49+
"username": "supabot",
50+
},
51+
Object {
52+
"age_range": "[25,35)",
53+
"catchphrase": "'bat' 'cat'",
54+
"data": null,
55+
"status": "OFFLINE",
56+
"username": "kiwicopple",
57+
},
58+
Object {
59+
"age_range": "[25,35)",
60+
"catchphrase": "'bat' 'rat'",
61+
"data": null,
62+
"status": "ONLINE",
63+
"username": "awailas",
64+
},
65+
Object {
66+
"age_range": "[20,30)",
67+
"catchphrase": "'fat' 'rat'",
68+
"data": null,
69+
"status": "ONLINE",
70+
"username": "dragarcia",
71+
},
72+
Object {
73+
"age_range": "[20,30)",
74+
"catchphrase": "'json' 'test'",
75+
"data": Object {
76+
"foo": Object {
77+
"bar": Object {
78+
"nested": "value",
79+
},
80+
"baz": "string value",
81+
},
82+
},
83+
"status": "ONLINE",
84+
"username": "jsonuser",
85+
},
86+
],
87+
"error": null,
88+
"status": 200,
89+
"statusText": "OK",
90+
}
91+
`)
92+
// Test passes if we reach here without errors, as it means nodeFetch was used
93+
} finally {
94+
// Restore original fetch
95+
globalThis.fetch = originalFetch
96+
}
97+
})
98+
99+
test('handles array error with 404 status', async () => {
100+
// Mock the fetch response to return an array error with 404
101+
const customFetch = jest.fn().mockImplementation(() =>
102+
Promise.resolve({
103+
ok: false,
104+
status: 404,
105+
statusText: 'Not Found',
106+
text: () => Promise.resolve('[]'),
107+
})
108+
)
109+
110+
const postgrestWithCustomFetch = new PostgrestClient<Database>(REST_URL, {
111+
fetch: customFetch,
112+
})
113+
114+
const res = await postgrestWithCustomFetch.from('users').select()
115+
116+
expect(res).toMatchInlineSnapshot(`
117+
Object {
118+
"count": null,
119+
"data": Array [],
120+
"error": null,
121+
"status": 200,
122+
"statusText": "OK",
123+
}
124+
`)
125+
})
126+
127+
test('handles empty body with 404 status', async () => {
128+
// Mock the fetch response to return an empty body with 404
129+
const customFetch = jest.fn().mockImplementation(() =>
130+
Promise.resolve({
131+
ok: false,
132+
status: 404,
133+
statusText: 'Not Found',
134+
text: () => Promise.resolve(''),
135+
})
136+
)
137+
138+
const postgrestWithCustomFetch = new PostgrestClient<Database>(REST_URL, {
139+
fetch: customFetch,
140+
})
141+
142+
const res = await postgrestWithCustomFetch.from('users').select()
143+
144+
expect(res).toMatchInlineSnapshot(`
145+
Object {
146+
"count": null,
147+
"data": null,
148+
"error": null,
149+
"status": 204,
150+
"statusText": "No Content",
151+
}
152+
`)
153+
})
154+
155+
test('maybeSingle handles zero rows error', async () => {
156+
const customFetch = jest.fn().mockImplementation(() =>
157+
Promise.resolve({
158+
ok: false,
159+
status: 406,
160+
statusText: 'Not Acceptable',
161+
text: () =>
162+
Promise.resolve(
163+
JSON.stringify({
164+
code: 'PGRST116',
165+
details: '0 rows',
166+
hint: null,
167+
message: 'JSON object requested, multiple (or no) rows returned',
168+
})
169+
),
170+
})
171+
)
172+
173+
const postgrestWithCustomFetch = new PostgrestClient<Database>(REST_URL, {
174+
fetch: customFetch,
175+
})
176+
177+
const res = await postgrestWithCustomFetch.from('users').select().maybeSingle()
178+
179+
expect(res).toMatchInlineSnapshot(`
180+
Object {
181+
"count": null,
182+
"data": null,
183+
"error": null,
184+
"status": 200,
185+
"statusText": "OK",
186+
}
187+
`)
188+
})
189+
190+
test('connection error w/o throwing', async () => {
191+
const postgrest = new PostgrestClient<Database>('http://foo.invalid')
192+
let isErrorCaught = false
193+
await postgrest
194+
.from('users')
195+
.select()
196+
.then(undefined, () => {
197+
isErrorCaught = true
198+
})
199+
expect(isErrorCaught).toBe(false)
200+
})
201+
202+
test('connection error w/ throwOnError', async () => {
203+
const postgrest = new PostgrestClient<Database>('http://foo.invalid')
204+
let isErrorCaught = false
205+
await postgrest
206+
.from('users')
207+
.select()
208+
.throwOnError()
209+
.then(undefined, () => {
210+
isErrorCaught = true
211+
})
212+
expect(isErrorCaught).toBe(true)
213+
})

test/client-headers.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { PostgrestClient } from '../src/index'
2+
import { Database } from './types.override'
3+
4+
const REST_URL = 'http://localhost:3000'
5+
const postgrest = new PostgrestClient<Database>(REST_URL)
6+
7+
test('custom headers', async () => {
8+
const postgrest = new PostgrestClient<Database>(REST_URL, { headers: { apikey: 'foo' } })
9+
expect((postgrest.from('users').select() as any).headers.get('apikey')).toEqual('foo')
10+
})
11+
12+
test('custom headers on a per-call basis', async () => {
13+
const postgrest1 = new PostgrestClient<Database>(REST_URL, { headers: { apikey: 'foo' } })
14+
const postgrest2 = postgrest1.rpc('void_func').setHeader('apikey', 'bar')
15+
// Original client object isn't affected
16+
expect((postgrest1.from('users').select() as any).headers.get('apikey')).toEqual('foo')
17+
// Derived client object uses new header value
18+
expect((postgrest2 as any).headers.get('apikey')).toEqual('bar')
19+
})
20+
21+
describe('custom prefer headers with ', () => {
22+
test('insert', async () => {
23+
const postgrest = new PostgrestClient<Database>(REST_URL, {
24+
headers: { Prefer: 'tx=rollback' },
25+
})
26+
const postgrestFilterBuilder = postgrest
27+
.from('users')
28+
.insert({ username: 'dragarcia' })
29+
.select() as any
30+
expect(postgrestFilterBuilder.headers.get('Prefer')).toContain('tx=rollback')
31+
expect(postgrestFilterBuilder.headers.get('Prefer')).toContain('return=')
32+
})
33+
test('update', async () => {
34+
const postgrest = new PostgrestClient<Database>(REST_URL, {
35+
headers: { Prefer: 'tx=rollback' },
36+
})
37+
const postgrestFilterBuilder = postgrest
38+
.from('users')
39+
.update({ username: 'dragarcia' })
40+
.select() as any
41+
expect(postgrestFilterBuilder.headers.get('Prefer')).toContain('tx=rollback')
42+
expect(postgrestFilterBuilder.headers.get('Prefer')).toContain('return=')
43+
})
44+
test('upsert', async () => {
45+
const postgrest = new PostgrestClient<Database>(REST_URL, {
46+
headers: { Prefer: 'tx=rollback' },
47+
})
48+
const postgrestFilterBuilder = postgrest
49+
.from('users')
50+
.upsert({ username: 'dragarcia' })
51+
.select() as any
52+
expect(postgrestFilterBuilder.headers.get('Prefer')).toContain('tx=rollback')
53+
expect(postgrestFilterBuilder.headers.get('Prefer')).toContain('return=')
54+
})
55+
test('delete', async () => {
56+
const postgrest = new PostgrestClient<Database>(REST_URL, {
57+
headers: { Prefer: 'tx=rollback' },
58+
})
59+
const postgrestFilterBuilder = postgrest.from('users').delete().select() as any
60+
expect(postgrestFilterBuilder.headers.get('Prefer')).toContain('tx=rollback')
61+
expect(postgrestFilterBuilder.headers.get('Prefer')).toContain('return=')
62+
})
63+
})
64+
65+
test("don't mutate PostgrestClient.headers", async () => {
66+
await postgrest.from('users').select().limit(1).single()
67+
const { error } = await postgrest.from('users').select()
68+
expect(error).toMatchInlineSnapshot(`null`)
69+
})

test/delete-operations.test.ts

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { PostgrestClient } from '../src/index'
2+
import { Database } from './types.override'
3+
4+
const REST_URL = 'http://localhost:3000'
5+
const postgrest = new PostgrestClient<Database>(REST_URL)
6+
7+
test('basic delete', async () => {
8+
let res = await postgrest.from('messages').delete().eq('message', 'foo').select()
9+
expect(res).toMatchInlineSnapshot(`
10+
Object {
11+
"count": null,
12+
"data": Array [],
13+
"error": null,
14+
"status": 200,
15+
"statusText": "OK",
16+
}
17+
`)
18+
19+
res = await postgrest.from('messages').select()
20+
expect(res).toMatchInlineSnapshot(`
21+
Object {
22+
"count": null,
23+
"data": Array [
24+
Object {
25+
"channel_id": 1,
26+
"data": null,
27+
"id": 1,
28+
"message": "Hello World 👋",
29+
"username": "supabot",
30+
},
31+
Object {
32+
"channel_id": 2,
33+
"data": null,
34+
"id": 2,
35+
"message": "Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.",
36+
"username": "supabot",
37+
},
38+
Object {
39+
"channel_id": 3,
40+
"data": null,
41+
"id": 3,
42+
"message": "Some message on channel wihtout details",
43+
"username": "supabot",
44+
},
45+
Object {
46+
"channel_id": 3,
47+
"data": null,
48+
"id": 4,
49+
"message": "Some message on channel wihtout details",
50+
"username": "supabot",
51+
},
52+
],
53+
"error": null,
54+
"status": 200,
55+
"statusText": "OK",
56+
}
57+
`)
58+
})
59+
60+
test("basic delete count: 'exact'", async () => {
61+
let res = await postgrest
62+
.from('messages')
63+
.delete({ count: 'exact' })
64+
.eq('message', 'foo')
65+
.select()
66+
expect(res).toMatchInlineSnapshot(`
67+
Object {
68+
"count": 0,
69+
"data": Array [],
70+
"error": null,
71+
"status": 200,
72+
"statusText": "OK",
73+
}
74+
`)
75+
76+
res = await postgrest.from('messages').select()
77+
expect(res).toMatchInlineSnapshot(`
78+
Object {
79+
"count": null,
80+
"data": Array [
81+
Object {
82+
"channel_id": 1,
83+
"data": null,
84+
"id": 1,
85+
"message": "Hello World 👋",
86+
"username": "supabot",
87+
},
88+
Object {
89+
"channel_id": 2,
90+
"data": null,
91+
"id": 2,
92+
"message": "Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.",
93+
"username": "supabot",
94+
},
95+
Object {
96+
"channel_id": 3,
97+
"data": null,
98+
"id": 3,
99+
"message": "Some message on channel wihtout details",
100+
"username": "supabot",
101+
},
102+
Object {
103+
"channel_id": 3,
104+
"data": null,
105+
"id": 4,
106+
"message": "Some message on channel wihtout details",
107+
"username": "supabot",
108+
},
109+
],
110+
"error": null,
111+
"status": 200,
112+
"statusText": "OK",
113+
}
114+
`)
115+
})

0 commit comments

Comments
 (0)