src/datastore/__tests__/UserDataStore.spec.js

Summary

Maintainability
F
1 wk
Test Coverage
import UserDataStore from '../UserDataStore'
import UserDataStoreNamespace from '../UserDataStoreNamespace'
import MockApi from '../../api/Api'

jest.mock('../../api/Api')

describe('UserDataStore', () => {
    const namespaces = ['DHIS', 'History', 'social-media-video']
    const keys = ['key1', 'a key', 'aowelfkxuw']
    let userDataStore
    let apiMock

    beforeEach(() => {
        apiMock = new MockApi()
        userDataStore = new UserDataStore(apiMock)
    })

    afterEach(() => {
        MockApi.mockReset()
    })

    describe('get()', () => {
        it('should return an instance of UserDatastoreNamespace', () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve(namespaces))

            return userDataStore.get('DHIS').then((namespace) => {
                expect(namespace).toBeInstanceOf(UserDataStoreNamespace)
            })
        })

        it('should return a UserDatastoreNamespace with keys if it exists', () => {
            apiMock.get
                .mockReturnValueOnce(Promise.resolve(namespaces))
                .mockReturnValueOnce(Promise.resolve(keys))

            return userDataStore.get('DHIS').then((namespace) =>
                namespace.getKeys().then((res) => {
                    expect(res).toEqual(keys)
                    expect(apiMock.get).toHaveBeenCalledTimes(2)
                })
            )
        })

        it('should not request API if autoload is false', () =>
            userDataStore.get('DHIS', false).then((res) => {
                expect(res).toBeInstanceOf(UserDataStoreNamespace)
                expect(apiMock.get).not.toHaveBeenCalled()
            }))

        it('should throw an error when no response', () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve(null))

            return userDataStore.get('DHIS').catch((e) => {
                expect(e.message).toBe(
                    'The requested namespace has no keys or does not exist.'
                )
            })
        })

        it('should throw an error if namespace does not exist on server', () => {
            const err = { httpStatusCode: 404 }
            apiMock.get.mockReturnValueOnce(Promise.reject(err))

            return expect(
                userDataStore.get('DHIS').catch((e) => {
                    expect(e).toThrow()
                })
            ).rejects.toBeDefined()
        })

        it('should throw when error is not 404', () => {
            const error = { httpStatusCode: 500 }
            apiMock.get.mockReturnValueOnce(Promise.reject(error))

            return userDataStore.get('DHIS').catch((e) => {
                expect(e).toEqual(error)
            })
        })

        it('should throw an error if response is an empty array', () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve([]))
            expect.assertions(1)
            return userDataStore
                .get('namespace')
                .then(() => {
                    throw new Error('this hould have failed')
                })
                .catch((e) => {
                    expect(e.message).toMatch(/does not exist/)
                })
        })

        describe('for an invalid namespace', () => {
            beforeEach(() => {
                apiMock.get.mockReturnValueOnce(
                    Promise.reject(
                        [
                            '{',
                            '"httpStatus":"Not Found",',
                            '"httpStatusCode":404,',
                            '"status":"ERROR",',
                            '"message":"The namespace \'not-my-namespace\' was not found."',
                            '}',
                        ].join('')
                    )
                )
            })

            it('should throw an error', () => {
                expect.assertions(1)

                return userDataStore.get('not-my-namespace').catch(() => {
                    // TODO: this seems to just be testing the mock
                    expect(true).toBe(true)
                })
            })
        })
    })

    describe('getAll()', () => {
        it('should return an array of namespaces', () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve(namespaces))

            expect.assertions(1)

            return userDataStore.getAll().then((namespaceRes) => {
                expect(namespaces).toEqual(namespaceRes)
            })
        })

        it('should throw an error when there is no response', () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve(null))

            expect.assertions(1)

            return userDataStore.getAll().catch((namespaceRes) => {
                expect(namespaceRes.message).toBe('No namespaces exist.')
            })
        })
    })

    describe('delete()', () => {
        beforeEach(() => {
            apiMock.delete.mockReturnValueOnce(Promise.resolve())
        })

        it('should call the api with correct url', () => {
            const namespaceDel = 'DHIS'

            return userDataStore.delete(namespaceDel).then(() => {
                expect(apiMock.delete).toBeCalledWith(
                    `userDataStore/${namespaceDel}`
                )
            })
        })
    })

    describe('getUserDataStore', () => {
        it('should return an instance of UserDataStore', () => {
            expect(UserDataStore.getUserDataStore()).toBeInstanceOf(
                UserDataStore
            )
        })

        it('should return the same object when called twice', () => {
            expect(UserDataStore.getUserDataStore()).toBe(
                UserDataStore.getUserDataStore()
            )
        })
    })

    describe('create()', () => {
        it('should return an instance of UserDataStoreNamespace if namespace do not exist', () => {
            const error = { httpStatusCode: 404 }
            apiMock.get.mockReturnValueOnce(Promise.reject(error))

            return userDataStore.create('DHIS').then((namespace) => {
                expect(namespace).toBeInstanceOf(UserDataStoreNamespace)
                expect(namespace.keys).toHaveLength(0)
            })
        })

        it('should return an error if namespace exists', () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve(keys))

            return userDataStore.get('DHIS').then((namespace) => {
                expect(namespace).toBeInstanceOf(UserDataStoreNamespace)
            })
        })
    })

    describe('has', () => {
        it('should resolve with true if namespace exists', async () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve(keys))
            const hasNamespace = await userDataStore.has('DHIS')
            expect(hasNamespace).toBe(true)
        })

        it('should resolve with false if namespace does not exists (404 from server)', async () => {
            const err = { httpStatusCode: 404 }
            apiMock.get.mockReturnValueOnce(Promise.reject(err))
            const hasNamespace = await userDataStore.has('arandomnamespace')
            expect(hasNamespace).toBe(false)
        })

        it('should resolve with false if namespace does not exists (empty array)', async () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve([]))
            const hasNamespace = await userDataStore.has('arandomnamespace')
            expect(hasNamespace).toBe(false)
        })

        it('should throw an error if resolved response is not an array', async () => {
            apiMock.get.mockReturnValueOnce(Promise.resolve({}))
            await expect(
                userDataStore.has('arandomnamespace')
            ).rejects.toBeDefined()
        })

        it('should throw an error if rejected response is not 404 or empty array ', async () => {
            const err = { httpStatusCode: 500 }
            apiMock.get.mockReturnValueOnce(Promise.resolve(err))
            await expect(
                userDataStore.has('arandomnamespace')
            ).rejects.toBeDefined()
        })
    })
})