97 lines
3.7 KiB
TypeScript
97 lines
3.7 KiB
TypeScript
import { Logger } from '@nestjs/common';
|
|
import { CategoryHiboutikService } from './category.hiboutik.service';
|
|
import { CategoryConverter } from '../../models/converter/category.converter';
|
|
import { CategoryHiboutikDto } from '../../models/hiboutikDTO/category.hiboutik.dto';
|
|
|
|
const hiboutikCategory = (id: number, parentId: number, overrides: Partial<CategoryHiboutikDto> = {}): CategoryHiboutikDto => ({
|
|
category_id: id,
|
|
category_name: `Category ${id}`,
|
|
category_id_parent: parentId,
|
|
category_enabled: 1,
|
|
category_enabled_www: 0,
|
|
category_position: 3,
|
|
...overrides,
|
|
});
|
|
|
|
describe('CategoryHiboutikService', () => {
|
|
const categoryHiboutikRepository = { getCategories: jest.fn() };
|
|
const categoryDatabaseRepository = { upsert: jest.fn(), setParent: jest.fn(), deleteMissing: jest.fn() };
|
|
let service: CategoryHiboutikService;
|
|
let calls: string[];
|
|
|
|
beforeAll(() => {
|
|
jest.spyOn(Logger.prototype, 'log').mockImplementation(() => undefined);
|
|
jest.spyOn(Logger.prototype, 'warn').mockImplementation(() => undefined);
|
|
jest.spyOn(Logger.prototype, 'error').mockImplementation(() => undefined);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
calls = [];
|
|
categoryDatabaseRepository.upsert.mockImplementation((category: { hiboutikId: number }) => {
|
|
calls.push(`upsert ${category.hiboutikId}`);
|
|
return Promise.resolve({});
|
|
});
|
|
categoryDatabaseRepository.setParent.mockImplementation((id: number) => {
|
|
calls.push(`parent ${id}`);
|
|
return Promise.resolve({});
|
|
});
|
|
categoryDatabaseRepository.deleteMissing.mockResolvedValue(0);
|
|
service = new CategoryHiboutikService(
|
|
categoryHiboutikRepository as never,
|
|
categoryDatabaseRepository as never,
|
|
new CategoryConverter(),
|
|
);
|
|
});
|
|
|
|
it('stores position and web visibility', async () => {
|
|
categoryHiboutikRepository.getCategories.mockResolvedValue([hiboutikCategory(1, 0)]);
|
|
|
|
await service.syncCategories();
|
|
|
|
expect(categoryDatabaseRepository.upsert).toHaveBeenCalledWith({
|
|
hiboutikId: 1,
|
|
name: 'Category 1',
|
|
enabled: true,
|
|
position: 3,
|
|
webEnabled: false,
|
|
});
|
|
});
|
|
|
|
it('links parents once every category is saved, a child being listed before its parent', async () => {
|
|
categoryHiboutikRepository.getCategories.mockResolvedValue([hiboutikCategory(2, 3), hiboutikCategory(3, 0)]);
|
|
|
|
await service.syncCategories();
|
|
|
|
expect(calls).toEqual(['upsert 2', 'upsert 3', 'parent 2', 'parent 3']);
|
|
expect(categoryDatabaseRepository.setParent).toHaveBeenCalledWith(2, 3);
|
|
expect(categoryDatabaseRepository.setParent).toHaveBeenCalledWith(3, null);
|
|
});
|
|
|
|
it('keeps syncing the other categories when one fails, then deletes the missing ones', async () => {
|
|
categoryHiboutikRepository.getCategories.mockResolvedValue([hiboutikCategory(1, 0), hiboutikCategory(2, 0)]);
|
|
categoryDatabaseRepository.upsert.mockRejectedValueOnce(new Error('boom'));
|
|
|
|
await expect(service.syncCategories()).resolves.toBeUndefined();
|
|
|
|
expect(categoryDatabaseRepository.upsert).toHaveBeenCalledTimes(2);
|
|
expect(categoryDatabaseRepository.deleteMissing).toHaveBeenCalledWith([1, 2]);
|
|
});
|
|
|
|
it('deletes every category when Hiboutik answers with an empty list', async () => {
|
|
categoryHiboutikRepository.getCategories.mockResolvedValue([]);
|
|
|
|
await service.syncCategories();
|
|
|
|
expect(categoryDatabaseRepository.deleteMissing).toHaveBeenCalledWith([]);
|
|
});
|
|
|
|
it('deletes nothing when the Hiboutik call fails', async () => {
|
|
categoryHiboutikRepository.getCategories.mockRejectedValue(new Error('Request failed with status code 500'));
|
|
|
|
await expect(service.syncCategories()).rejects.toThrow('500');
|
|
|
|
expect(categoryDatabaseRepository.deleteMissing).not.toHaveBeenCalled();
|
|
});
|
|
});
|