63 lines
2.6 KiB
TypeScript
63 lines
2.6 KiB
TypeScript
import { CustomersService } from './customers.service';
|
|||
|
|
|
||
|
|
/**
|
||
|
|
* `GET customer/me/orders` must carry each item's product and variant.
|
||
|
|
*
|
||
|
|
* The apps used to label order rows by downloading the ENTIRE catalogue and
|
||
|
|
* joining it in the browser (composables/useOrderItemProduct.ts). With the real
|
||
|
|
* catalogue at ~16k products that is the wrong trade for a few row labels, and
|
||
|
|
* it was also broken for the case order history exists for: a product that has
|
||
|
|
* since left the storefront is absent from the catalogue, so the row rendered
|
||
|
|
* blank.
|
||
|
|
*
|
||
|
|
* Both apps now read these fields straight off the item, so the include is part
|
||
|
|
* of the contract — hence a test, which this method did not have.
|
||
|
|
*/
|
||
|
|
describe('CustomersService.getOrders — items carry their product', () => {
|
||
|
|
function setup() {
|
||
|
|
const findMany = jest.fn().mockResolvedValue([]);
|
||
|
|
const prisma = { order: { findMany } };
|
||
|
|
// getOrders touches neither the accounting sync nor anything on it.
|
||
|
|
const service = new CustomersService(prisma as never, {} as never);
|
||
|
|
return { service, findMany };
|
||
|
|
}
|
||
|
|
|
||
|
|
it('includes the variant, its product and the first image', async () => {
|
||
|
|
const { service, findMany } = setup();
|
||
|
|
await service.getOrders('c1');
|
||
|
|
|
||
|
|
const include = findMany.mock.calls[0][0].include;
|
||
|
|
const variant = include.items.include.productVariant;
|
||
|
|
|
||
|
|
expect(variant.select.title).toBe(true);
|
||
|
|
expect(variant.select.product.select.title).toBe(true);
|
||
|
|
// images[0] is the product's main photo, so it must be ordered and limited
|
||
|
|
// to one — the apps read `images[0].url` and nothing else.
|
||
|
|
expect(variant.select.product.select.images).toMatchObject({
|
||
|
|
orderBy: { sortOrder: 'asc' },
|
||
|
|
take: 1,
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('is scoped to the caller and newest first', async () => {
|
||
|
|
// Guards the two properties that were already here: one customer must never
|
||
|
|
// receive another's orders, and the list is reverse-chronological.
|
||
|
|
const { service, findMany } = setup();
|
||
|
|
await service.getOrders('c1');
|
||
|
|
expect(findMany.mock.calls[0][0]).toMatchObject({
|
||
|
|
where: { customerId: 'c1' },
|
||
|
|
orderBy: { createdAt: 'desc' },
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not filter the product by storefront visibility', async () => {
|
||
|
|
// Deliberate: an order for a product that has since been deactivated, or
|
||
|
|
// had its photo removed, must still show what was bought. The storefront
|
||
|
|
// rules apply to the catalogue, not to history.
|
||
|
|
const { service, findMany } = setup();
|
||
|
|
await service.getOrders('c1');
|
||
|
|
const product = findMany.mock.calls[0][0].include.items.include.productVariant.select.product;
|
||
|
|
expect(product.where).toBeUndefined();
|
||
|
|
});
|
||
|
|
});
|