@labdigital/commercetools-mock 2.34.3 → 2.36.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.
@@ -3,6 +3,12 @@ import type {
3
3
  Cart,
4
4
  CentPrecisionMoney,
5
5
  ProductDraft,
6
+ ShippingMethod,
7
+ ShippingMethodDraft,
8
+ ShippingMethodResourceIdentifier,
9
+ TaxCategory,
10
+ TaxCategoryDraft,
11
+ Zone,
6
12
  } from "@commercetools/platform-sdk";
7
13
  import assert from "assert";
8
14
  import supertest from "supertest";
@@ -89,6 +95,41 @@ describe("Cart Update Actions", () => {
89
95
  cart = response.body;
90
96
  };
91
97
 
98
+ const createZone = async (country: string): Promise<Zone> => {
99
+ const response = await supertest(ctMock.app)
100
+ .post("/dummy/zones")
101
+ .send({
102
+ name: country,
103
+ locations: [
104
+ {
105
+ country,
106
+ },
107
+ ],
108
+ });
109
+ expect(response.status).toBe(201);
110
+ return response.body;
111
+ };
112
+
113
+ const createTaxCategory = async (
114
+ draft: TaxCategoryDraft,
115
+ ): Promise<TaxCategory> => {
116
+ const response = await supertest(ctMock.app)
117
+ .post("/dummy/tax-categories")
118
+ .send(draft);
119
+ expect(response.status).toBe(201);
120
+ return response.body;
121
+ };
122
+
123
+ const createShippingMethod = async (
124
+ draft: ShippingMethodDraft,
125
+ ): Promise<ShippingMethod> => {
126
+ const response = await supertest(ctMock.app)
127
+ .post("/dummy/shipping-methods")
128
+ .send(draft);
129
+ expect(response.status).toBe(201);
130
+ return response.body;
131
+ };
132
+
92
133
  const productDraft: ProductDraft = {
93
134
  name: {
94
135
  "nl-NL": "test product",
@@ -672,6 +713,7 @@ describe("Cart Update Actions", () => {
672
713
  },
673
714
  });
674
715
  });
716
+
675
717
  test("setShippingAddressCustomType", async () => {
676
718
  assert(cart, "cart not created");
677
719
 
@@ -739,6 +781,381 @@ describe("Cart Update Actions", () => {
739
781
  },
740
782
  });
741
783
  });
784
+
785
+ describe("setShippingMethod", () => {
786
+ let standardShippingMethod: ShippingMethod;
787
+ let standardExcludedShippingMethod: ShippingMethod;
788
+ beforeEach(async () => {
789
+ assert(cart, "cart not created");
790
+ const nlZone = await createZone("NL");
791
+ const frZone = await createZone("FR");
792
+ const standardTax = await createTaxCategory({
793
+ name: "Standard tax category",
794
+ key: "standard",
795
+ rates: [
796
+ {
797
+ name: "FR standard tax rate",
798
+ amount: 0.2,
799
+ includedInPrice: true,
800
+ country: "FR",
801
+ },
802
+ {
803
+ name: "NL standard tax rate",
804
+ amount: 0.21,
805
+ includedInPrice: true,
806
+ country: "NL",
807
+ },
808
+ ],
809
+ });
810
+ await createTaxCategory({
811
+ name: "Reduced tax category",
812
+ key: "reduced",
813
+ rates: [
814
+ {
815
+ name: "FR reduced tax rate",
816
+ amount: 0.1,
817
+ includedInPrice: true,
818
+ country: "FR",
819
+ },
820
+ {
821
+ name: "NL reduced tax rate",
822
+ amount: 0.09,
823
+ includedInPrice: true,
824
+ country: "NL",
825
+ },
826
+ ],
827
+ });
828
+ const standardExcludedTax = await createTaxCategory({
829
+ name: "Tax category that is excluded from price",
830
+ key: "standard-excluded",
831
+ rates: [
832
+ {
833
+ name: "FR standard-excluded tax rate",
834
+ amount: 0.2,
835
+ includedInPrice: false,
836
+ country: "FR",
837
+ },
838
+ {
839
+ name: "NL standard-excluded tax rate",
840
+ amount: 0.21,
841
+ includedInPrice: false,
842
+ country: "NL",
843
+ },
844
+ ],
845
+ });
846
+ standardShippingMethod = await createShippingMethod({
847
+ isDefault: false,
848
+ key: "standard",
849
+ name: "Standard shipping",
850
+ taxCategory: {
851
+ typeId: "tax-category",
852
+ id: standardTax.id,
853
+ },
854
+ zoneRates: [
855
+ {
856
+ zone: {
857
+ typeId: "zone",
858
+ id: nlZone.id,
859
+ },
860
+ shippingRates: [
861
+ {
862
+ price: {
863
+ type: "centPrecision",
864
+ currencyCode: "EUR",
865
+ centAmount: 499,
866
+ fractionDigits: 2,
867
+ },
868
+ },
869
+ ],
870
+ },
871
+ {
872
+ zone: {
873
+ typeId: "zone",
874
+ id: frZone.id,
875
+ },
876
+ shippingRates: [
877
+ {
878
+ price: {
879
+ type: "centPrecision",
880
+ currencyCode: "EUR",
881
+ centAmount: 699,
882
+ fractionDigits: 2,
883
+ },
884
+ },
885
+ ],
886
+ },
887
+ ],
888
+ });
889
+
890
+ standardExcludedShippingMethod = await createShippingMethod({
891
+ isDefault: false,
892
+ key: "standard-excluded",
893
+ name: "Standard shipping with tax excluded from price",
894
+ taxCategory: {
895
+ typeId: "tax-category",
896
+ id: standardExcludedTax.id,
897
+ },
898
+ zoneRates: [
899
+ {
900
+ zone: {
901
+ typeId: "zone",
902
+ id: nlZone.id,
903
+ },
904
+ shippingRates: [
905
+ {
906
+ price: {
907
+ type: "centPrecision",
908
+ currencyCode: "EUR",
909
+ centAmount: 499,
910
+ fractionDigits: 2,
911
+ },
912
+ },
913
+ ],
914
+ },
915
+ {
916
+ zone: {
917
+ typeId: "zone",
918
+ id: frZone.id,
919
+ },
920
+ shippingRates: [
921
+ {
922
+ price: {
923
+ type: "centPrecision",
924
+ currencyCode: "EUR",
925
+ centAmount: 699,
926
+ fractionDigits: 2,
927
+ },
928
+ },
929
+ ],
930
+ },
931
+ ],
932
+ });
933
+ await createShippingMethod({
934
+ isDefault: false,
935
+ key: "express",
936
+ name: "Express shipping",
937
+ taxCategory: {
938
+ typeId: "tax-category",
939
+ id: standardTax.id,
940
+ },
941
+ zoneRates: [
942
+ {
943
+ zone: {
944
+ typeId: "zone",
945
+ id: nlZone.id,
946
+ },
947
+ shippingRates: [
948
+ {
949
+ price: {
950
+ type: "centPrecision",
951
+ currencyCode: "EUR",
952
+ centAmount: 899,
953
+ fractionDigits: 2,
954
+ },
955
+ },
956
+ ],
957
+ },
958
+ {
959
+ zone: {
960
+ typeId: "zone",
961
+ id: frZone.id,
962
+ },
963
+ shippingRates: [
964
+ {
965
+ price: {
966
+ type: "centPrecision",
967
+ currencyCode: "EUR",
968
+ centAmount: 1099,
969
+ fractionDigits: 2,
970
+ },
971
+ },
972
+ ],
973
+ },
974
+ ],
975
+ });
976
+
977
+ expect(
978
+ (
979
+ await supertest(ctMock.app)
980
+ .post(`/dummy/carts/${cart.id}`)
981
+ .send({
982
+ version: 1,
983
+ actions: [
984
+ {
985
+ action: "setShippingAddress",
986
+ address: {
987
+ streetName: "Street name",
988
+ city: "Utrecht",
989
+ country: "NL",
990
+ },
991
+ },
992
+ ],
993
+ })
994
+ ).status,
995
+ ).toBe(200);
996
+ });
997
+
998
+ test("correctly sets shipping method", async () => {
999
+ assert(cart, "cart not created");
1000
+
1001
+ const shippingMethod: ShippingMethodResourceIdentifier = {
1002
+ typeId: "shipping-method",
1003
+ id: standardShippingMethod.id,
1004
+ };
1005
+
1006
+ const response = await supertest(ctMock.app)
1007
+ .post(`/dummy/carts/${cart.id}`)
1008
+ .send({
1009
+ version: 2,
1010
+ actions: [{ action: "setShippingMethod", shippingMethod }],
1011
+ });
1012
+ expect(response.status).toBe(200);
1013
+ expect(response.body.version).toBe(3);
1014
+ expect(response.body.shippingInfo.shippingMethod.id).toEqual(
1015
+ standardShippingMethod.id,
1016
+ );
1017
+ });
1018
+
1019
+ test("correctly sets shippingInfo rates + tax when includedInPrice: true", async () => {
1020
+ assert(cart, "cart not created");
1021
+ assert(standardShippingMethod, "shipping method not created");
1022
+
1023
+ const shippingMethod: ShippingMethodResourceIdentifier = {
1024
+ typeId: "shipping-method",
1025
+ id: standardShippingMethod.id,
1026
+ };
1027
+
1028
+ const response = await supertest(ctMock.app)
1029
+ .post(`/dummy/carts/${cart.id}`)
1030
+ .send({
1031
+ version: 2,
1032
+ actions: [{ action: "setShippingMethod", shippingMethod }],
1033
+ });
1034
+ expect(response.status).toBe(200);
1035
+ expect(response.body.version).toBe(3);
1036
+ expect(response.body.shippingInfo.shippingRate.price).toMatchObject({
1037
+ centAmount: 499,
1038
+ currencyCode: "EUR",
1039
+ fractionDigits: 2,
1040
+ type: "centPrecision",
1041
+ });
1042
+ expect(response.body.shippingInfo.price).toMatchObject({
1043
+ centAmount: 499,
1044
+ currencyCode: "EUR",
1045
+ fractionDigits: 2,
1046
+ type: "centPrecision",
1047
+ });
1048
+ expect(response.body.shippingInfo.taxRate).toMatchObject({
1049
+ name: "NL standard tax rate",
1050
+ amount: 0.21,
1051
+ includedInPrice: true,
1052
+ country: "NL",
1053
+ });
1054
+ expect(response.body.shippingInfo.taxedPrice).toMatchObject({
1055
+ totalNet: {
1056
+ type: "centPrecision",
1057
+ centAmount: 412,
1058
+ currencyCode: "EUR",
1059
+ fractionDigits: 2,
1060
+ },
1061
+ totalGross: {
1062
+ type: "centPrecision",
1063
+ centAmount: 499,
1064
+ currencyCode: "EUR",
1065
+ fractionDigits: 2,
1066
+ },
1067
+ taxPortions: [
1068
+ {
1069
+ name: "NL standard tax rate",
1070
+ rate: 0.21,
1071
+ amount: {
1072
+ type: "centPrecision",
1073
+ centAmount: 87,
1074
+ currencyCode: "EUR",
1075
+ fractionDigits: 2,
1076
+ },
1077
+ },
1078
+ ],
1079
+ totalTax: {
1080
+ type: "centPrecision",
1081
+ centAmount: 87,
1082
+ currencyCode: "EUR",
1083
+ fractionDigits: 2,
1084
+ },
1085
+ });
1086
+ });
1087
+
1088
+ test("correctly sets shippingInfo rates + tax when includedInPrice: false", async () => {
1089
+ assert(cart, "cart not created");
1090
+ assert(standardExcludedShippingMethod, "shipping method not created");
1091
+
1092
+ const shippingMethod: ShippingMethodResourceIdentifier = {
1093
+ typeId: "shipping-method",
1094
+ id: standardExcludedShippingMethod.id,
1095
+ };
1096
+
1097
+ const response = await supertest(ctMock.app)
1098
+ .post(`/dummy/carts/${cart.id}`)
1099
+ .send({
1100
+ version: 2,
1101
+ actions: [{ action: "setShippingMethod", shippingMethod }],
1102
+ });
1103
+ expect(response.status).toBe(200);
1104
+ expect(response.body.version).toBe(3);
1105
+ expect(response.body.shippingInfo.shippingRate.price).toMatchObject({
1106
+ centAmount: 499,
1107
+ currencyCode: "EUR",
1108
+ fractionDigits: 2,
1109
+ type: "centPrecision",
1110
+ });
1111
+ // TODO: should this be gross or net? docs unclear (currently always just returns the shipping rate (tier) price)
1112
+ expect(response.body.shippingInfo.price).toMatchObject({
1113
+ centAmount: 499,
1114
+ currencyCode: "EUR",
1115
+ fractionDigits: 2,
1116
+ type: "centPrecision",
1117
+ });
1118
+ expect(response.body.shippingInfo.taxRate).toMatchObject({
1119
+ name: "NL standard-excluded tax rate",
1120
+ amount: 0.21,
1121
+ includedInPrice: false,
1122
+ country: "NL",
1123
+ });
1124
+ expect(response.body.shippingInfo.taxedPrice).toMatchObject({
1125
+ totalNet: {
1126
+ type: "centPrecision",
1127
+ centAmount: 499,
1128
+ currencyCode: "EUR",
1129
+ fractionDigits: 2,
1130
+ },
1131
+ totalGross: {
1132
+ type: "centPrecision",
1133
+ centAmount: 604,
1134
+ currencyCode: "EUR",
1135
+ fractionDigits: 2,
1136
+ },
1137
+ taxPortions: [
1138
+ {
1139
+ name: "NL standard-excluded tax rate",
1140
+ rate: 0.21,
1141
+ amount: {
1142
+ type: "centPrecision",
1143
+ centAmount: 105,
1144
+ currencyCode: "EUR",
1145
+ fractionDigits: 2,
1146
+ },
1147
+ },
1148
+ ],
1149
+ totalTax: {
1150
+ type: "centPrecision",
1151
+ centAmount: 105,
1152
+ currencyCode: "EUR",
1153
+ fractionDigits: 2,
1154
+ },
1155
+ });
1156
+ });
1157
+ });
1158
+
742
1159
  test("setLineItemShippingDetails", async () => {
743
1160
  const product = await supertest(ctMock.app)
744
1161
  .post(`/dummy/products`)
@@ -1,4 +1,8 @@
1
- import { Customer, CustomerToken } from "@commercetools/platform-sdk";
1
+ import {
2
+ Customer,
3
+ CustomerDraft,
4
+ CustomerToken,
5
+ } from "@commercetools/platform-sdk";
2
6
  import assert from "assert";
3
7
  import supertest from "supertest";
4
8
  import { afterEach, beforeEach, describe, expect, test } from "vitest";
@@ -7,6 +11,46 @@ import { CommercetoolsMock, getBaseResourceProperties } from "../index";
7
11
 
8
12
  const ctMock = new CommercetoolsMock();
9
13
 
14
+ afterEach(() => {
15
+ ctMock.clear();
16
+ });
17
+
18
+ describe("Customer create", () => {
19
+ test("create new customer", async () => {
20
+ const draft: CustomerDraft = {
21
+ email: "new-user@example.com",
22
+ password: "supersecret",
23
+ authenticationMode: "Password",
24
+ stores: [],
25
+ addresses: [
26
+ {
27
+ key: "address-key",
28
+ firstName: "John",
29
+ lastName: "Doe",
30
+ streetName: "Main Street",
31
+ streetNumber: "1",
32
+ postalCode: "12345",
33
+ country: "DE",
34
+ },
35
+ ],
36
+ billingAddresses: [0],
37
+ shippingAddresses: [0],
38
+ };
39
+
40
+ const response = await supertest(ctMock.app)
41
+ .post(`/dummy/customers`)
42
+ .send(draft);
43
+
44
+ const customer = response.body.customer as Customer;
45
+ expect(response.status, JSON.stringify(customer)).toBe(201);
46
+ expect(customer.version).toBe(1);
47
+ expect(customer.defaultBillingAddressId).toBeUndefined();
48
+ expect(customer.defaultShippingAddressId).toBeUndefined();
49
+ expect(customer.billingAddressIds).toHaveLength(1);
50
+ expect(customer.shippingAddressIds).toHaveLength(1);
51
+ });
52
+ });
53
+
10
54
  describe("Customer Update Actions", () => {
11
55
  let customer: Customer | undefined;
12
56
 
@@ -25,10 +69,6 @@ describe("Customer Update Actions", () => {
25
69
  ctMock.project("dummy").add("customer", customer);
26
70
  });
27
71
 
28
- afterEach(() => {
29
- ctMock.clear();
30
- });
31
-
32
72
  test("exists", async () => {
33
73
  assert(customer, "customer not created");
34
74
 
@@ -12,6 +12,7 @@ import { CustomerGroupService } from "./customer-group";
12
12
  import { DiscountCodeService } from "./discount-code";
13
13
  import { ExtensionServices } from "./extension";
14
14
  import { InventoryEntryService } from "./inventory-entry";
15
+ import { MyBusinessUnitService } from "./my-business-unit";
15
16
  import { MyCartService } from "./my-cart";
16
17
  import { MyCustomerService } from "./my-customer";
17
18
  import { MyOrderService } from "./my-order";
@@ -66,6 +67,7 @@ export const createServices = (
66
67
  "my-cart": new MyCartService(router, repos["my-cart"]),
67
68
  "my-order": new MyOrderService(router, repos["my-order"]),
68
69
  "my-customer": new MyCustomerService(router, repos["my-customer"]),
70
+ "my-business-unit": new MyBusinessUnitService(router, repos["business-unit"]),
69
71
  "my-payment": new MyPaymentService(router, repos["my-payment"]),
70
72
  "my-shopping-list": new MyShoppingListService(
71
73
  router,
@@ -0,0 +1,28 @@
1
+ import { Router } from "express";
2
+ import { BusinessUnitRepository } from "~src/repositories/business-unit";
3
+ import AbstractService from "./abstract";
4
+
5
+ export class MyBusinessUnitService extends AbstractService {
6
+ public repository: BusinessUnitRepository;
7
+
8
+ constructor(parent: Router, repository: BusinessUnitRepository) {
9
+ super(parent);
10
+ this.repository = repository;
11
+ }
12
+
13
+ getBasePath() {
14
+ return "me";
15
+ }
16
+
17
+ registerRoutes(parent: Router) {
18
+ // Overwrite this function to be able to handle /me/business-units path.
19
+ const basePath = this.getBasePath();
20
+ const router = Router({ mergeParams: true });
21
+
22
+ this.extraRoutes(router);
23
+
24
+ router.get("/business-units/", this.get.bind(this));
25
+
26
+ parent.use(`/${basePath}`, router);
27
+ }
28
+ }
@@ -35,6 +35,8 @@ describe("Me", () => {
35
35
  version: 1,
36
36
  isEmailVerified: false,
37
37
  addresses: [],
38
+ billingAddressIds: [],
39
+ shippingAddressIds: [],
38
40
  id: expect.anything(),
39
41
  createdAt: expect.anything(),
40
42
  lastModifiedAt: expect.anything(),
@@ -7,7 +7,7 @@ import { describe, expect, it } from "vitest";
7
7
  import {
8
8
  markMatchingShippingRate,
9
9
  markMatchingShippingRatePriceTiers,
10
- } from "./shippingCalculator";
10
+ } from "./shipping";
11
11
 
12
12
  // describe('markMatchingShippingMethods', () => {
13
13
  // const zones: Record<string, Zone> = {