Skip to content

Commit 9ad457e

Browse files
authored
Merge branch 'avallete/fix-add-returns-to-builder' into avallete/feat-add-overrideTypes-method
2 parents 5f24f39 + e84c452 commit 9ad457e

File tree

4 files changed

+223
-1
lines changed

4 files changed

+223
-1
lines changed

Diff for: jest.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module.exports = {
22
preset: 'ts-jest',
33
testEnvironment: 'node',
4+
collectCoverageFrom: ['src/**/*'],
45
}

Diff for: src/PostgrestBuilder.ts

+1
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ export default abstract class PostgrestBuilder<Result, ThrowOnError extends bool
224224
* @deprecated Use overrideTypes<yourType, { merge: false }>() method at the end of your call chain instead
225225
*/
226226
returns<NewResult>(): PostgrestBuilder<CheckMatchingArrayTypes<Result, NewResult>, ThrowOnError> {
227+
/* istanbul ignore next */
227228
return this as unknown as PostgrestBuilder<
228229
CheckMatchingArrayTypes<Result, NewResult>,
229230
ThrowOnError

Diff for: src/PostgrestTransformBuilder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ export default class PostgrestTransformBuilder<
307307
* Override the type of the returned `data`.
308308
*
309309
* @typeParam NewResult - The new result type to override with
310-
* @deprecated Use overrideTypes<yourType, { partial: false }>() method at the end of your call chain instead
310+
* @deprecated Use overrideTypes<yourType, { merge: false }>() method at the end of your call chain instead
311311
*/
312312
returns<NewResult>(): PostgrestTransformBuilder<
313313
Schema,

Diff for: test/basic.ts

+220
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,42 @@ test('basic select overrideTypes from builder', async () => {
161161
"status": 200,
162162
"statusText": "OK",
163163
}
164+
`);
165+
})
166+
167+
test('basic select with maybeSingle yielding more than one result', async () => {
168+
const res = await postgrest.from('users').select().maybeSingle()
169+
expect(res).toMatchInlineSnapshot(`
170+
Object {
171+
"count": null,
172+
"data": null,
173+
"error": Object {
174+
"code": "PGRST116",
175+
"details": "Results contain 5 rows, application/vnd.pgrst.object+json requires 1 row",
176+
"hint": null,
177+
"message": "JSON object requested, multiple (or no) rows returned",
178+
},
179+
"status": 406,
180+
"statusText": "Not Acceptable",
181+
}
182+
`)
183+
})
184+
185+
test('basic select with single yielding more than one result', async () => {
186+
const res = await postgrest.from('users').select().single()
187+
expect(res).toMatchInlineSnapshot(`
188+
Object {
189+
"count": null,
190+
"data": null,
191+
"error": Object {
192+
"code": "PGRST116",
193+
"details": "The result contains 5 rows",
194+
"hint": null,
195+
"message": "JSON object requested, multiple (or no) rows returned",
196+
},
197+
"status": 406,
198+
"statusText": "Not Acceptable",
199+
}
164200
`)
165201
})
166202

@@ -2011,3 +2047,187 @@ test('join on 1-1 relation with nullables', async () => {
20112047
}
20122048
`)
20132049
})
2050+
2051+
test('custom fetch function', async () => {
2052+
const customFetch = jest.fn().mockImplementation(() =>
2053+
Promise.resolve({
2054+
ok: true,
2055+
status: 200,
2056+
statusText: 'OK',
2057+
text: () => Promise.resolve('[]'),
2058+
})
2059+
)
2060+
2061+
const postgrestWithCustomFetch = new PostgrestClient<Database>(REST_URL, {
2062+
fetch: customFetch,
2063+
})
2064+
2065+
await postgrestWithCustomFetch.from('users').select()
2066+
2067+
expect(customFetch).toHaveBeenCalledWith(
2068+
expect.stringContaining(REST_URL),
2069+
expect.objectContaining({
2070+
method: 'GET',
2071+
headers: expect.any(Object),
2072+
})
2073+
)
2074+
})
2075+
2076+
test('handles undefined global fetch', async () => {
2077+
// Store original fetch
2078+
const originalFetch = globalThis.fetch
2079+
// Delete global fetch to simulate environments where it's undefined
2080+
delete (globalThis as any).fetch
2081+
2082+
try {
2083+
const postgrestClient = new PostgrestClient<Database>(REST_URL)
2084+
const result = await postgrestClient.from('users').select()
2085+
expect(result).toMatchInlineSnapshot(`
2086+
Object {
2087+
"count": null,
2088+
"data": Array [
2089+
Object {
2090+
"age_range": "[1,2)",
2091+
"catchphrase": "'cat' 'fat'",
2092+
"data": null,
2093+
"status": "ONLINE",
2094+
"username": "supabot",
2095+
},
2096+
Object {
2097+
"age_range": "[25,35)",
2098+
"catchphrase": "'bat' 'cat'",
2099+
"data": null,
2100+
"status": "OFFLINE",
2101+
"username": "kiwicopple",
2102+
},
2103+
Object {
2104+
"age_range": "[25,35)",
2105+
"catchphrase": "'bat' 'rat'",
2106+
"data": null,
2107+
"status": "ONLINE",
2108+
"username": "awailas",
2109+
},
2110+
Object {
2111+
"age_range": "[20,30)",
2112+
"catchphrase": "'json' 'test'",
2113+
"data": Object {
2114+
"foo": Object {
2115+
"bar": Object {
2116+
"nested": "value",
2117+
},
2118+
"baz": "string value",
2119+
},
2120+
},
2121+
"status": "ONLINE",
2122+
"username": "jsonuser",
2123+
},
2124+
Object {
2125+
"age_range": "[20,30)",
2126+
"catchphrase": "'fat' 'rat'",
2127+
"data": null,
2128+
"status": "ONLINE",
2129+
"username": "dragarcia",
2130+
},
2131+
],
2132+
"error": null,
2133+
"status": 200,
2134+
"statusText": "OK",
2135+
}
2136+
`)
2137+
// Test passes if we reach here without errors, as it means nodeFetch was used
2138+
} finally {
2139+
// Restore original fetch
2140+
globalThis.fetch = originalFetch
2141+
}
2142+
})
2143+
2144+
test('handles array error with 404 status', async () => {
2145+
// Mock the fetch response to return an array error with 404
2146+
const customFetch = jest.fn().mockImplementation(() =>
2147+
Promise.resolve({
2148+
ok: false,
2149+
status: 404,
2150+
statusText: 'Not Found',
2151+
text: () => Promise.resolve('[]'),
2152+
})
2153+
)
2154+
2155+
const postgrestWithCustomFetch = new PostgrestClient<Database>(REST_URL, {
2156+
fetch: customFetch,
2157+
})
2158+
2159+
const res = await postgrestWithCustomFetch.from('users').select()
2160+
2161+
expect(res).toMatchInlineSnapshot(`
2162+
Object {
2163+
"count": null,
2164+
"data": Array [],
2165+
"error": null,
2166+
"status": 200,
2167+
"statusText": "OK",
2168+
}
2169+
`)
2170+
})
2171+
2172+
test('handles empty body with 404 status', async () => {
2173+
// Mock the fetch response to return an empty body with 404
2174+
const customFetch = jest.fn().mockImplementation(() =>
2175+
Promise.resolve({
2176+
ok: false,
2177+
status: 404,
2178+
statusText: 'Not Found',
2179+
text: () => Promise.resolve(''),
2180+
})
2181+
)
2182+
2183+
const postgrestWithCustomFetch = new PostgrestClient<Database>(REST_URL, {
2184+
fetch: customFetch,
2185+
})
2186+
2187+
const res = await postgrestWithCustomFetch.from('users').select()
2188+
2189+
expect(res).toMatchInlineSnapshot(`
2190+
Object {
2191+
"count": null,
2192+
"data": null,
2193+
"error": null,
2194+
"status": 204,
2195+
"statusText": "No Content",
2196+
}
2197+
`)
2198+
})
2199+
2200+
test('maybeSingle handles zero rows error', async () => {
2201+
const customFetch = jest.fn().mockImplementation(() =>
2202+
Promise.resolve({
2203+
ok: false,
2204+
status: 406,
2205+
statusText: 'Not Acceptable',
2206+
text: () =>
2207+
Promise.resolve(
2208+
JSON.stringify({
2209+
code: 'PGRST116',
2210+
details: '0 rows',
2211+
hint: null,
2212+
message: 'JSON object requested, multiple (or no) rows returned',
2213+
})
2214+
),
2215+
})
2216+
)
2217+
2218+
const postgrestWithCustomFetch = new PostgrestClient<Database>(REST_URL, {
2219+
fetch: customFetch,
2220+
})
2221+
2222+
const res = await postgrestWithCustomFetch.from('users').select().maybeSingle()
2223+
2224+
expect(res).toMatchInlineSnapshot(`
2225+
Object {
2226+
"count": null,
2227+
"data": null,
2228+
"error": null,
2229+
"status": 200,
2230+
"statusText": "OK",
2231+
}
2232+
`)
2233+
})

0 commit comments

Comments
 (0)