gitlab-org--gitlab-foss/spec/frontend/lib/utils/users_cache_spec.js

279 lines
7.5 KiB
JavaScript

import * as UserApi from '~/api/user_api';
import UsersCache from '~/lib/utils/users_cache';
describe('UsersCache', () => {
const dummyUsername = 'win';
const dummyUserId = 123;
const dummyUser = {
name: 'has a farm',
username: 'farmer',
};
const dummyUserStatus = 'my status';
beforeEach(() => {
UsersCache.internalStorage = {};
});
describe('get', () => {
it('returns undefined for empty cache', () => {
expect(UsersCache.internalStorage).toEqual({});
const user = UsersCache.get(dummyUsername);
expect(user).toBe(undefined);
});
it('returns undefined for missing user', () => {
UsersCache.internalStorage['no body'] = 'no data';
const user = UsersCache.get(dummyUsername);
expect(user).toBe(undefined);
});
it('returns matching user', () => {
UsersCache.internalStorage[dummyUsername] = dummyUser;
const user = UsersCache.get(dummyUsername);
expect(user).toBe(dummyUser);
});
});
describe('hasData', () => {
it('returns false for empty cache', () => {
expect(UsersCache.internalStorage).toEqual({});
expect(UsersCache.hasData(dummyUsername)).toBe(false);
});
it('returns false for missing user', () => {
UsersCache.internalStorage['no body'] = 'no data';
expect(UsersCache.hasData(dummyUsername)).toBe(false);
});
it('returns true for matching user', () => {
UsersCache.internalStorage[dummyUsername] = dummyUser;
expect(UsersCache.hasData(dummyUsername)).toBe(true);
});
});
describe('remove', () => {
it('does nothing if cache is empty', () => {
expect(UsersCache.internalStorage).toEqual({});
UsersCache.remove(dummyUsername);
expect(UsersCache.internalStorage).toEqual({});
});
it('does nothing if cache contains no matching data', () => {
UsersCache.internalStorage['no body'] = 'no data';
UsersCache.remove(dummyUsername);
expect(UsersCache.internalStorage['no body']).toBe('no data');
});
it('removes matching data', () => {
UsersCache.internalStorage[dummyUsername] = dummyUser;
UsersCache.remove(dummyUsername);
expect(UsersCache.internalStorage).toEqual({});
});
});
describe('retrieve', () => {
let apiSpy;
beforeEach(() => {
jest
.spyOn(UserApi, 'getUsers')
.mockImplementation((query, options) => apiSpy(query, options));
});
it('stores and returns data from API call if cache is empty', async () => {
apiSpy = (query, options) => {
expect(query).toBe('');
expect(options).toEqual({
username: dummyUsername,
});
return Promise.resolve({
data: [dummyUser],
});
};
const user = await UsersCache.retrieve(dummyUsername);
expect(user).toBe(dummyUser);
expect(UsersCache.internalStorage[dummyUsername]).toBe(dummyUser);
});
it('returns undefined if Ajax call fails and cache is empty', async () => {
const dummyError = new Error('server exploded');
apiSpy = (query, options) => {
expect(query).toBe('');
expect(options).toEqual({
username: dummyUsername,
});
return Promise.reject(dummyError);
};
await expect(UsersCache.retrieve(dummyUsername)).rejects.toEqual(dummyError);
});
it('makes no Ajax call if matching data exists', async () => {
UsersCache.internalStorage[dummyUsername] = dummyUser;
apiSpy = () => {
throw new Error('expected no Ajax call!');
};
const user = await UsersCache.retrieve(dummyUsername);
expect(user).toBe(dummyUser);
});
});
describe('retrieveById', () => {
let apiSpy;
beforeEach(() => {
jest.spyOn(UserApi, 'getUser').mockImplementation((id) => apiSpy(id));
});
it('stores and returns data from API call if cache is empty', async () => {
apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.resolve({
data: dummyUser,
});
};
const user = await UsersCache.retrieveById(dummyUserId);
expect(user).toEqual(dummyUser);
expect(UsersCache.internalStorage[dummyUserId]).toEqual(dummyUser);
});
it('returns undefined if Ajax call fails and cache is empty', async () => {
const dummyError = new Error('server exploded');
apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.reject(dummyError);
};
await expect(UsersCache.retrieveById(dummyUserId)).rejects.toEqual(dummyError);
});
it('makes no Ajax call if matching data exists', async () => {
UsersCache.internalStorage[dummyUserId] = dummyUser;
apiSpy = () => {
throw new Error('expected no Ajax call!');
};
const user = await UsersCache.retrieveById(dummyUserId);
expect(user).toBe(dummyUser);
});
it('does not clobber existing cached values', async () => {
UsersCache.internalStorage[dummyUserId] = {
status: dummyUserStatus,
};
apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.resolve({
data: dummyUser,
});
};
const user = await UsersCache.retrieveById(dummyUserId);
const expectedUser = {
status: dummyUserStatus,
...dummyUser,
};
expect(user).toEqual(expectedUser);
expect(UsersCache.internalStorage[dummyUserId]).toEqual(expectedUser);
});
});
describe('retrieveStatusById', () => {
let apiSpy;
beforeEach(() => {
jest.spyOn(UserApi, 'getUserStatus').mockImplementation((id) => apiSpy(id));
});
it('stores and returns data from API call if cache is empty', async () => {
apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.resolve({
data: dummyUserStatus,
});
};
const userStatus = await UsersCache.retrieveStatusById(dummyUserId);
expect(userStatus).toBe(dummyUserStatus);
expect(UsersCache.internalStorage[dummyUserId].status).toBe(dummyUserStatus);
});
it('returns undefined if Ajax call fails and cache is empty', async () => {
const dummyError = new Error('server exploded');
apiSpy = (id) => {
expect(id).toBe(dummyUserId);
return Promise.reject(dummyError);
};
await expect(UsersCache.retrieveStatusById(dummyUserId)).rejects.toEqual(dummyError);
});
it('makes no Ajax call if matching data exists', async () => {
UsersCache.internalStorage[dummyUserId] = {
status: dummyUserStatus,
};
apiSpy = () => {
throw new Error('expected no Ajax call!');
};
const userStatus = await UsersCache.retrieveStatusById(dummyUserId);
expect(userStatus).toBe(dummyUserStatus);
});
});
describe('updateById', () => {
describe('when the user is not cached', () => {
it('does nothing and returns undefined', () => {
expect(UsersCache.updateById(dummyUserId, { name: 'root' })).toBe(undefined);
expect(UsersCache.internalStorage).toStrictEqual({});
});
});
describe('when the user is cached', () => {
const updatedName = 'has two farms';
beforeEach(() => {
UsersCache.internalStorage[dummyUserId] = dummyUser;
});
it('updates the user only with the new data', async () => {
UsersCache.updateById(dummyUserId, { name: updatedName });
expect(await UsersCache.retrieveById(dummyUserId)).toStrictEqual({
username: dummyUser.username,
name: updatedName,
});
});
});
});
});