feat(sync): synchronize Hiboutik data through POST /sync

This commit is contained in:
MastersGame
2026-11-05 23:00:49 +01:00
parent 60cd4cc1d6
commit 358e99c1ba
17 changed files with 878 additions and 34 deletions

View File

@@ -0,0 +1,68 @@
import { Logger } from '@nestjs/common';
import { HiboutikService } from './hiboutik.service';
describe('HiboutikService', () => {
const brandService = { syncBrands: jest.fn() };
const categoryService = { syncCategories: jest.fn() };
const supplierService = { syncSuppliers: jest.fn() };
const productService = { syncProducts: jest.fn() };
const customerService = { syncCustomers: jest.fn() };
let service: HiboutikService;
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();
brandService.syncBrands.mockResolvedValue(undefined);
categoryService.syncCategories.mockResolvedValue(undefined);
supplierService.syncSuppliers.mockResolvedValue(undefined);
productService.syncProducts.mockResolvedValue(undefined);
customerService.syncCustomers.mockResolvedValue(undefined);
service = new HiboutikService(
brandService as never,
categoryService as never,
customerService as never,
productService as never,
supplierService as never,
);
});
it('runs the steps in dependency order', async () => {
const order: string[] = [];
brandService.syncBrands.mockImplementation(() => Promise.resolve(order.push('brands')));
categoryService.syncCategories.mockImplementation(() => Promise.resolve(order.push('categories')));
supplierService.syncSuppliers.mockImplementation(() => Promise.resolve(order.push('suppliers')));
productService.syncProducts.mockImplementation(() => Promise.resolve(order.push('products')));
customerService.syncCustomers.mockImplementation(() => Promise.resolve(order.push('customers')));
await service.syncAll();
expect(order).toEqual(['brands', 'categories', 'suppliers', 'products', 'customers']);
});
it('continues with the next steps when one fails', async () => {
brandService.syncBrands.mockRejectedValue(new Error('boom'));
await service.syncAll();
expect(productService.syncProducts).toHaveBeenCalled();
expect(customerService.syncCustomers).toHaveBeenCalled();
});
it('refuses a second synchronization while one is running, and unlocks at the end', async () => {
let finishBrands: () => void = () => undefined;
brandService.syncBrands.mockReturnValue(new Promise<void>((resolve) => (finishBrands = resolve)));
expect(service.startSync()).toBe(true);
expect(service.isSyncInProgress).toBe(true);
expect(service.startSync()).toBe(false);
finishBrands();
await new Promise((resolve) => setImmediate(resolve));
expect(service.isSyncInProgress).toBe(false);
});
});