2020-03-09 18:30:44 +01:00
|
|
|
/* eslint-env jest */
|
|
|
|
import { isSerializableProps } from 'next/dist/lib/is-serializable-props'
|
|
|
|
|
|
|
|
describe('isSerializableProps', () => {
|
|
|
|
it('handles null and undefined props', () => {
|
|
|
|
expect(() => isSerializableProps('/', 'test', null))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing props returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Props must be returned as a plain object from test: \`{ props: { ... } }\` (received: \`[object Null]\`)."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', undefined))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing props returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Props must be returned as a plain object from test: \`{ props: { ... } }\` (received: \`[object Undefined]\`)."
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('handles non-plain object props', () => {
|
|
|
|
expect(() => isSerializableProps('/', 'test', []))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
|
|
|
"Error serializing props returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Props must be returned as a plain object from test: \`{ props: { ... } }\` (received: \`[object Array]\`)."
|
|
|
|
`)
|
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', class Foobar {}))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
|
|
|
"Error serializing props returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Props must be returned as a plain object from test: \`{ props: { ... } }\` (received: \`[object Function]\`)."
|
|
|
|
`)
|
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', function Foobar() {}))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
|
|
|
"Error serializing props returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Props must be returned as a plain object from test: \`{ props: { ... } }\` (received: \`[object Function]\`)."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('allows empty props', () => {
|
|
|
|
expect(isSerializableProps('/', 'test', {})).toBe(true)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('allows all different types of props', () => {
|
|
|
|
expect(
|
|
|
|
isSerializableProps('/', 'test', {
|
|
|
|
str: 'foobar',
|
|
|
|
bool: true,
|
|
|
|
bool2: false,
|
|
|
|
num: 0,
|
|
|
|
numn1: -1,
|
|
|
|
num5: 5,
|
|
|
|
noop: null,
|
|
|
|
arr: [
|
|
|
|
'f',
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
-5,
|
|
|
|
-1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
5,
|
|
|
|
null,
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
str: 'foobar',
|
|
|
|
bool: true,
|
|
|
|
bool2: false,
|
|
|
|
num: 0,
|
|
|
|
numn1: -1,
|
|
|
|
num5: 5,
|
|
|
|
noop: null,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
obj1: {
|
|
|
|
str: 'foobar',
|
|
|
|
bool: true,
|
|
|
|
bool2: false,
|
|
|
|
num: 0,
|
|
|
|
numn1: -1,
|
|
|
|
num5: 5,
|
|
|
|
noop: null,
|
|
|
|
arr: [
|
|
|
|
'f',
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
-5,
|
|
|
|
-1,
|
|
|
|
0,
|
|
|
|
1,
|
|
|
|
5,
|
|
|
|
null,
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
str: 'foobar',
|
|
|
|
bool: true,
|
|
|
|
bool2: false,
|
|
|
|
num: 0,
|
|
|
|
numn1: -1,
|
|
|
|
num5: 5,
|
|
|
|
noop: null,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
})
|
|
|
|
).toBe(true)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('disallows top-level non-serializable types', () => {
|
|
|
|
expect(() => isSerializableProps('/', 'test', { toplevel: new Date() }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.toplevel\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`object\` (\\"[object Date]\\") cannot be serialized as JSON. Please only return JSON serializable data types."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', { toplevel: class A {} }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.toplevel\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`function\` cannot be serialized as JSON. Please only return JSON serializable data types."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', { toplevel: undefined }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.toplevel\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`undefined\` cannot be serialized as JSON. Please use \`null\` or omit this value."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() =>
|
|
|
|
isSerializableProps('/', 'test', { toplevel: Symbol('FOOBAR') })
|
|
|
|
).toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.toplevel\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`symbol\` cannot be serialized as JSON. Please only return JSON serializable data types."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
2020-05-18 21:24:37 +02:00
|
|
|
expect(() => isSerializableProps('/', 'test', { toplevel: function () {} }))
|
2020-03-09 18:30:44 +01:00
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.toplevel\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`function\` cannot be serialized as JSON. Please only return JSON serializable data types."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('diallows nested non-serializable types', () => {
|
|
|
|
expect(() =>
|
|
|
|
isSerializableProps('/', 'test', { k: { a: [1, { n: new Date() }] } })
|
|
|
|
).toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k.a[1].n\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`object\` (\\"[object Date]\\") cannot be serialized as JSON. Please only return JSON serializable data types."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() =>
|
|
|
|
isSerializableProps('/', 'test', { k: { a: [1, { n: class A {} }] } })
|
|
|
|
).toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k.a[1].n\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`function\` cannot be serialized as JSON. Please only return JSON serializable data types."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', { k: { a: [1, undefined] } }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k.a[1]\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`undefined\` cannot be serialized as JSON. Please use \`null\` or omit this value."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() =>
|
|
|
|
isSerializableProps('/', 'test', { k: { n: Symbol('FOOBAR') } })
|
|
|
|
).toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k.n\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`symbol\` cannot be serialized as JSON. Please only return JSON serializable data types."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() =>
|
2020-05-18 21:24:37 +02:00
|
|
|
isSerializableProps('/', 'test', { k: { a: [function () {}] } })
|
2020-03-09 18:30:44 +01:00
|
|
|
).toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k.a[0]\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: \`function\` cannot be serialized as JSON. Please only return JSON serializable data types."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('can handle obj circular refs', () => {
|
2021-08-24 14:52:45 +02:00
|
|
|
const obj: any = { foo: 'bar', test: true }
|
2020-03-09 18:30:44 +01:00
|
|
|
obj.child = obj
|
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', obj))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.child\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Circular references cannot be expressed in JSON (references: \`(self)\`)."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', { k: [obj] }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k[0].child\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Circular references cannot be expressed in JSON (references: \`.k[0]\`)."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('can handle arr circular refs', () => {
|
2021-08-24 14:52:45 +02:00
|
|
|
const arr: any = [{ foo: 'bar' }, true]
|
2020-03-09 18:30:44 +01:00
|
|
|
arr.push(arr)
|
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', { arr }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.arr[2]\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Circular references cannot be expressed in JSON (references: \`.arr\`)."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', { k: [{ arr }] }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k[0].arr[2]\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Circular references cannot be expressed in JSON (references: \`.k[0].arr\`)."
|
|
|
|
`)
|
2020-03-09 18:30:44 +01:00
|
|
|
})
|
2020-03-09 19:58:51 +01:00
|
|
|
|
|
|
|
it('can handle deep obj circular refs', () => {
|
2021-08-24 14:52:45 +02:00
|
|
|
const obj: any = { foo: 'bar', test: true, leve1: { level2: {} } }
|
2020-03-09 19:58:51 +01:00
|
|
|
obj.leve1.level2.child = obj
|
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', obj))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.leve1.level2.child\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Circular references cannot be expressed in JSON (references: \`(self)\`)."
|
|
|
|
`)
|
2020-03-09 19:58:51 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('can handle deep obj circular refs (with arrays)', () => {
|
2021-08-24 14:52:45 +02:00
|
|
|
const obj: any = { foo: 'bar', test: true, leve1: { level2: {} } }
|
2020-03-09 19:58:51 +01:00
|
|
|
obj.leve1.level2.child = [{ another: [obj] }]
|
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', obj))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.leve1.level2.child[0].another[0]\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Circular references cannot be expressed in JSON (references: \`(self)\`)."
|
|
|
|
`)
|
2020-03-09 19:58:51 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('can handle deep arr circular refs', () => {
|
|
|
|
const arr = [1, 2, []]
|
|
|
|
arr[3] = [false, [null, 0, arr]]
|
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', { k: arr }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k[3][1][2]\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Circular references cannot be expressed in JSON (references: \`.k\`)."
|
|
|
|
`)
|
2020-03-09 19:58:51 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('can handle deep arr circular refs (with objects)', () => {
|
|
|
|
const arr = [1, 2, []]
|
|
|
|
arr[3] = [false, { nested: [null, 0, arr] }]
|
|
|
|
|
|
|
|
expect(() => isSerializableProps('/', 'test', { k: arr }))
|
|
|
|
.toThrowErrorMatchingInlineSnapshot(`
|
2021-07-25 08:08:30 +02:00
|
|
|
"Error serializing \`.k[3][1].nested[2]\` returned from \`test\` in \\"/\\".
|
|
|
|
Reason: Circular references cannot be expressed in JSON (references: \`.k\`)."
|
|
|
|
`)
|
2020-03-09 19:58:51 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('allows multi object refs', () => {
|
|
|
|
const obj = { foo: 'bar', test: true }
|
|
|
|
expect(
|
|
|
|
isSerializableProps('/', 'test', {
|
|
|
|
obj1: obj,
|
|
|
|
obj2: obj,
|
|
|
|
})
|
|
|
|
).toBe(true)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('allows multi object refs nested', () => {
|
|
|
|
const obj = { foo: 'bar', test: true }
|
|
|
|
expect(
|
|
|
|
isSerializableProps('/', 'test', {
|
|
|
|
obj1: obj,
|
|
|
|
obj2: obj,
|
|
|
|
anArray: [obj],
|
|
|
|
aKey: { obj },
|
|
|
|
})
|
|
|
|
).toBe(true)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('allows multi array refs', () => {
|
|
|
|
const arr = [{ foo: 'bar' }, true]
|
|
|
|
expect(
|
|
|
|
isSerializableProps('/', 'test', {
|
|
|
|
arr1: arr,
|
|
|
|
arr2: arr,
|
|
|
|
})
|
|
|
|
).toBe(true)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('allows multi array refs nested', () => {
|
|
|
|
const arr = [{ foo: 'bar' }, true]
|
|
|
|
expect(
|
|
|
|
isSerializableProps('/', 'test', {
|
|
|
|
arr1: arr,
|
|
|
|
arr2: arr,
|
|
|
|
arr3: [arr],
|
|
|
|
arr4: [1, [2, 3, arr]],
|
|
|
|
})
|
|
|
|
).toBe(true)
|
|
|
|
})
|
2020-09-12 08:36:29 +02:00
|
|
|
|
|
|
|
it('allows identical object instances in an array', () => {
|
|
|
|
const obj = { foo: 'bar' }
|
|
|
|
const arr = [obj, obj]
|
|
|
|
const objWithArr = { deep: { arr } }
|
|
|
|
|
|
|
|
expect(isSerializableProps('/', 'test', { arr })).toBe(true)
|
|
|
|
expect(isSerializableProps('/', 'test', { objWithArr })).toBe(true)
|
|
|
|
})
|
2020-11-09 15:25:41 +01:00
|
|
|
|
|
|
|
it('allows identical object instances in an array deeply', () => {
|
|
|
|
const obj = { foo: 'bar' }
|
|
|
|
const arr = [obj, [obj]]
|
|
|
|
const objWithArr = { deep: { arr } }
|
|
|
|
|
|
|
|
expect(isSerializableProps('/', 'test', { arr })).toBe(true)
|
|
|
|
expect(isSerializableProps('/', 'test', { objWithArr })).toBe(true)
|
|
|
|
})
|
2020-03-09 18:30:44 +01:00
|
|
|
})
|