wopian/kitsu

View on GitHub
packages/kitsu-core/src/serialise/index.spec.js

Summary

Maintainability
A
0 mins
Test Coverage
import plural from 'pluralize'
import { camel } from '../'
import { serialise } from './'

describe('kitsu-core', () => {
  describe('serialise', () => {
    it('accepts camelCaseTypes as an option (default)', () => {
      expect.assertions(1)
      const input = serialise('library-entries', { id: '1' }, undefined)
      expect(input).toEqual({
        data: {
          id: '1',
          type: 'library-entries'
        }
      })
    })

    it('accepts camelCaseTypes as an option (value set)', () => {
      expect.assertions(1)
      const input = serialise('library-entries', { id: '1' }, undefined, {
        camelCaseTypes: camel
      })
      expect(input).toEqual({
        data: {
          id: '1',
          type: 'libraryEntries'
        }
      })
    })

    it('accepts pluralTypes  as an option (default)', () => {
      expect.assertions(1)
      const input = serialise('libraryEntry', { id: '1' }, undefined)
      expect(input).toEqual({
        data: {
          id: '1',
          type: 'libraryEntry'
        }
      })
    })

    it('accepts pluralTypes as an option (value set)', () => {
      expect.assertions(1)
      const input = serialise('libraryEntry', { id: '1' }, undefined, {
        pluralTypes: plural
      })
      expect(input).toEqual({
        data: {
          id: '1',
          type: 'libraryEntries'
        }
      })
    })

    it('serialises to a JSON API compliant object', () => {
      expect.assertions(1)
      const input = serialise(
        'libraryEntries',
        {
          ratingTwenty: 20
        },
        undefined,
        {
          camelCaseTypes: camel,
          pluralTypes: plural
        }
      )
      expect(input).toEqual({
        data: {
          attributes: {
            ratingTwenty: 20
          },
          type: 'libraryEntries'
        }
      })
    })

    it('serialises JSON API relationships', () => {
      expect.assertions(1)
      const input = serialise(
        'libraryEntries',
        {
          user: {
            data: {
              id: '2'
            }
          }
        },
        undefined,
        {
          camelCaseTypes: camel,
          pluralTypes: plural
        }
      )
      expect(input).toEqual({
        data: {
          relationships: {
            user: {
              data: {
                id: '2',
                type: 'users'
              }
            }
          },
          type: 'libraryEntries'
        }
      })
    })

    it('serialises JSON API array relationships', () => {
      expect.assertions(1)
      const input = serialise(
        'libraryEntries',
        {
          user: {
            data: [
              {
                id: '2',
                type: 'users',
                content: 'yuzu'
              },
              {
                id: '3'
              }
            ]
          }
        },
        undefined,
        {
          camelCaseTypes: camel,
          pluralTypes: plural
        }
      )
      expect(input).toEqual({
        data: {
          relationships: {
            user: {
              data: [
                {
                  id: '2',
                  type: 'users',
                  attributes: {
                    content: 'yuzu'
                  }
                },
                {
                  id: '3',
                  type: 'users'
                }
              ]
            }
          },
          type: 'libraryEntries'
        }
      })
    })

    it('serialises JSON API with a client-generated ID', () => {
      expect.assertions(1)
      const input = serialise(
        'libraryEntries',
        {
          id: '123456789',
          ratingTwenty: 20
        },
        undefined,
        {
          camelCaseTypes: camel,
          pluralTypes: plural
        }
      )
      expect(input).toEqual({
        data: {
          id: '123456789',
          type: 'libraryEntries',
          attributes: {
            ratingTwenty: 20
          }
        }
      })
    })

    it('pluralises type', () => {
      expect.assertions(1)
      const input = serialise(
        'libraryEntry',
        {
          rating: '1'
        },
        undefined,
        {
          camelCaseTypes: camel,
          pluralTypes: plural
        }
      )
      expect(input).toEqual({
        data: {
          type: 'libraryEntries',
          attributes: {
            rating: '1'
          }
        }
      })
    })

    it('does not pluralise mass nouns', () => {
      expect.assertions(1)
      const input = serialise(
        'anime',
        {
          slug: 'Cowboy Bebop 2'
        },
        undefined,
        {
          camelCaseTypes: camel,
          pluralTypes: plural
        }
      )
      expect(input).toEqual({
        data: {
          type: 'anime',
          attributes: {
            slug: 'Cowboy Bebop 2'
          }
        }
      })
    })

    it('does not pluralise type', () => {
      expect.assertions(1)
      const input = serialise('libraryEntry', {
        rating: '1'
      })
      expect(input).toEqual({
        data: {
          type: 'libraryEntry',
          attributes: {
            rating: '1'
          }
        }
      })
    })

    it('does not throws an error if obj is missing when method is POST', () => {
      expect.assertions(1)
      const input = serialise('anime', { }, 'POST')
      expect(input).toEqual({
        data: {
          type: 'anime'
        }
      })
    })

    it('throws an error if obj is missing when method is not POST', () => {
      expect.assertions(1)
      expect(() => serialise('post', {}, 'PATCH'))
        .toThrowError('PATCH requires an object or array body')
    })

    it('throws an error if obj is not an Object', () => {
      expect.assertions(1)
      expect(() => serialise('post', 'id: 1', 'DELETE'))
        .toThrowError('DELETE requires an object or array body')
    })

    it('throws an error when missing ID', () => {
      expect.assertions(1)
      expect(() => serialise('user', { theme: 'dark' }, 'PATCH'))
        .toThrowError('PATCH requires an ID for the user type')
    })

    it('throws an error when missing ID in array', () => {
      expect.assertions(1)
      expect(() => serialise('user', [ { theme: 'dark' } ], 'PATCH'))
        .toThrowError('PATCH requires an ID for the user type')
    })

    it('serialises strings/numbers/booleans into attributes', () => {
      expect.assertions(1)
      const input = serialise('resourceModel', {
        string: 'shark',
        number: 1,
        boolean: true
      })
      expect(input).toEqual({
        data: {
          type: 'resourceModel',
          attributes: {
            string: 'shark',
            number: 1,
            boolean: true
          }
        }
      })
    })

    it('serialises bare objects into attributes', () => {
      expect.assertions(1)
      const input = serialise('resourceModel', {
        object: {
          string: 'shark'
        },
        blank: {}
      })
      expect(input).toEqual({
        data: {
          type: 'resourceModel',
          attributes: {
            object: {
              string: 'shark'
            },
            blank: {}
          }
        }
      })
    })

    it('serialises type objects into relationships', () => {
      expect.assertions(1)
      const input = serialise('resourceModel', {
        myRelationship: {
          data: {
            id: '1',
            type: 'relationshipModel',
            content: 'Hello',
            attributes: 'Keep me'
          }
        }
      })
      expect(input).toEqual({
        data: {
          type: 'resourceModel',
          relationships: {
            myRelationship: {
              data: {
                id: '1',
                type: 'relationshipModel',
                attributes: {
                  content: 'Hello',
                  attributes: 'Keep me'
                }
              }
            }
          }
        }
      })
    })

    it('serialises type objects into relationships inside arrays', () => {
      expect.assertions(1)
      const input = serialise('resourceModel', [ {
        myRelationship: {
          data: {
            id: '1',
            type: 'relationshipModel',
            content: 'Hello'
          }
        }
      } ])
      expect(input).toEqual({
        data: [ {
          type: 'resourceModel',
          relationships: {
            myRelationship: {
              data: {
                id: '1',
                type: 'relationshipModel',
                attributes: {
                  content: 'Hello'
                }
              }
            }
          }
        } ]
      })
    })

    it('serialises bare arrays into attributes', () => {
      expect.assertions(1)
      const input = serialise('resourceModel', {
        array: [ 0 ],
        deepArray: [ [ 0 ] ],
        arrayObject: [ { string: 'shark' } ],
        blank: []
      })
      expect(input).toEqual({
        data: {
          type: 'resourceModel',
          attributes: {
            array: [ 0 ],
            deepArray: [ [ 0 ] ],
            arrayObject: [ { string: 'shark' } ],
            blank: []
          }
        }
      })
    })

    it('serialises type arrays into relationships', () => {
      expect.assertions(1)
      const input = serialise('resourceModels', {
        arrayRelation: {
          data: [
            {
              id: '1',
              type: 'arrayRelations',
              content: 'Hey',
              attributes: 'Keep me'
            }
          ]
        }
      })
      expect(input).toEqual({
        data: {
          type: 'resourceModels',
          relationships: {
            arrayRelation: {
              data: [ {
                id: '1',
                type: 'arrayRelations',
                attributes: {
                  content: 'Hey',
                  attributes: 'Keep me'
                }
              } ]
            }
          }
        }
      })
    })

    it('serialises relationship clearing (to-one)', () => {
      expect.assertions(1)
      const input = serialise('resourceModel', null)
      expect(input).toEqual({
        data: null
      })
    })

    it('serialises relationship clearing (to-many)', () => {
      expect.assertions(1)
      const input = serialise('resourceModel', [])
      expect(input).toEqual({
        data: []
      })
    })

    it('serialises a data array without ID (POST)', () => {
      expect.assertions(1)
      const resource = { content: 'some new content' }
      const resourceOutput = { type: 'posts', attributes: { content: 'some new content' } }
      const input = serialise('posts', [ resource, resource ])
      expect(input).toEqual({
        data: [ resourceOutput, resourceOutput ]
      })
    })

    it('serialises a data array with ID (PATCH/DELETE)', () => {
      expect.assertions(1)
      const resource = { id: '1', content: 'some new content' }
      const resourceOutput = { id: '1', type: 'posts', attributes: { content: 'some new content' } }
      const input = serialise('posts', [ resource, resource ])
      expect(input).toEqual({
        data: [ resourceOutput, resourceOutput ]
      })
    })

    it('does not error with an invalid JSON value (undefined)', () => {
      expect.assertions(1)
      const resource = { id: '1', content: undefined }
      const resourceOutput = { id: '1', type: 'posts', attributes: { content: undefined } }
      const input = serialise('posts', resource)
      expect(input).toEqual({ data: resourceOutput })
    })

    it('serialises object and array relationships', () => {
      expect.assertions(1)
      const input = {
        id: '1',
        type: 'libraryEntries',
        links: { self: 'library-entries/1' },
        meta: { extra: true },
        ratingTwenty: 10,
        user: {
          links: {
            self: 'library-entries/1/relationships/user',
            related: 'library-entries/1/user'
          },
          meta: { some: 'meta info' },
          data: {
            id: '2',
            type: 'users',
            name: 'Example',
            links: { self: 'users/2' }
          }
        },
        unit: {
          links: {
            self: 'library-entries/1/relationships/unit',
            related: 'library-entries/1/unit'
          },
          meta: { extra: 'info' },
          data: [
            {
              id: '3',
              type: 'episodes',
              number: 12,
              links: { self: 'episodes/3' }
            }
          ]
        }
      }
      const output = {
        data: {
          id: '1',
          type: 'libraryEntries',
          links: { self: 'library-entries/1' },
          meta: { extra: true },
          attributes: { ratingTwenty: 10 },
          relationships: {
            user: {
              links: {
                self: 'library-entries/1/relationships/user',
                related: 'library-entries/1/user'
              },
              meta: { some: 'meta info' },
              data: {
                id: '2',
                type: 'users',
                attributes: { name: 'Example' },
                links: { self: 'users/2' }
              }
            },
            unit: {
              links: {
                self: 'library-entries/1/relationships/unit',
                related: 'library-entries/1/unit'
              },
              meta: { extra: 'info' },
              data: [
                {
                  id: '3',
                  type: 'episodes',
                  attributes: { number: 12 },
                  links: { self: 'episodes/3' }
                }
              ]
            }
          }
        }
      }
      expect(serialise('libraryEntries', input)).toStrictEqual(output)
    })

    it('keeps non-JSON:API links/meta properties in attributes', () => {
      expect.assertions(1)
      const input = {
        id: '1',
        type: 'libraryEntries',
        links: 'Not JSON:API link object',
        meta: 'Not JSON:API meta object',
        user: {
          data: {
            id: '1',
            links: 'Not JSON:API link object',
            meta: 'Not JSON:API meta object'
          }
        }
      }
      const output = {
        data: {
          id: '1',
          type: 'libraryEntries',
          attributes: {
            links: 'Not JSON:API link object',
            meta: 'Not JSON:API meta object'
          },
          relationships: {
            user: {
              data: {
                id: '1',
                type: 'user',
                attributes: {
                  links: 'Not JSON:API link object',
                  meta: 'Not JSON:API meta object'
                }
              }
            }
          }
        }
      }
      expect(serialise('libraryEntries', input)).toStrictEqual(output)
    })

    it('deletes a to-one relationship', () => {
      expect.assertions(1)
      const input = {
        id: '1',
        type: 'libraryEntries',
        user: {
          data: null
        }
      }
      const output = {
        data: {
          id: '1',
          type: 'libraryEntries',
          relationships: {
            user: {
              data: null
            }
          }
        }
      }
      expect(serialise('libraryEntries', input)).toStrictEqual(output)
    })

    it('deletes a to-many relationship', () => {
      expect.assertions(1)
      const input = {
        id: '1',
        type: 'libraryEntries',
        user: {
          data: []
        }
      }
      const output = {
        data: {
          id: '1',
          type: 'libraryEntries',
          relationships: {
            user: {
              data: []
            }
          }
        }
      }
      expect(serialise('libraryEntries', input)).toStrictEqual(output)
    })
  })
})