@labdigital/commercetools-mock 2.45.0 → 2.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +56 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +56 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/predicateParser.test.ts +33 -2
- package/src/lib/predicateParser.ts +6 -0
- package/src/product-search.ts +48 -8
- package/src/repositories/cart/index.ts +17 -0
- package/src/repositories/product/helpers.ts +18 -2
- package/src/services/cart.test.ts +25 -0
- package/src/services/customer.test.ts +12 -51
- package/src/services/product.test.ts +154 -70
- package/src/testing/customer.ts +40 -0
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
Category,
|
|
3
3
|
CategoryDraft,
|
|
4
4
|
Image,
|
|
5
|
+
InventoryEntryDraft,
|
|
5
6
|
PriceDraft,
|
|
6
7
|
Product,
|
|
7
8
|
ProductData,
|
|
@@ -20,7 +21,14 @@ import type {
|
|
|
20
21
|
} from "@commercetools/platform-sdk";
|
|
21
22
|
import assert from "assert";
|
|
22
23
|
import supertest from "supertest";
|
|
23
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
afterAll,
|
|
26
|
+
beforeAll,
|
|
27
|
+
beforeEach,
|
|
28
|
+
describe,
|
|
29
|
+
expect,
|
|
30
|
+
test,
|
|
31
|
+
} from "vitest";
|
|
24
32
|
import { CommercetoolsMock } from "../index";
|
|
25
33
|
|
|
26
34
|
const productTypeDraft: ProductTypeDraft = {
|
|
@@ -492,6 +500,10 @@ describe("Product update actions", () => {
|
|
|
492
500
|
expect(response.status).toBe(201);
|
|
493
501
|
});
|
|
494
502
|
|
|
503
|
+
afterAll(async () => {
|
|
504
|
+
ctMock.clear();
|
|
505
|
+
});
|
|
506
|
+
|
|
495
507
|
test("setAttribute masterVariant (staged)", async () => {
|
|
496
508
|
assert(productPublished, "product not created");
|
|
497
509
|
|
|
@@ -1488,76 +1500,148 @@ describe("Product update actions", () => {
|
|
|
1488
1500
|
?.myCustomField,
|
|
1489
1501
|
).toBe("MyRandomValue");
|
|
1490
1502
|
});
|
|
1503
|
+
});
|
|
1491
1504
|
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
// Find product with sku "1337" to be part of the search results
|
|
1523
|
-
const productFound = results.find(
|
|
1524
|
-
(result) => result?.productProjection?.masterVariant?.sku === "1337",
|
|
1525
|
-
);
|
|
1526
|
-
expect(productFound).toBeDefined();
|
|
1527
|
-
|
|
1528
|
-
const priceCurrencyMatch = results.find((result) =>
|
|
1529
|
-
result?.productProjection?.masterVariant?.prices?.find(
|
|
1530
|
-
(price) => price?.value?.currencyCode === "EUR",
|
|
1531
|
-
),
|
|
1532
|
-
);
|
|
1533
|
-
expect(priceCurrencyMatch).toBeDefined();
|
|
1534
|
-
}
|
|
1535
|
-
{
|
|
1536
|
-
const body: ProductSearchRequest = {
|
|
1537
|
-
limit: 88,
|
|
1538
|
-
offset: 88,
|
|
1539
|
-
};
|
|
1540
|
-
|
|
1541
|
-
const response = await supertest(ctMock.app)
|
|
1542
|
-
.post("/dummy/products/search")
|
|
1543
|
-
.send(body);
|
|
1544
|
-
|
|
1545
|
-
const pagedSearchResponse: ProductPagedSearchResponse = response.body;
|
|
1546
|
-
expect(pagedSearchResponse.limit).toBe(88);
|
|
1547
|
-
expect(pagedSearchResponse.offset).toBe(88);
|
|
1548
|
-
expect(pagedSearchResponse.total).toBeGreaterThan(0);
|
|
1549
|
-
|
|
1550
|
-
// No results, since we start at offset 88
|
|
1551
|
-
const results: ProductSearchResult[] = pagedSearchResponse.results;
|
|
1552
|
-
expect(results).toBeDefined();
|
|
1553
|
-
expect(results.length).toBe(0);
|
|
1554
|
-
|
|
1555
|
-
// Product with sku "1337" should not be part of the results
|
|
1556
|
-
const productFound = results.find(
|
|
1557
|
-
(result) => result?.productProjection?.masterVariant?.sku === "1337",
|
|
1558
|
-
);
|
|
1559
|
-
expect(productFound).toBeUndefined();
|
|
1560
|
-
}
|
|
1505
|
+
// Test the general product search implementation
|
|
1506
|
+
describe("Product Search - Generic", () => {
|
|
1507
|
+
const ctMock = new CommercetoolsMock();
|
|
1508
|
+
|
|
1509
|
+
async function addInventoryEntry(sku: string, quantity: number) {
|
|
1510
|
+
const inventoryEntryDraft: InventoryEntryDraft = {
|
|
1511
|
+
key: `${sku}_stock`,
|
|
1512
|
+
sku,
|
|
1513
|
+
quantityOnStock: quantity,
|
|
1514
|
+
supplyChannel: {
|
|
1515
|
+
typeId: "channel",
|
|
1516
|
+
id: "dummy-inventory-channel",
|
|
1517
|
+
},
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1520
|
+
await supertest(ctMock.app)
|
|
1521
|
+
.post("/dummy/inventory")
|
|
1522
|
+
.send(inventoryEntryDraft);
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
beforeAll(async () => {
|
|
1526
|
+
await beforeAllProductTests(ctMock);
|
|
1527
|
+
|
|
1528
|
+
new Array(24).fill(null).forEach(async () => {
|
|
1529
|
+
const response = await supertest(ctMock.app)
|
|
1530
|
+
.post("/dummy/products")
|
|
1531
|
+
.send(publishedProductDraft);
|
|
1532
|
+
|
|
1533
|
+
expect(response.status).toBe(201);
|
|
1561
1534
|
});
|
|
1562
1535
|
});
|
|
1536
|
+
|
|
1537
|
+
test("Pagination", async () => {
|
|
1538
|
+
{
|
|
1539
|
+
const body: ProductSearchRequest = {
|
|
1540
|
+
productProjectionParameters: {
|
|
1541
|
+
storeProjection: "dummy-store",
|
|
1542
|
+
localeProjection: ["en-US"],
|
|
1543
|
+
priceCurrency: "EUR",
|
|
1544
|
+
priceChannel: "dummy-channel",
|
|
1545
|
+
expand: ["categories[*]", "categories[*].ancestors[*]"],
|
|
1546
|
+
},
|
|
1547
|
+
limit: 24,
|
|
1548
|
+
};
|
|
1549
|
+
const response = await supertest(ctMock.app)
|
|
1550
|
+
.post("/dummy/products/search")
|
|
1551
|
+
.send(body);
|
|
1552
|
+
|
|
1553
|
+
const pagedSearchResponse: ProductPagedSearchResponse = response.body;
|
|
1554
|
+
expect(pagedSearchResponse.limit).toBe(24);
|
|
1555
|
+
expect(pagedSearchResponse.offset).toBe(0);
|
|
1556
|
+
expect(pagedSearchResponse.total).toBeGreaterThan(0);
|
|
1557
|
+
|
|
1558
|
+
// Deliberately not supported fow now
|
|
1559
|
+
expect(pagedSearchResponse.facets).toEqual([]);
|
|
1560
|
+
|
|
1561
|
+
const results: ProductSearchResult[] = pagedSearchResponse.results;
|
|
1562
|
+
expect(results).toBeDefined();
|
|
1563
|
+
expect(results.length).toBeGreaterThan(0);
|
|
1564
|
+
|
|
1565
|
+
// Find product with sku "1337" to be part of the search results
|
|
1566
|
+
const productFound = results.find(
|
|
1567
|
+
(result) => result?.productProjection?.masterVariant?.sku === "1337",
|
|
1568
|
+
);
|
|
1569
|
+
expect(productFound).toBeDefined();
|
|
1570
|
+
|
|
1571
|
+
const priceCurrencyMatch = results.find((result) =>
|
|
1572
|
+
result?.productProjection?.masterVariant?.prices?.find(
|
|
1573
|
+
(price) => price?.value?.currencyCode === "EUR",
|
|
1574
|
+
),
|
|
1575
|
+
);
|
|
1576
|
+
expect(priceCurrencyMatch).toBeDefined();
|
|
1577
|
+
}
|
|
1578
|
+
{
|
|
1579
|
+
const body: ProductSearchRequest = {
|
|
1580
|
+
limit: 88,
|
|
1581
|
+
offset: 88,
|
|
1582
|
+
};
|
|
1583
|
+
|
|
1584
|
+
const response = await supertest(ctMock.app)
|
|
1585
|
+
.post("/dummy/products/search")
|
|
1586
|
+
.send(body);
|
|
1587
|
+
|
|
1588
|
+
const pagedSearchResponse: ProductPagedSearchResponse = response.body;
|
|
1589
|
+
expect(pagedSearchResponse.limit).toBe(88);
|
|
1590
|
+
expect(pagedSearchResponse.offset).toBe(88);
|
|
1591
|
+
expect(pagedSearchResponse.total).toBeGreaterThan(0);
|
|
1592
|
+
|
|
1593
|
+
// No results, since we start at offset 88
|
|
1594
|
+
const results: ProductSearchResult[] = pagedSearchResponse.results;
|
|
1595
|
+
expect(results).toBeDefined();
|
|
1596
|
+
expect(results.length).toBe(0);
|
|
1597
|
+
|
|
1598
|
+
// Product with sku "1337" should not be part of the results
|
|
1599
|
+
const productFound = results.find(
|
|
1600
|
+
(result) => result?.productProjection?.masterVariant?.sku === "1337",
|
|
1601
|
+
);
|
|
1602
|
+
expect(productFound).toBeUndefined();
|
|
1603
|
+
}
|
|
1604
|
+
});
|
|
1605
|
+
|
|
1606
|
+
test("Filter on inventory", async () => {
|
|
1607
|
+
const body: ProductSearchRequest = {
|
|
1608
|
+
query: {
|
|
1609
|
+
exact: {
|
|
1610
|
+
field: "variants.availability.isOnStockForChannel",
|
|
1611
|
+
value: "dummy-inventory-channel",
|
|
1612
|
+
},
|
|
1613
|
+
},
|
|
1614
|
+
productProjectionParameters: {
|
|
1615
|
+
storeProjection: "dummy-store",
|
|
1616
|
+
localeProjection: ["en-US"],
|
|
1617
|
+
priceCurrency: "EUR",
|
|
1618
|
+
priceChannel: "dummy-channel",
|
|
1619
|
+
},
|
|
1620
|
+
limit: 1,
|
|
1621
|
+
};
|
|
1622
|
+
|
|
1623
|
+
const response1 = await supertest(ctMock.app)
|
|
1624
|
+
.post("/dummy/products/search")
|
|
1625
|
+
.send(body);
|
|
1626
|
+
|
|
1627
|
+
const pagedSearchResponse1: ProductPagedSearchResponse = response1.body;
|
|
1628
|
+
|
|
1629
|
+
expect(pagedSearchResponse1.results.length).toBe(0);
|
|
1630
|
+
|
|
1631
|
+
await addInventoryEntry(
|
|
1632
|
+
publishedProductDraft.variants?.[0]?.sku as string,
|
|
1633
|
+
10,
|
|
1634
|
+
);
|
|
1635
|
+
|
|
1636
|
+
const response2 = await supertest(ctMock.app)
|
|
1637
|
+
.post("/dummy/products/search")
|
|
1638
|
+
.send(body);
|
|
1639
|
+
|
|
1640
|
+
const pagedSearchResponse2: ProductPagedSearchResponse = response2.body;
|
|
1641
|
+
|
|
1642
|
+
const productFound = pagedSearchResponse2.results.find(
|
|
1643
|
+
(result) => result?.productProjection?.masterVariant?.sku === "1337",
|
|
1644
|
+
);
|
|
1645
|
+
expect(productFound).toBeDefined();
|
|
1646
|
+
});
|
|
1563
1647
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Customer, CustomerDraft } from "@commercetools/platform-sdk";
|
|
2
|
+
import { Factory } from "fishery";
|
|
3
|
+
import supertest from "supertest";
|
|
4
|
+
import type { CommercetoolsMock } from "~src/ctMock";
|
|
5
|
+
|
|
6
|
+
export const customerDraftFactory = (m: CommercetoolsMock) =>
|
|
7
|
+
Factory.define<CustomerDraft, CustomerDraft, Customer>(({ onCreate }) => {
|
|
8
|
+
onCreate(async (draft) => {
|
|
9
|
+
const response = await supertest(m.app)
|
|
10
|
+
.post(`/dummy/customers`)
|
|
11
|
+
.send(draft);
|
|
12
|
+
|
|
13
|
+
return response.body.customer;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
email: "customer@example.com",
|
|
18
|
+
firstName: "John",
|
|
19
|
+
lastName: "Doe",
|
|
20
|
+
locale: "nl-NL",
|
|
21
|
+
password: "my-secret-pw",
|
|
22
|
+
addresses: [
|
|
23
|
+
{
|
|
24
|
+
firstName: "John",
|
|
25
|
+
lastName: "Doe",
|
|
26
|
+
streetName: "Street name",
|
|
27
|
+
streetNumber: "42",
|
|
28
|
+
postalCode: "1234 AB",
|
|
29
|
+
city: "Utrecht",
|
|
30
|
+
country: "NL",
|
|
31
|
+
company: "Lab Digital",
|
|
32
|
+
phone: "+31612345678",
|
|
33
|
+
email: "customer@example.com",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
isEmailVerified: false,
|
|
37
|
+
stores: [],
|
|
38
|
+
authenticationMode: "Password",
|
|
39
|
+
};
|
|
40
|
+
});
|