Skip to content

Commit

Permalink
chore: add more runtime tests coverage for selection
Browse files Browse the repository at this point in the history
create tests cases to assert postgrest runtime behavior across large
typology of queries. Prepare for future testing against result infered types
  • Loading branch information
avallete committed Sep 27, 2024
1 parent 5ea6d90 commit d81f8fa
Show file tree
Hide file tree
Showing 3 changed files with 1,720 additions and 168 deletions.
171 changes: 3 additions & 168 deletions test/index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { expectError, expectType } from 'tsd'
import { PostgrestClient, PostgrestSingleResponse } from '../src/index'
import { SelectQueryError } from '../src/select-query-parser'
import { PostgrestClient } from '../src/index'
import { Prettify } from '../src/types'
import { Database, Json } from './types'

Expand Down Expand Up @@ -65,7 +64,7 @@ const postgrest = new PostgrestClient<Database>(REST_URL)
throw new Error(error.message)
}
expectType<{ message: string | null; status: Database['public']['Enums']['user_status'] | null }>(
data
data,
)
}

Expand All @@ -76,19 +75,10 @@ const postgrest = new PostgrestClient<Database>(REST_URL)
throw new Error(error.message)
}
expectType<Prettify<{ message: string | null } & Database['public']['Tables']['users']['Row']>>(
data
data,
)
}

// embedded resource with no fields
{
const { data, error } = await postgrest.from('messages').select('message, users()').single()
if (error) {
throw new Error(error.message)
}
expectType<{ message: string | null }>(data)
}

// `count` in embedded resource
{
const { data, error } = await postgrest.from('messages').select('message, users(count)').single()
Expand All @@ -113,25 +103,6 @@ const postgrest = new PostgrestClient<Database>(REST_URL)
expectType<string>(data.baz)
}

// typecasting and aggregate functions
{
const { data, error } = await postgrest
.from('messages')
.select(
'message, users.count(), casted_message:message::int4, casted_count:users.count()::text'
)
.single()
if (error) {
throw new Error(error.message)
}
expectType<{
message: string | null
count: number
casted_message: number
casted_count: string
}>(data)
}

// rpc return type
{
const { data, error } = await postgrest.rpc('get_status')
Expand All @@ -141,62 +112,6 @@ const postgrest = new PostgrestClient<Database>(REST_URL)
expectType<'ONLINE' | 'OFFLINE'>(data)
}

// many-to-one relationship
{
const { data: message, error } = await postgrest.from('messages').select('user:users(*)').single()
if (error) {
throw new Error(error.message)
}
expectType<Database['public']['Tables']['users']['Row'] | null>(message.user)
}

// !inner relationship
{
const { data: message, error } = await postgrest
.from('messages')
.select('channels!inner(*, channel_details!inner(*))')
.single()
if (error) {
throw new Error(error.message)
}
type ExpectedType = Prettify<
Database['public']['Tables']['channels']['Row'] & {
channel_details: Database['public']['Tables']['channel_details']['Row']
}
>

expectType<ExpectedType>(message.channels)
}

// one-to-many relationship
{
const { data: user, error } = await postgrest.from('users').select('messages(*)').single()
if (error) {
throw new Error(error.message)
}
expectType<Database['public']['Tables']['messages']['Row'][]>(user.messages)
}

// referencing missing column
{
const res = await postgrest.from('users').select('username, dat')
expectType<PostgrestSingleResponse<SelectQueryError<`Referencing missing column \`dat\``>[]>>(res)
}

// one-to-one relationship
{
const { data: channels, error } = await postgrest
.from('channels')
.select('channel_details(*)')
.single()
if (error) {
throw new Error(error.message)
}
expectType<Database['public']['Tables']['channel_details']['Row'] | null>(
channels.channel_details
)
}

// PostgrestBuilder's children retains class when using inherited methods
{
const x = postgrest.from('channels').select()
Expand All @@ -205,83 +120,3 @@ const postgrest = new PostgrestClient<Database>(REST_URL)
expectType<typeof x>(y)
expectType<typeof x>(z)
}

// !left oneToOne
{
const { data: oneToOne, error } = await postgrest
.from('channel_details')
.select('channels!left(*)')
.single()

if (error) {
throw new Error(error.message)
}

// TODO: this should never be nullable
expectType<Database['public']['Tables']['channels']['Row'] | null>(oneToOne.channels)
}

// !left oneToMany
{
const { data: oneToMany, error } = await postgrest
.from('users')
.select('messages!left(*)')
.single()

if (error) {
throw new Error(error.message)
}

expectType<Array<Database['public']['Tables']['messages']['Row']>>(oneToMany.messages)
}

// !left zeroToOne
{
const { data: zeroToOne, error } = await postgrest
.from('user_profiles')
.select('users!left(*)')
.single()

if (error) {
throw new Error(error.message)
}

expectType<Database['public']['Tables']['users']['Row'] | null>(zeroToOne.users)
}

// join over a 1-1 relation with both nullables and non-nullables fields
{
const { data: bestFriends, error } = await postgrest
.from('best_friends')
.select(
'first_user:users!best_friends_first_user_fkey(*), second_user:users!best_friends_second_user_fkey(*), third_wheel:users!best_friends_third_wheel_fkey(*)'
)
.single()

if (error) {
throw new Error(error.message)
}

// TODO: Those two fields shouldn't be nullables
expectType<Database['public']['Tables']['users']['Row'] | null>(bestFriends.first_user)
expectType<Database['public']['Tables']['users']['Row'] | null>(bestFriends.second_user)
// The third wheel should be nullable
expectType<Database['public']['Tables']['users']['Row'] | null>(bestFriends.third_wheel)
}
// join over a 1-M relation with both nullables and non-nullables fields
{
const { data: users, error } = await postgrest
.from('users')
.select(
`first_friend_of:best_friends_first_user_fkey(*),
second_friend_of:best_friends_second_user_fkey(*),
third_wheel_of:best_friends_third_wheel_fkey(*)`
)
.single()

if (error) {
throw new Error(error.message)
}
// TODO: type properly the result for this kind of queries
expectType<Array<{}>>(users.first_friend_of)
}
1 change: 1 addition & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import './basic'
import './relationships'
import './filters'
import './resource-embedding'
import './transforms'
Loading

0 comments on commit d81f8fa

Please sign in to comment.