Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
at main 3.3 kB view raw
1// @vitest-environment jsdom 2 3import { stringifyVariables, extractFiles } from './variables'; 4import { describe, it, expect } from 'vitest'; 5import { Script } from 'vm'; 6 7describe('stringifyVariables', () => { 8 it('stringifies objects stabily', () => { 9 expect(stringifyVariables({ b: 'b', a: 'a' })).toBe('{"a":"a","b":"b"}'); 10 expect(stringifyVariables({ x: { b: 'b', a: 'a' } })).toBe( 11 '{"x":{"a":"a","b":"b"}}' 12 ); 13 }); 14 15 it('stringifies arrays', () => { 16 expect(stringifyVariables([1, 2])).toBe('[1,2]'); 17 expect(stringifyVariables({ x: [1, 2] })).toBe('{"x":[1,2]}'); 18 }); 19 20 it('stringifies scalars', () => { 21 expect(stringifyVariables(1)).toBe('1'); 22 expect(stringifyVariables('test')).toBe('"test"'); 23 expect(stringifyVariables(null)).toBe('null'); 24 expect(stringifyVariables(undefined)).toBe(''); 25 expect(stringifyVariables(Infinity)).toBe('null'); 26 expect(stringifyVariables(1 / 0)).toBe('null'); 27 }); 28 29 it('returns null for circular structures', () => { 30 const x = { x: null } as any; 31 x.x = x; 32 expect(stringifyVariables(x)).toBe('{"x":null}'); 33 }); 34 35 it('stringifies dates correctly', () => { 36 const date = new Date('2019-12-11T04:20:00'); 37 expect(stringifyVariables(date)).toBe(`"${date.toJSON()}"`); 38 }); 39 40 it('stringifies dictionaries (Object.create(null)) correctly', () => { 41 expect(stringifyVariables(Object.create(null))).toBe('{}'); 42 }); 43 44 it('recovers if the root object is a dictionary (Object.create(null)) and nests a plain object', () => { 45 const root = Object.create(null); 46 root.data = { test: true }; 47 expect(stringifyVariables(root)).toBe('{"data":{"test":true}}'); 48 }); 49 50 it('recovers if the root object contains a dictionary (Object.create(null))', () => { 51 const data = Object.create(null); 52 data.test = true; 53 const root = { data }; 54 expect(stringifyVariables(root)).toBe('{"data":{"test":true}}'); 55 }); 56 57 it('replaces non-plain objects at the root with keyed replacements', () => { 58 expect(stringifyVariables(new (class Test {})())).toMatch( 59 /^{"__key":"\w+"}$/ 60 ); 61 expect(stringifyVariables(new Map())).toMatch(/^{"__key":"\w+"}$/); 62 }); 63 64 it('stringifies files correctly', () => { 65 const file = new File([0] as any, 'test.js'); 66 const str = stringifyVariables(file); 67 expect(str).toBe('null'); 68 }); 69 70 it('stringifies plain objects from foreign JS contexts correctly', () => { 71 const scriptGlobal: typeof globalThis = new Script( 72 'exports = globalThis' 73 ).runInNewContext({}).exports; 74 75 const plain = new scriptGlobal.Function('return { test: true }')(); 76 expect(stringifyVariables(plain)).toBe('{"test":true}'); 77 78 const data = new scriptGlobal.Function('return new (class Test {})')(); 79 expect(stringifyVariables(data)).toMatch(/^{"__key":"\w+"}$/); 80 }); 81}); 82 83describe('extractFiles', () => { 84 it('extracts files from nested objects', () => { 85 const file = new Blob(); 86 expect(extractFiles({ files: { a: file } })).toEqual( 87 new Map([['variables.files.a', file]]) 88 ); 89 }); 90 91 it('extracts files from nested arrays', () => { 92 const file = new Blob(); 93 expect(extractFiles({ files: [file] })).toEqual( 94 new Map([['variables.files.0', file]]) 95 ); 96 }); 97});