import { getCustomRepository } from 'typeorm'; import { RetailerProduct } from '@/entities'; import { RetailerProductSource } from '@/entities/types'; import { RetailerKind } from '@/types'; import RetailerProductRepository from '../RetailerProductRepository'; describe('RetailerProductRepository', () => { let repo: RetailerProductRepository; beforeEach(async () => { repo = getCustomRepository(RetailerProductRepository); }); describe('CRUD', () => { it('should be able to create new populated retailer product', async () => { const { retailerProductId } = await repo.upsert({ retailer: RetailerKind.PERIGOLD, source: RetailerProductSource.GOOGLE_SHOPPING, productIdentifiers: ['test12'], data: { asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); const retailerProduct = await RetailerProduct.findOneOrFail( retailerProductId ); expect(retailerProduct).toMatchObject({ id: expect.any(String), identifiers: ['test12'], retailer: RetailerKind.PERIGOLD, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', source: RetailerProductSource.GOOGLE_SHOPPING, url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }); }); it('should be able to create a sparse retailer product', async () => { const { retailerProductId } = await repo.upsert({ retailer: RetailerKind.PERIGOLD, source: RetailerProductSource.GOOGLE_SHOPPING, productIdentifiers: ['test12'], data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); const retailerProduct = await RetailerProduct.findOneOrFail( retailerProductId ); expect(retailerProduct).toMatchObject({ id: expect.any(String), retailer: RetailerKind.PERIGOLD, price: 100, description: 'description', name: 'test', source: RetailerProductSource.GOOGLE_SHOPPING, url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }); }); it('should not be able to create products without identifiers', async () => { const retailer = RetailerKind.PERIGOLD; await expect( repo.upsert({ productIdentifiers: [], source: RetailerProductSource.GOOGLE_SHOPPING, retailer, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"Must provide at least one identifier"` ); }); it('should not be able to create products with mis-formed identifiers', async () => { const retailer = RetailerKind.PERIGOLD; await expect( repo.upsert({ productIdentifiers: [''], source: RetailerProductSource.GOOGLE_SHOPPING, retailer, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }) ).rejects.toThrowErrorMatchingInlineSnapshot( `" is not a valid identifier"` ); }); it('should be able to update products with the same identifier', async () => { const retailer = RetailerKind.PERIGOLD; const id = 'test'; const { retailerProductId } = await repo.upsert({ retailer, productIdentifiers: ['test12'], source: RetailerProductSource.GOOGLE_SHOPPING, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); const retailerProduct = await RetailerProduct.findOneOrFail( retailerProductId ); expect(retailerProduct.description).toBe('description'); await repo.upsert({ productIdentifiers: ['test12'], data: { description: 'updated description', }, retailer, }); const updatedRetailerProduct = await RetailerProduct.findOneOrFail( retailerProductId ); expect(updatedRetailerProduct.description).toBe('updated description'); }); it('does not update products with same identifier across retailers', async () => { const retailer = RetailerKind.PERIGOLD; const id = 'test'; const { retailerProductId } = await repo.upsert({ retailer, source: RetailerProductSource.GOOGLE_SHOPPING, productIdentifiers: ['test12'], data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); const retailerProduct = await RetailerProduct.findOneOrFail( retailerProductId ); expect(retailerProduct.description).toBe('description'); await repo.upsert({ productIdentifiers: ['test12'], source: RetailerProductSource.GOOGLE_SHOPPING, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, retailer: RetailerKind.AMAZON, }); expect(await repo.findByRetailer({ retailer })).toHaveLength(1); expect( await repo.findByRetailer({ retailer: RetailerKind.AMAZON }) ).toHaveLength(1); }); }); describe('identifier resolution', () => { it('should be able to find products by single identifier', async () => { const retailer = RetailerKind.PERIGOLD; const id = 'test12'; const { retailerProductId } = await repo.upsert({ retailer, productIdentifiers: ['test12'], source: RetailerProductSource.GOOGLE_SHOPPING, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); expect( (await repo.findOneByIdentifiers({ identifiers: [id], retailer }))?.id ).toBe(retailerProductId); }); it('should be able to find products with multiple identifiers with all identifiers', async () => { const retailer = RetailerKind.PERIGOLD; const identifiers = ['test1', 'test2']; await repo.upsert({ retailer, productIdentifiers: identifiers, source: RetailerProductSource.GOOGLE_SHOPPING, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); expect( await repo.findOneByIdentifiers({ identifiers, retailer }) ).toMatchObject({ id: expect.any(String), retailer, identifiers, price: 100, description: 'description', name: 'test', source: RetailerProductSource.GOOGLE_SHOPPING, }); }); it('should be able to find products if there are multiple identifiers by a single identifier for the same retailer', async () => { const retailer = RetailerKind.PERIGOLD; const identifiers = ['test1', 'test2']; const { retailerProductId } = await repo.upsert({ retailer, productIdentifiers: identifiers, source: RetailerProductSource.GOOGLE_SHOPPING, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); expect( (await repo.findOneByIdentifiers({ identifiers: ['test1'], retailer })) ?.id ).toBe(retailerProductId); }); it('should not find products with different identifier', async () => { const retailer = RetailerKind.PERIGOLD; const identifiers = ['test1', 'test2']; await repo.upsert({ retailer, productIdentifiers: ['test12'], source: RetailerProductSource.GOOGLE_SHOPPING, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); expect( await repo.findOneByIdentifiers({ identifiers: ['test3'], retailer }) ).toBe(undefined); }); it('should not find products with same identifer for the same retailer', async () => { const retailer = RetailerKind.PERIGOLD; const identifiers = ['test1', 'test2']; await repo.upsert({ retailer, productIdentifiers: ['test12'], source: RetailerProductSource.GOOGLE_SHOPPING, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); expect( await repo.findOneByIdentifiers({ identifiers, retailer: RetailerKind.AMAZON, }) ).toBe(undefined); }); it('upsert with a single matching identifier is able to add additional identifiers', async () => { const retailer = RetailerKind.PERIGOLD; const identifiers = ['test1', 'test2']; await repo.upsert({ retailer, productIdentifiers: identifiers, source: RetailerProductSource.GOOGLE_SHOPPING, data: { price: 100, description: 'description', name: 'test', url: 'https://www.amazon.com/Haussmann-Twist-Stool-High-Walnut/dp/B00KRY0SY2', }, }); await repo.upsert({ retailer, productIdentifiers: [...identifiers, 'test3'], data: {}, }); expect( await repo.findOneByIdentifiers({ identifiers, retailer }) ).toMatchObject({ identifiers: expect.arrayContaining([...identifiers, 'test3']), }); }); }); });