Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
at main 6.2 kB view raw
1import { pipe, map, fromValue, toPromise, take } from 'wonka'; 2import { vi, expect, it, beforeEach } from 'vitest'; 3import { GraphQLError } from 'graphql'; 4 5import { 6 gql, 7 createClient, 8 Operation, 9 ExchangeIO, 10 Client, 11 CombinedError, 12} from '@urql/core'; 13 14import { throwOnErrorExchange } from './throwOnErrorExchange'; 15 16const dispatchDebug = vi.fn(); 17 18const query = gql` 19 { 20 topLevel 21 topLevelList 22 object { 23 inner 24 } 25 objectList { 26 inner 27 } 28 } 29`; 30const mockData = { 31 topLevel: 'topLevel', 32 topLevelList: ['topLevelList'], 33 object: { inner: 'inner' }, 34 objectList: [{ inner: 'inner' }], 35}; 36 37let client: Client, op: Operation; 38beforeEach(() => { 39 client = createClient({ 40 url: 'http://0.0.0.0', 41 exchanges: [], 42 }); 43 op = client.createRequestOperation('query', { key: 1, query, variables: {} }); 44}); 45 46it('throws on top level field error', async () => { 47 const forward: ExchangeIO = ops$ => 48 pipe( 49 ops$, 50 map( 51 operation => 52 ({ 53 operation, 54 data: { 55 ...mockData, 56 topLevel: null, 57 }, 58 error: new CombinedError({ 59 graphQLErrors: [ 60 new GraphQLError('top level error', { path: ['topLevel'] }), 61 ], 62 }), 63 }) as any 64 ) 65 ); 66 67 const res = await pipe( 68 fromValue(op), 69 throwOnErrorExchange()({ forward, client, dispatchDebug }), 70 take(1), 71 toPromise 72 ); 73 74 expect(() => res.data?.topLevel).toThrow('top level error'); 75 expect(() => res.data).not.toThrow(); 76 expect(() => res.data?.topLevelList[0]).not.toThrow(); 77}); 78 79it('throws on top level list element error', async () => { 80 const forward: ExchangeIO = ops$ => 81 pipe( 82 ops$, 83 map( 84 operation => 85 ({ 86 operation, 87 data: { 88 ...mockData, 89 topLevelList: ['topLevelList', null], 90 }, 91 error: new CombinedError({ 92 graphQLErrors: [ 93 new GraphQLError('top level list error', { 94 path: ['topLevelList', 1], 95 }), 96 ], 97 }), 98 }) as any 99 ) 100 ); 101 102 const res = await pipe( 103 fromValue(op), 104 throwOnErrorExchange()({ forward, client, dispatchDebug }), 105 take(1), 106 toPromise 107 ); 108 109 expect(() => res.data?.topLevelList[1]).toThrow('top level list error'); 110 expect(() => res.data).not.toThrow(); 111 expect(() => res.data?.topLevelList[0]).not.toThrow(); 112}); 113 114it('throws on object field error', async () => { 115 const forward: ExchangeIO = ops$ => 116 pipe( 117 ops$, 118 map( 119 operation => 120 ({ 121 operation, 122 data: { 123 ...mockData, 124 object: null, 125 }, 126 error: new CombinedError({ 127 graphQLErrors: [ 128 new GraphQLError('object field error', { path: ['object'] }), 129 ], 130 }), 131 }) as any 132 ) 133 ); 134 135 const res = await pipe( 136 fromValue(op), 137 throwOnErrorExchange()({ forward, client, dispatchDebug }), 138 take(1), 139 toPromise 140 ); 141 142 expect(() => res.data?.object).toThrow('object field error'); 143 expect(() => res.data?.object.inner).toThrow('object field error'); 144 expect(() => res.data).not.toThrow(); 145 expect(() => res.data?.topLevel).not.toThrow(); 146}); 147 148it('throws on object inner field error', async () => { 149 const forward: ExchangeIO = ops$ => 150 pipe( 151 ops$, 152 map( 153 operation => 154 ({ 155 operation, 156 data: { 157 ...mockData, 158 object: { 159 inner: null, 160 }, 161 }, 162 error: new CombinedError({ 163 graphQLErrors: [ 164 new GraphQLError('object inner field error', { 165 path: ['object', 'inner'], 166 }), 167 ], 168 }), 169 }) as any 170 ) 171 ); 172 173 const res = await pipe( 174 fromValue(op), 175 throwOnErrorExchange()({ forward, client, dispatchDebug }), 176 take(1), 177 toPromise 178 ); 179 180 expect(() => res.data?.object.inner).toThrow('object inner field error'); 181 expect(() => res.data).not.toThrow(); 182 expect(() => res.data?.object).not.toThrow(); 183}); 184 185it('throws on object list field error', async () => { 186 const forward: ExchangeIO = ops$ => 187 pipe( 188 ops$, 189 map( 190 operation => 191 ({ 192 operation, 193 data: { 194 ...mockData, 195 objectList: null, 196 }, 197 error: new CombinedError({ 198 graphQLErrors: [ 199 new GraphQLError('object list field error', { 200 path: ['objectList'], 201 }), 202 ], 203 }), 204 }) as any 205 ) 206 ); 207 208 const res = await pipe( 209 fromValue(op), 210 throwOnErrorExchange()({ forward, client, dispatchDebug }), 211 take(1), 212 toPromise 213 ); 214 215 expect(() => res.data?.objectList).toThrow('object list field error'); 216 expect(() => res.data?.objectList[0]).toThrow('object list field error'); 217 expect(() => res.data?.objectList[0].inner).toThrow( 218 'object list field error' 219 ); 220 expect(() => res.data).not.toThrow(); 221 expect(() => res.data?.topLevel).not.toThrow(); 222}); 223 224it('throws on object inner field error', async () => { 225 const forward: ExchangeIO = ops$ => 226 pipe( 227 ops$, 228 map( 229 operation => 230 ({ 231 operation, 232 data: { 233 ...mockData, 234 objectList: [{ inner: 'inner' }, { inner: null }], 235 }, 236 error: new CombinedError({ 237 graphQLErrors: [ 238 new GraphQLError('object list inner field error', { 239 path: ['objectList', 1, 'inner'], 240 }), 241 ], 242 }), 243 }) as any 244 ) 245 ); 246 247 const res = await pipe( 248 fromValue(op), 249 throwOnErrorExchange()({ forward, client, dispatchDebug }), 250 take(1), 251 toPromise 252 ); 253 254 expect(() => res.data?.objectList[1].inner).toThrow( 255 'object list inner field error' 256 ); 257 expect(() => res.data).not.toThrow(); 258 expect(() => res.data?.objectList[0].inner).not.toThrow(); 259});