Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
at main 5.7 kB view raw
1/* eslint-disable @typescript-eslint/no-var-requires */ 2 3import { gql, CombinedError } from '@urql/core'; 4import { minifyIntrospectionQuery } from '@urql/introspection'; 5import { vi, expect, it, beforeEach, describe, beforeAll } from 'vitest'; 6 7import { __initAnd_write as write } from './write'; 8import * as InMemoryData from '../store/data'; 9import { Store } from '../store/store'; 10 11const TODO_QUERY = gql` 12 query todos { 13 todos { 14 id 15 text 16 complete 17 author { 18 id 19 name 20 known 21 __typename 22 } 23 __typename 24 } 25 } 26`; 27 28describe('Query', () => { 29 let schema, store; 30 31 beforeAll(() => { 32 schema = minifyIntrospectionQuery( 33 require('../test-utils/simple_schema.json') 34 ); 35 }); 36 37 beforeEach(() => { 38 store = new Store({ schema }); 39 write( 40 store, 41 { query: TODO_QUERY }, 42 { 43 __typename: 'Query', 44 todos: [ 45 { id: '0', text: 'Teach', __typename: 'Todo' }, 46 { id: '1', text: 'Learn', __typename: 'Todo' }, 47 ], 48 } 49 ); 50 51 vi.clearAllMocks(); 52 }); 53 54 it('should not crash for valid writes', async () => { 55 const VALID_TODO_QUERY = gql` 56 mutation { 57 toggleTodo { 58 id 59 text 60 complete 61 } 62 } 63 `; 64 write( 65 store, 66 { query: VALID_TODO_QUERY }, 67 { 68 __typename: 'Mutation', 69 toggleTodo: { 70 __typename: 'Todo', 71 id: '0', 72 text: 'Teach', 73 complete: true, 74 }, 75 } 76 ); 77 expect(console.warn).not.toHaveBeenCalled(); 78 expect(console.error).not.toHaveBeenCalled(); 79 }); 80 81 it('should warn once for invalid fields on an entity', () => { 82 const INVALID_TODO_QUERY = gql` 83 mutation { 84 toggleTodo { 85 id 86 text 87 incomplete 88 } 89 } 90 `; 91 write( 92 store, 93 { query: INVALID_TODO_QUERY }, 94 { 95 __typename: 'Mutation', 96 toggleTodo: { 97 __typename: 'Todo', 98 id: '0', 99 text: 'Teach', 100 incomplete: false, 101 }, 102 } 103 ); 104 expect(console.warn).toHaveBeenCalledTimes(1); 105 write( 106 store, 107 { query: INVALID_TODO_QUERY }, 108 { 109 __typename: 'Mutation', 110 toggleTodo: { 111 __typename: 'Todo', 112 id: '0', 113 text: 'Teach', 114 incomplete: false, 115 }, 116 } 117 ); 118 expect(console.warn).toHaveBeenCalledTimes(1); 119 expect((console.warn as any).mock.calls[0][0]).toMatch( 120 /The field `incomplete` does not exist on `Todo`/ 121 ); 122 }); 123 124 it('should warn once for invalid link fields on an entity', () => { 125 const INVALID_TODO_QUERY = gql` 126 mutation { 127 toggleTodo { 128 id 129 text 130 writer { 131 id 132 } 133 } 134 } 135 `; 136 write( 137 store, 138 { query: INVALID_TODO_QUERY }, 139 { 140 __typename: 'Mutation', 141 toggleTodo: { 142 __typename: 'Todo', 143 id: '0', 144 text: 'Teach', 145 writer: { 146 id: '0', 147 }, 148 }, 149 } 150 ); 151 // Because of us indicating Todo:Writer as a scalar 152 expect(console.warn).toHaveBeenCalledTimes(2); 153 expect((console.warn as any).mock.calls[0][0]).toMatch( 154 /The field `writer` does not exist on `Todo`/ 155 ); 156 }); 157 158 it('should skip undefined values that are expected', () => { 159 const query = gql` 160 { 161 field 162 } 163 `; 164 165 // This should not overwrite the field 166 write(store, { query }, { field: undefined } as any); 167 // Because of us writing an undefined field 168 expect(console.warn).toHaveBeenCalledTimes(2); 169 170 expect((console.warn as any).mock.calls[1][0]).toMatch( 171 /Invalid undefined: The field at `field`/ 172 ); 173 174 write(store, { query }, { field: 'test' } as any); 175 write(store, { query }, { field: undefined } as any); 176 InMemoryData.initDataState('read', store.data, null); 177 // The field must still be `'test'` 178 expect(InMemoryData.readRecord('Query', 'field')).toBe('test'); 179 }); 180 181 it('should write errored records as undefined rather than null', () => { 182 const query = gql` 183 { 184 missingField 185 setField 186 } 187 `; 188 189 write( 190 store, 191 { query }, 192 { missingField: null, setField: 'test' } as any, 193 new CombinedError({ 194 graphQLErrors: [ 195 { 196 message: 'Test', 197 path: ['missingField'], 198 }, 199 ], 200 }) 201 ); 202 203 InMemoryData.initDataState('read', store.data, null); 204 205 // The setField must still be `'test'` 206 expect(InMemoryData.readRecord('Query', 'setField')).toBe('test'); 207 // The missingField must still be `undefined` 208 expect(InMemoryData.readRecord('Query', 'missingField')).toBe(undefined); 209 }); 210 211 it('should write errored links as undefined rather than null', () => { 212 const query = gql` 213 { 214 missingTodoItem: todos { 215 id 216 text 217 } 218 missingTodo: todo { 219 id 220 text 221 } 222 } 223 `; 224 225 write( 226 store, 227 { query }, 228 { 229 missingTodoItem: [null, { __typename: 'Todo', id: 1, text: 'Learn' }], 230 missingTodo: null, 231 } as any, 232 new CombinedError({ 233 graphQLErrors: [ 234 { 235 message: 'Test', 236 path: ['missingTodoItem', 0], 237 }, 238 { 239 message: 'Test', 240 path: ['missingTodo'], 241 }, 242 ], 243 }) 244 ); 245 246 InMemoryData.initDataState('read', store.data, null); 247 expect(InMemoryData.readLink('Query', 'todos')).toEqual([ 248 undefined, 249 'Todo:1', 250 ]); 251 expect(InMemoryData.readLink('Query', 'todo')).toEqual(undefined); 252 }); 253});