@unchainedshop/core-products 2.0.0-rc.4 → 2.0.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/jest.config.js +4 -0
- package/lib/mock/product.d.ts +25 -0
- package/lib/mock/product.js +51 -0
- package/lib/mock/product.js.map +1 -0
- package/package.json +7 -7
- package/src/director/ProductPricingSheet.test.ts +180 -0
- package/{tests → src}/mock/product.js +0 -0
- package/{tests/products-index.test.js → src/module/buildFindSelector.test.ts} +21 -16
- package/src/module/utils/configureProductPrices.test.ts +98 -0
- package/src/module/utils/getPriceLevels.test.ts +84 -0
- package/src/module/utils/getPriceRange.test.ts +53 -0
- package/tests/product-index.test.ts +7 -0
- package/tsconfig.json +4 -22
- package/tests/configureProductPrices.test.js +0 -318
- package/tests/products-review.test.js +0 -74
package/jest.config.js
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare namespace _default {
|
|
2
|
+
const _id: string;
|
|
3
|
+
const type: string;
|
|
4
|
+
const status: string;
|
|
5
|
+
const sequence: number;
|
|
6
|
+
const authorId: string;
|
|
7
|
+
const tags: any[];
|
|
8
|
+
const created: Date;
|
|
9
|
+
const createdBy: string;
|
|
10
|
+
const slugs: string[];
|
|
11
|
+
const updated: Date;
|
|
12
|
+
const updatedBy: string;
|
|
13
|
+
namespace commerce {
|
|
14
|
+
const pricing: {
|
|
15
|
+
amount: number;
|
|
16
|
+
maxQuantity: number;
|
|
17
|
+
isTaxable: boolean;
|
|
18
|
+
isNetPrice: boolean;
|
|
19
|
+
currencyCode: string;
|
|
20
|
+
countryCode: string;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
const published: Date;
|
|
24
|
+
}
|
|
25
|
+
export default _default;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
_id: 'aaf98dd6b1d4d6c0de605b9d',
|
|
3
|
+
type: 'SIMPLE_PRODUCT',
|
|
4
|
+
status: 'ACTIVE',
|
|
5
|
+
sequence: 10,
|
|
6
|
+
authorId: 'PKve0k9fLCUzn2EUi',
|
|
7
|
+
tags: [],
|
|
8
|
+
created: new Date('2022-10-28T10:41:13.346Z'),
|
|
9
|
+
createdBy: 'PKve0k9fLCUzn2EUi',
|
|
10
|
+
slugs: ['test'],
|
|
11
|
+
updated: new Date('2022-12-04T13:50:24.245Z'),
|
|
12
|
+
updatedBy: 'PKve0k9fLCUzn2EUi',
|
|
13
|
+
commerce: {
|
|
14
|
+
pricing: [
|
|
15
|
+
{
|
|
16
|
+
amount: 1000,
|
|
17
|
+
maxQuantity: null,
|
|
18
|
+
isTaxable: false,
|
|
19
|
+
isNetPrice: false,
|
|
20
|
+
currencyCode: 'CHF',
|
|
21
|
+
countryCode: 'CH',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
amount: 20000,
|
|
25
|
+
maxQuantity: 2,
|
|
26
|
+
isTaxable: true,
|
|
27
|
+
isNetPrice: true,
|
|
28
|
+
currencyCode: 'ETB',
|
|
29
|
+
countryCode: 'ET',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
amount: 1,
|
|
33
|
+
maxQuantity: 1,
|
|
34
|
+
isTaxable: false,
|
|
35
|
+
isNetPrice: false,
|
|
36
|
+
currencyCode: 'ETH',
|
|
37
|
+
countryCode: 'CH',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
amount: 750,
|
|
41
|
+
maxQuantity: 2,
|
|
42
|
+
isTaxable: false,
|
|
43
|
+
isNetPrice: false,
|
|
44
|
+
currencyCode: 'CHF',
|
|
45
|
+
countryCode: 'CH',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
published: new Date('2022-12-04T13:31:26.406Z'),
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=product.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product.js","sourceRoot":"","sources":["../../src/mock/product.js"],"names":[],"mappings":"AAAA,eAAe;IACb,GAAG,EAAE,0BAA0B;IAC/B,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,mBAAmB;IAC7B,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,IAAI,IAAI,CAAC,0BAA0B,CAAC;IAC7C,SAAS,EAAE,mBAAmB;IAC9B,KAAK,EAAE,CAAC,MAAM,CAAC;IACf,OAAO,EAAE,IAAI,IAAI,CAAC,0BAA0B,CAAC;IAC7C,SAAS,EAAE,mBAAmB;IAC9B,QAAQ,EAAE;QACR,OAAO,EAAE;YACP;gBACE,MAAM,EAAE,IAAI;gBACZ,WAAW,EAAE,IAAI;gBACjB,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,KAAK;gBACjB,YAAY,EAAE,KAAK;gBACnB,WAAW,EAAE,IAAI;aAClB;YACD;gBACE,MAAM,EAAE,KAAK;gBACb,WAAW,EAAE,CAAC;gBACd,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,IAAI;gBAChB,YAAY,EAAE,KAAK;gBACnB,WAAW,EAAE,IAAI;aAClB;YACD;gBACE,MAAM,EAAE,CAAC;gBACT,WAAW,EAAE,CAAC;gBACd,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,KAAK;gBACjB,YAAY,EAAE,KAAK;gBACnB,WAAW,EAAE,IAAI;aAClB;YACD;gBACE,MAAM,EAAE,GAAG;gBACX,WAAW,EAAE,CAAC;gBACd,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,KAAK;gBACjB,YAAY,EAAE,KAAK;gBACnB,WAAW,EAAE,IAAI;aAClB;SACF;KACF;IACD,SAAS,EAAE,IAAI,IAAI,CAAC,0BAA0B,CAAC;CAChD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/core-products",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"main": "lib/products-index.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./lib/products-index.js",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
},
|
|
32
32
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@unchainedshop/events": "^2.0.0
|
|
35
|
-
"@unchainedshop/file-upload": "^2.0.0
|
|
36
|
-
"@unchainedshop/utils": "^2.0.0
|
|
34
|
+
"@unchainedshop/events": "^2.0.0",
|
|
35
|
+
"@unchainedshop/file-upload": "^2.0.0",
|
|
36
|
+
"@unchainedshop/utils": "^2.0.0",
|
|
37
37
|
"locale": "^0.1.0",
|
|
38
38
|
"lru-cache": "^7.14.1",
|
|
39
39
|
"simpl-schema": "=3.2.0"
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/locale": "^0.1.1",
|
|
43
43
|
"@types/node": "^18.11.18",
|
|
44
|
-
"@unchainedshop/types": "^2.0.0
|
|
45
|
-
"jest": "^29.
|
|
46
|
-
"ts-jest": "^29.0.
|
|
44
|
+
"@unchainedshop/types": "^2.0.0",
|
|
45
|
+
"jest": "^29.4.1",
|
|
46
|
+
"ts-jest": "^29.0.5",
|
|
47
47
|
"typescript": "^4.9.4"
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { ProductPricingSheet } from "./ProductPricingSheet.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const TAX = { category: 'TAX', amount: 50, isNetPrice: false, isTaxable: false };
|
|
5
|
+
const TAX2 = { category: 'TAX', amount: 25, isNetPrice: false, isTaxable: false };
|
|
6
|
+
const DISCOUNT = { category: 'DISCOUNT', amount: 20, isNetPrice: false, isTaxable: false, discountId: 'for-all' };
|
|
7
|
+
const DISCOUNT2 = { category: 'DISCOUNT', amount: 20, isNetPrice: false, isTaxable: false, discountId: 'for-all' };
|
|
8
|
+
const DISCOUNT3 = { category: 'DISCOUNT', amount: 20, isNetPrice: false, isTaxable: false, discountId: 'special' };
|
|
9
|
+
const ITEM1 = { category: 'ITEM', amount: 200, isNetPrice: true, isTaxable: false };
|
|
10
|
+
const ITEM2 = { category: 'ITEM', amount: 200, isNetPrice: true, isTaxable: false };
|
|
11
|
+
const calculations = [TAX, TAX2, DISCOUNT, DISCOUNT2, DISCOUNT3, ITEM1, ITEM2];
|
|
12
|
+
|
|
13
|
+
describe('ProductPricingSheet', () => {
|
|
14
|
+
let pricingSheet
|
|
15
|
+
|
|
16
|
+
const pricingSheetParams = {
|
|
17
|
+
calculation: calculations,
|
|
18
|
+
currency: 'CHF',
|
|
19
|
+
quantity: 2,
|
|
20
|
+
};
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
pricingSheet = ProductPricingSheet(pricingSheetParams);
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('should return an object that implements the IProductPricingSheet interface', () => {
|
|
26
|
+
expect(pricingSheet).toBeDefined();
|
|
27
|
+
expect(pricingSheet.quantity).toEqual(2);
|
|
28
|
+
expect(pricingSheet.currency).toEqual('CHF');
|
|
29
|
+
expect(typeof pricingSheet.addItem).toBe('function');
|
|
30
|
+
expect(typeof pricingSheet.addDiscount).toBe('function');
|
|
31
|
+
expect(typeof pricingSheet.addTax).toBe('function');
|
|
32
|
+
expect(typeof pricingSheet.taxSum).toBe('function');
|
|
33
|
+
expect(typeof pricingSheet.itemSum).toBe('function');
|
|
34
|
+
expect(typeof pricingSheet.discountSum).toBe('function');
|
|
35
|
+
expect(typeof pricingSheet.unitPrice).toBe('function');
|
|
36
|
+
expect(typeof pricingSheet.discountPrices).toBe('function');
|
|
37
|
+
expect(typeof pricingSheet.getItemRows).toBe('function');
|
|
38
|
+
expect(typeof pricingSheet.getDiscountRows).toBe('function');
|
|
39
|
+
expect(typeof pricingSheet.getTaxRows).toBe('function');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('gross() should return the GROSS sum of all ProductPricingCalculation', () => {
|
|
43
|
+
expect(pricingSheet.gross()).toEqual(535)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('net() should return the NET sum of all ProductPricingCalculation (i.e before TAX)', () => {
|
|
47
|
+
expect(pricingSheet.net()).toEqual(460)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
describe('total()', () => {
|
|
51
|
+
it('should return sum of all ProductPricingCalculations ', () => {
|
|
52
|
+
expect(pricingSheet.total()).toEqual({"amount": 535, "currency": "CHF"})
|
|
53
|
+
expect(pricingSheet.total()).toEqual({ amount: pricingSheet.gross(), currency: "CHF"})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('should return sum of all ProductPricingCalculations ', () => {
|
|
57
|
+
expect(pricingSheet.total({useNetPrice: true})).toEqual({"amount": 460, "currency": "CHF"})
|
|
58
|
+
expect(pricingSheet.total({useNetPrice: true})).toEqual({ amount: pricingSheet.net(), currency: "CHF"})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('should return sum of all ProductPricingCalculations for the provided category ', () => {
|
|
62
|
+
expect(pricingSheet.total({category: 'ITEM'})).toEqual({"amount": 400, "currency": "CHF"})
|
|
63
|
+
expect(pricingSheet.total({category: 'DISCOUNT'})).toEqual({"amount": 60, "currency": "CHF"})
|
|
64
|
+
expect(pricingSheet.total({category: 'TAX'})).toEqual({"amount": 75, "currency": "CHF"})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe('isValid()', () => {
|
|
69
|
+
it('should return true if there is at least 1 registered ProductPricingCalculation ', () => {
|
|
70
|
+
expect(pricingSheet.isValid()).toEqual(true)
|
|
71
|
+
})
|
|
72
|
+
it('should return false if there is no registered ProductPricingCalculation ', () => {
|
|
73
|
+
const sheet = ProductPricingSheet({...pricingSheetParams, calculation: []});
|
|
74
|
+
expect(sheet.isValid()).toEqual(false)
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
describe('getItemRows', () => {
|
|
79
|
+
it('should return all the items registered on the ProductPricingSheet', () => {
|
|
80
|
+
expect(pricingSheet.getItemRows()).toEqual([ITEM1, ITEM2])
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
describe('getRawPricingSheet', () => {
|
|
85
|
+
it('should return all registered ProductPricingCalculation', () => {
|
|
86
|
+
|
|
87
|
+
expect(pricingSheet.getRawPricingSheet()).toEqual(calculations)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
describe('getTaxRows', () => {
|
|
93
|
+
it('should return all the TAX registered on the ProductPricingSheet', () => {
|
|
94
|
+
|
|
95
|
+
expect(pricingSheet.getTaxRows()).toEqual([TAX, TAX2])
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
describe('getDiscountRows', () => {
|
|
101
|
+
it('should return all the DISCOUNTS registered on the ProductPricingSheet', () => {
|
|
102
|
+
expect(pricingSheet.getDiscountRows('for-all')).toEqual([DISCOUNT, DISCOUNT2])
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
describe('taxSum', () => {
|
|
108
|
+
it('should return the sum of TAX calculation registered on the adapter', () => {
|
|
109
|
+
expect(pricingSheet.taxSum()).toEqual(75)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
describe('discountSum', () => {
|
|
115
|
+
it('should return the sum of DISCOUNT calculation registered on the adapter', () => {
|
|
116
|
+
expect(pricingSheet.discountSum()).toEqual(60)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
describe('itemSum', () => {
|
|
122
|
+
it('should return the sum of TAX calculation registered on the adapter', () => {
|
|
123
|
+
expect(pricingSheet.itemSum()).toEqual(400)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
describe('unitPrice', () => {
|
|
129
|
+
it('should return the GROSS sum for a product price useNetPrice:false', () => {
|
|
130
|
+
expect(pricingSheet.unitPrice({useNetPrice: false})).toEqual({"amount": 268, "category": "ITEM", "currency": "CHF", "isNetPrice": false, "isTaxable": true})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('should return the NET sum for a product price when useNetPrice:true', () => {
|
|
134
|
+
expect(pricingSheet.unitPrice({useNetPrice: true})).toEqual({"amount": 230, "category": "ITEM", "currency": "CHF", "isNetPrice": true, "isTaxable": true})
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
describe('discountPrices', () => {
|
|
139
|
+
it('should return the sum of all discounts registered on the price sheet based on discountId', () => {
|
|
140
|
+
expect(pricingSheet.discountPrices('for-all')).toEqual([{"amount": 40, "currency": "CHF", "discountId": "for-all"}])
|
|
141
|
+
expect(pricingSheet.discountPrices('special')).toEqual([{"amount": 20, "currency": "CHF", "discountId": "special"}])
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('should return empty array if discount with the provided discountId is not found', () => {
|
|
145
|
+
expect(pricingSheet.discountPrices('non-existing')).toEqual([])
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
describe('addItem', () => {
|
|
151
|
+
it('should add ProductPricingCalculation ITEM category successfully', () => {
|
|
152
|
+
expect(pricingSheet.getItemRows()).toEqual([ITEM1, ITEM2])
|
|
153
|
+
pricingSheet.addItem({amount: 300, isNetPrice: true, isTaxable: true})
|
|
154
|
+
expect(pricingSheet.getItemRows()).toEqual([ITEM1, ITEM2, {amount: 300, isNetPrice: true, isTaxable: true, category: 'ITEM', meta: undefined}])
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
describe('addDiscount', () => {
|
|
160
|
+
it('should add ProductPricingCalculation DISCOUNT category successfully', () => {
|
|
161
|
+
expect(pricingSheet.getDiscountRows('new')).toEqual([])
|
|
162
|
+
pricingSheet.addDiscount({amount: 300, isNetPrice: true, isTaxable: true, discountId: 'new'})
|
|
163
|
+
expect(pricingSheet.getDiscountRows('new')).toEqual([{amount: 300, isNetPrice: true, isTaxable: true, category: 'DISCOUNT', meta: undefined, discountId: 'new'}])
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
describe('addTax', () => {
|
|
169
|
+
it('should add ProductPricingCalculation TAX category successfully', () => {
|
|
170
|
+
expect(pricingSheet.getTaxRows()).toEqual([TAX, TAX2])
|
|
171
|
+
pricingSheet.addTax({amount: 50})
|
|
172
|
+
expect(pricingSheet.getTaxRows()).toEqual([TAX, TAX2, {amount: 50, isNetPrice: false, isTaxable: false, category: 'TAX'}])
|
|
173
|
+
})
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
File without changes
|
|
@@ -1,61 +1,66 @@
|
|
|
1
|
-
import {buildFindSelector} from "
|
|
1
|
+
import { buildFindSelector } from "./configureProductsModule";
|
|
2
|
+
|
|
2
3
|
describe('Product', () => {
|
|
3
4
|
describe("buildFindSelector", () => {
|
|
4
5
|
it('Return correct filter object object when no parameter is passed', async () => {
|
|
5
|
-
expect(buildFindSelector({})).toEqual({ status: { $eq: 'ACTIVE' } })
|
|
6
|
+
expect(buildFindSelector({}as any)).toEqual( { status: { '$eq': 'ACTIVE' } })
|
|
6
7
|
})
|
|
7
|
-
|
|
8
8
|
it('Return correct filter object object when passed includeDraft:true, productsIds, productSelector, queryString, slugs, tags ', async () => {
|
|
9
|
-
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2'], productSelector: {type: "SIMPLE_PRODUCT"}, queryString: "hello world", slugs: ['slug-1', 'slug-2'], tags: ['tag-1', 'tag-2'] })).toEqual( {
|
|
9
|
+
expect(buildFindSelector({ includeDrafts: true, productIds: ['product-1-id', 'product-id-2'], productSelector: {type: "SIMPLE_PRODUCT"}, queryString: "hello world", slugs: ['slug-1', 'slug-2'], tags: ['tag-1', 'tag-2'] } as any)).toEqual( {
|
|
10
10
|
type: 'SIMPLE_PRODUCT',
|
|
11
11
|
_id: { '$in': [ 'product-1-id', 'product-id-2' ] },
|
|
12
12
|
slugs: { '$in': [ 'slug-1', 'slug-2' ] },
|
|
13
13
|
tags: { '$all': [ 'tag-1', 'tag-2' ] },
|
|
14
14
|
'$text': { '$search': 'hello world' },
|
|
15
15
|
status: { '$in': [ 'ACTIVE', null ] }
|
|
16
|
-
}
|
|
17
|
-
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
});
|
|
18
19
|
|
|
19
20
|
it('Return correct filter object object when passed includeDraft:true, productsIds, productSelector, queryString, slugs ', async () => {
|
|
20
|
-
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2'], productSelector: {type: "SIMPLE_PRODUCT"}, queryString: "hello world", slugs: ['slug-1', 'slug-2']})).toEqual( {
|
|
21
|
+
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2'], productSelector: {type: "SIMPLE_PRODUCT"}, queryString: "hello world", slugs: ['slug-1', 'slug-2']}as any)).toEqual( {
|
|
21
22
|
type: 'SIMPLE_PRODUCT',
|
|
22
23
|
_id: { '$in': [ 'product-1-id', 'product-id-2' ] },
|
|
23
24
|
slugs: { '$in': [ 'slug-1', 'slug-2' ] },
|
|
24
25
|
'$text': { '$search': 'hello world' },
|
|
25
|
-
status: { '$in': [ 'ACTIVE', null ] }
|
|
26
|
+
status: { '$in': [ 'ACTIVE', null ] },
|
|
27
|
+
|
|
26
28
|
})
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
it('Return correct filter object object when passed includeDraft:true, productsIds, productSelector, queryString ', async () => {
|
|
30
|
-
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2'], productSelector: {type: "SIMPLE_PRODUCT"}, queryString: "hello world"})).toEqual( {
|
|
32
|
+
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2'], productSelector: {type: "SIMPLE_PRODUCT"}, queryString: "hello world"}as any)).toEqual( {
|
|
31
33
|
type: 'SIMPLE_PRODUCT',
|
|
32
34
|
_id: { '$in': [ 'product-1-id', 'product-id-2' ] },
|
|
33
35
|
'$text': { '$search': 'hello world' },
|
|
34
|
-
status: { '$in': [ 'ACTIVE', null ] }
|
|
36
|
+
status: { '$in': [ 'ACTIVE', null ] },
|
|
37
|
+
|
|
35
38
|
})
|
|
36
39
|
});
|
|
37
40
|
|
|
38
41
|
it('Return correct filter object object when passed includeDraft:true, productsIds, productSelector ', async () => {
|
|
39
|
-
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2'], productSelector: {type: "SIMPLE_PRODUCT"}})).toEqual( {
|
|
42
|
+
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2'], productSelector: {type: "SIMPLE_PRODUCT"}}as any)).toEqual( {
|
|
40
43
|
type: 'SIMPLE_PRODUCT',
|
|
41
44
|
_id: { '$in': [ 'product-1-id', 'product-id-2' ] },
|
|
42
|
-
status: { '$in': [ 'ACTIVE', null ] }
|
|
45
|
+
status: { '$in': [ 'ACTIVE', null ] },
|
|
46
|
+
|
|
43
47
|
})
|
|
44
48
|
});
|
|
45
49
|
|
|
46
50
|
it('Return correct filter object object when passed includeDraft:true, productsIds ', async () => {
|
|
47
|
-
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2']})).toEqual( {
|
|
51
|
+
expect(buildFindSelector({includeDrafts: true, productIds: ['product-1-id', 'product-id-2']}as any)).toEqual( {
|
|
48
52
|
_id: { '$in': [ 'product-1-id', 'product-id-2' ] },
|
|
49
|
-
status: { '$in': [ 'ACTIVE', null ] }
|
|
53
|
+
status: { '$in': [ 'ACTIVE', null ] },
|
|
54
|
+
|
|
50
55
|
})
|
|
51
56
|
});
|
|
52
57
|
|
|
53
58
|
it('Return filter tags if passed as a string ', async () => {
|
|
54
|
-
expect(buildFindSelector({tags: "string-tag"})).toEqual({ tags: 'string-tag', status: { '$eq': 'ACTIVE' } })
|
|
59
|
+
expect(buildFindSelector({tags: "string-tag"}as any)).toEqual({ tags: 'string-tag', status: { '$eq': 'ACTIVE' } })
|
|
55
60
|
});
|
|
56
61
|
|
|
57
62
|
it('includeDrafts true should add null to status filter array as null ', async () => {
|
|
58
|
-
expect(buildFindSelector({includeDrafts: true})).toEqual({status: { '$in': [ 'ACTIVE', null ] }} )
|
|
63
|
+
expect(buildFindSelector({includeDrafts: true}as any)).toEqual({status: { '$in': [ 'ACTIVE', null ] }} )
|
|
59
64
|
});
|
|
60
65
|
|
|
61
66
|
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { getDecimals, normalizeRate } from "../configureProductPrices.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
describe('Rate conversion', () => {
|
|
6
|
+
it('getDecimals', () => {
|
|
7
|
+
expect(getDecimals(18)).toBe(9);
|
|
8
|
+
expect(getDecimals(8)).toBe(8);
|
|
9
|
+
expect(getDecimals(1)).toBe(1);
|
|
10
|
+
expect(getDecimals(null)).toBe(2);
|
|
11
|
+
expect(getDecimals(undefined)).toBe(2);
|
|
12
|
+
expect(getDecimals(0)).toBe(0);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('normalizeRate converting between FIAT with 2 decimals', () => {
|
|
16
|
+
expect(normalizeRate({
|
|
17
|
+
isoCode: "USD",
|
|
18
|
+
decimals: 2
|
|
19
|
+
} as any, {
|
|
20
|
+
isoCode: "CHF",
|
|
21
|
+
decimals: 2
|
|
22
|
+
} as any, { quoteCurrency: "USD", rate: 0.9} as any)).toBe(1.1111111111111112);
|
|
23
|
+
|
|
24
|
+
expect(normalizeRate({
|
|
25
|
+
isoCode: "CHF", // in Rappen
|
|
26
|
+
decimals: 2
|
|
27
|
+
} as any, {
|
|
28
|
+
isoCode: "USD", // in Pennies
|
|
29
|
+
decimals: 2
|
|
30
|
+
} as any, { quoteCurrency: "USD", rate: 0.9} as any)).toBe(0.9);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('normalizeRate converting between FIAT with 0 and 2 decimals', () => {
|
|
34
|
+
expect(normalizeRate({
|
|
35
|
+
isoCode: "CLP", // in Pesos
|
|
36
|
+
decimals: 0
|
|
37
|
+
} as any, {
|
|
38
|
+
isoCode: "CHF", // in Rappen
|
|
39
|
+
decimals: 2
|
|
40
|
+
} as any, { baseCurrency: "CLP", quoteCurrency: "CHF", rate: 0.0010451376} as any)).toBe(0.10451376);
|
|
41
|
+
|
|
42
|
+
expect(normalizeRate({
|
|
43
|
+
isoCode: "CLP", // in Pesos
|
|
44
|
+
decimals: 0
|
|
45
|
+
} as any, {
|
|
46
|
+
isoCode: "CHF", // in Rappen
|
|
47
|
+
decimals: 2
|
|
48
|
+
} as any, {
|
|
49
|
+
baseCurrency: "CHF", quoteCurrency: "CLP", rate: 956.75994,
|
|
50
|
+
expiresAt: undefined,
|
|
51
|
+
timestamp: undefined
|
|
52
|
+
})).toBe(0.10451942626276765);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('normalizeRate converting FIAT to/from Crypto with Crypto->Fiat Pair', () => {
|
|
56
|
+
expect(normalizeRate({
|
|
57
|
+
isoCode: "USD", // in Pennies
|
|
58
|
+
decimals: 2
|
|
59
|
+
} as any, {
|
|
60
|
+
isoCode: "BTC", // In Satoshis
|
|
61
|
+
decimals: 9
|
|
62
|
+
} as any, { baseCurrency: "BTC", quoteCurrency: "USD", rate: 19284.61} as any)).toBe(518.5482102049251);
|
|
63
|
+
|
|
64
|
+
expect(normalizeRate({
|
|
65
|
+
isoCode: "ETH", // in GWEI
|
|
66
|
+
decimals: 18
|
|
67
|
+
} as any, {
|
|
68
|
+
isoCode: "CHF", // in Rappen
|
|
69
|
+
decimals: 2
|
|
70
|
+
} as any, { baseCurrency: "ETH", quoteCurrency: "CHF", rate: 1311.63} as any)).toBe(0.000131163);
|
|
71
|
+
|
|
72
|
+
// 1 ETH = 0.000131163
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('normalizeRate converting FIAT to/from Crypto with Fiat->Crypto Pair', () => {
|
|
76
|
+
expect(normalizeRate({
|
|
77
|
+
isoCode: "USD", // in Pennies
|
|
78
|
+
decimals: 2
|
|
79
|
+
} as any, {
|
|
80
|
+
isoCode: "BTC", // in Satoshis
|
|
81
|
+
decimals: 8
|
|
82
|
+
} as any, { baseCurrency: "USD", quoteCurrency: "BTC", rate: 0.000052} as any)).toBe(52);
|
|
83
|
+
|
|
84
|
+
// 1 USD = 100 Pennies
|
|
85
|
+
// 100 Pennies = 5200 Satoshis
|
|
86
|
+
|
|
87
|
+
expect(normalizeRate({
|
|
88
|
+
isoCode: "ETH", // in GWEI
|
|
89
|
+
decimals: 18
|
|
90
|
+
} as any, {
|
|
91
|
+
isoCode: "CLP", // in Pesos
|
|
92
|
+
decimals: 0
|
|
93
|
+
} as any, { baseCurrency: "CLP", quoteCurrency: "ETH", rate: 0.000000794} as any)).toBe(0.0012594458438287153);
|
|
94
|
+
|
|
95
|
+
// 1 ETH = 1,000,000,000 GWEI (10^9)
|
|
96
|
+
// 1,000,000,000 GWEI = 1’259’445 CLP
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { getPriceLevels } from "./getPriceLevels.js";
|
|
2
|
+
import product from '../../mock/product.js'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
describe('Price level', () => {
|
|
6
|
+
it('Should return empty array when country code is not specified', () => {
|
|
7
|
+
expect(getPriceLevels({ product, currencyCode: 'CHF' } as any)).toHaveLength(0);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('Should return empty array when country code is not specified', () => {
|
|
11
|
+
expect(getPriceLevels({ product, countryCode: 'ET' } as any)).toHaveLength(1);
|
|
12
|
+
expect(getPriceLevels({ product, countryCode: 'ET' } as any)).toEqual([
|
|
13
|
+
{
|
|
14
|
+
amount: 20000,
|
|
15
|
+
maxQuantity: 2,
|
|
16
|
+
isTaxable: true,
|
|
17
|
+
isNetPrice: true,
|
|
18
|
+
currencyCode: 'ETB',
|
|
19
|
+
countryCode: 'ET',
|
|
20
|
+
},
|
|
21
|
+
]);
|
|
22
|
+
expect(getPriceLevels({ product, countryCode: 'CH' } as any)).toHaveLength(3);
|
|
23
|
+
expect(getPriceLevels({ product, countryCode: 'CH' } as any)).toEqual([
|
|
24
|
+
{
|
|
25
|
+
amount: 1000,
|
|
26
|
+
maxQuantity: null,
|
|
27
|
+
isTaxable: false,
|
|
28
|
+
isNetPrice: false,
|
|
29
|
+
currencyCode: 'CHF',
|
|
30
|
+
countryCode: 'CH',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
amount: 1,
|
|
34
|
+
maxQuantity: 1,
|
|
35
|
+
isTaxable: false,
|
|
36
|
+
isNetPrice: false,
|
|
37
|
+
currencyCode: 'ETH',
|
|
38
|
+
countryCode: 'CH',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
amount: 750,
|
|
42
|
+
maxQuantity: 2,
|
|
43
|
+
isTaxable: false,
|
|
44
|
+
isNetPrice: false,
|
|
45
|
+
currencyCode: 'CHF',
|
|
46
|
+
countryCode: 'CH',
|
|
47
|
+
},
|
|
48
|
+
]);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('Should return all prices for a given country sorted by max quantity ASC', () => {
|
|
52
|
+
expect(getPriceLevels({ product, countryCode: 'CH' } as any)).toEqual([
|
|
53
|
+
{
|
|
54
|
+
amount: 1000,
|
|
55
|
+
maxQuantity: null,
|
|
56
|
+
isTaxable: false,
|
|
57
|
+
isNetPrice: false,
|
|
58
|
+
currencyCode: 'CHF',
|
|
59
|
+
countryCode: 'CH',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
amount: 1,
|
|
63
|
+
maxQuantity: 1,
|
|
64
|
+
isTaxable: false,
|
|
65
|
+
isNetPrice: false,
|
|
66
|
+
currencyCode: 'ETH',
|
|
67
|
+
countryCode: 'CH',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
amount: 750,
|
|
71
|
+
maxQuantity: 2,
|
|
72
|
+
isTaxable: false,
|
|
73
|
+
isNetPrice: false,
|
|
74
|
+
currencyCode: 'CHF',
|
|
75
|
+
countryCode: 'CH',
|
|
76
|
+
},
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('Should return all prices currencyCode', () => {
|
|
81
|
+
expect(getPriceLevels({ product, countryCode: 'CH', currencyCode: 'CHF' } as any)).toHaveLength(2);
|
|
82
|
+
expect(getPriceLevels({ product, countryCode: 'CH', currencyCode: 'ETH' } as any)).toHaveLength(1);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { getPriceRange } from './getPriceRange.js';
|
|
2
|
+
import product from '../../mock/product.js'
|
|
3
|
+
import { getPriceLevels } from './getPriceLevels.js';
|
|
4
|
+
|
|
5
|
+
describe('Price Range', () => {
|
|
6
|
+
it('Should return the minimum and maximum price of a product when there are multiple prices', () => {
|
|
7
|
+
expect(
|
|
8
|
+
getPriceRange({
|
|
9
|
+
productId: product._id,
|
|
10
|
+
prices: getPriceLevels({ product, countryCode: 'CH', currencyCode: 'CHF' } as any),
|
|
11
|
+
}),
|
|
12
|
+
).toEqual({
|
|
13
|
+
minPrice: {
|
|
14
|
+
_id: '3e94daeb7a9600e9bb07b50c92c21ac9002da34a2d8fe799a6ce885404b545b9',
|
|
15
|
+
isTaxable: false,
|
|
16
|
+
isNetPrice: false,
|
|
17
|
+
amount: 750,
|
|
18
|
+
currencyCode: 'CHF',
|
|
19
|
+
},
|
|
20
|
+
maxPrice: {
|
|
21
|
+
_id: 'b6a9702eb217f07ad5fa8c3a378e072d49b667813db0e127fab7cf5e2c4b2639',
|
|
22
|
+
isTaxable: false,
|
|
23
|
+
isNetPrice: false,
|
|
24
|
+
amount: 1000,
|
|
25
|
+
currencyCode: 'CHF',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('Should still return and object with min and max price field when no price list is provided', () => {
|
|
31
|
+
expect(
|
|
32
|
+
getPriceRange({
|
|
33
|
+
productId: product._id,
|
|
34
|
+
prices: getPriceLevels({ product, countryCode: 'DE', currencyCode: 'EUR' } as any),
|
|
35
|
+
}),
|
|
36
|
+
).toEqual({
|
|
37
|
+
minPrice: {
|
|
38
|
+
_id: '00f750fe893f9f5e04c31a6a6f1a60f5d941182e388b7908a02e5bc855d16797',
|
|
39
|
+
isTaxable: false,
|
|
40
|
+
isNetPrice: false,
|
|
41
|
+
amount: NaN,
|
|
42
|
+
currencyCode: undefined,
|
|
43
|
+
},
|
|
44
|
+
maxPrice: {
|
|
45
|
+
_id: '00f750fe893f9f5e04c31a6a6f1a60f5d941182e388b7908a02e5bc855d16797',
|
|
46
|
+
isTaxable: false,
|
|
47
|
+
isNetPrice: false,
|
|
48
|
+
amount: NaN,
|
|
49
|
+
currencyCode: undefined,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
});
|
package/tsconfig.json
CHANGED
|
@@ -1,29 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../shared/base.tsconfig.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
|
-
"
|
|
4
|
-
"allowSyntheticDefaultImports": true,
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"experimentalDecorators": true,
|
|
8
|
-
"forceConsistentCasingInFileNames": true,
|
|
9
|
-
"lib": [
|
|
10
|
-
"esnext"
|
|
11
|
-
],
|
|
12
|
-
"module": "Node16",
|
|
13
|
-
"moduleResolution": "Node16",
|
|
14
|
-
"noImplicitReturns": true,
|
|
15
|
-
"noUnusedLocals": false,
|
|
4
|
+
"rootDir": "src",
|
|
16
5
|
"outDir": "lib",
|
|
17
|
-
"preserveWatchOutput": true,
|
|
18
|
-
"skipLibCheck": true,
|
|
19
|
-
"sourceMap": true,
|
|
20
|
-
"target": "ES2022",
|
|
21
|
-
"types": [
|
|
22
|
-
"node",
|
|
23
|
-
"jest"
|
|
24
|
-
]
|
|
25
6
|
},
|
|
7
|
+
"exclude": ["**/*.test.ts", "**/*.test.js", "tests"],
|
|
26
8
|
"include": [
|
|
27
|
-
"src"
|
|
9
|
+
"./src"
|
|
28
10
|
]
|
|
29
11
|
}
|
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
import { getDecimals, normalizeRate } from '../lib/module/configureProductPrices.js';
|
|
2
|
-
import { getPriceLevels } from '../lib/module/utils/getPriceLevels.js';
|
|
3
|
-
import { getPriceRange } from '../lib/module/utils/getPriceRange.js';
|
|
4
|
-
import product from './mock/product'
|
|
5
|
-
|
|
6
|
-
describe('Rate conversion', () => {
|
|
7
|
-
test('getDecimals', () => {
|
|
8
|
-
expect(getDecimals(18)).toBe(9);
|
|
9
|
-
expect(getDecimals(8)).toBe(8);
|
|
10
|
-
expect(getDecimals(1)).toBe(1);
|
|
11
|
-
expect(getDecimals(null)).toBe(2);
|
|
12
|
-
expect(getDecimals(undefined)).toBe(2);
|
|
13
|
-
expect(getDecimals(0)).toBe(0);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('normalizeRate converting between FIAT with 2 decimals', () => {
|
|
17
|
-
expect(normalizeRate({
|
|
18
|
-
isoCode: "USD",
|
|
19
|
-
decimals: 2
|
|
20
|
-
}, {
|
|
21
|
-
isoCode: "CHF",
|
|
22
|
-
decimals: 2
|
|
23
|
-
}, { quoteCurrency: "USD", rate: 0.9})).toBe(1.1111111111111112);
|
|
24
|
-
|
|
25
|
-
expect(normalizeRate({
|
|
26
|
-
isoCode: "CHF", // in Rappen
|
|
27
|
-
decimals: 2
|
|
28
|
-
}, {
|
|
29
|
-
isoCode: "USD", // in Pennies
|
|
30
|
-
decimals: 2
|
|
31
|
-
}, { quoteCurrency: "USD", rate: 0.9})).toBe(0.9);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('normalizeRate converting between FIAT with 0 and 2 decimals', () => {
|
|
35
|
-
expect(normalizeRate({
|
|
36
|
-
isoCode: "CLP", // in Pesos
|
|
37
|
-
decimals: 0
|
|
38
|
-
}, {
|
|
39
|
-
isoCode: "CHF", // in Rappen
|
|
40
|
-
decimals: 2
|
|
41
|
-
}, { baseCurrency: "CLP", quoteCurrency: "CHF", rate: 0.0010451376})).toBe(0.10451376);
|
|
42
|
-
|
|
43
|
-
expect(normalizeRate({
|
|
44
|
-
isoCode: "CLP", // in Pesos
|
|
45
|
-
decimals: 0
|
|
46
|
-
}, {
|
|
47
|
-
isoCode: "CHF", // in Rappen
|
|
48
|
-
decimals: 2
|
|
49
|
-
}, { baseCurrency: "CHF", quoteCurrency: "CLP", rate: 956.75994})).toBe(0.10451942626276765);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('normalizeRate converting FIAT to/from Crypto with Crypto->Fiat Pair', () => {
|
|
53
|
-
expect(normalizeRate({
|
|
54
|
-
isoCode: "USD", // in Pennies
|
|
55
|
-
decimals: 2
|
|
56
|
-
}, {
|
|
57
|
-
isoCode: "BTC", // In Satoshis
|
|
58
|
-
decimals: 9
|
|
59
|
-
}, { baseCurrency: "BTC", quoteCurrency: "USD", rate: 19284.61})).toBe(518.5482102049251);
|
|
60
|
-
|
|
61
|
-
expect(normalizeRate({
|
|
62
|
-
isoCode: "ETH", // in GWEI
|
|
63
|
-
decimals: 18
|
|
64
|
-
}, {
|
|
65
|
-
isoCode: "CHF", // in Rappen
|
|
66
|
-
decimals: 2
|
|
67
|
-
}, { baseCurrency: "ETH", quoteCurrency: "CHF", rate: 1311.63})).toBe(0.000131163);
|
|
68
|
-
|
|
69
|
-
// 1 ETH = 0.000131163
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test('normalizeRate converting FIAT to/from Crypto with Fiat->Crypto Pair', () => {
|
|
73
|
-
expect(normalizeRate({
|
|
74
|
-
isoCode: "USD", // in Pennies
|
|
75
|
-
decimals: 2
|
|
76
|
-
}, {
|
|
77
|
-
isoCode: "BTC", // in Satoshis
|
|
78
|
-
decimals: 8
|
|
79
|
-
}, { baseCurrency: "USD", quoteCurrency: "BTC", rate: 0.000052})).toBe(52);
|
|
80
|
-
|
|
81
|
-
// 1 USD = 100 Pennies
|
|
82
|
-
// 100 Pennies = 5200 Satoshis
|
|
83
|
-
|
|
84
|
-
expect(normalizeRate({
|
|
85
|
-
isoCode: "ETH", // in GWEI
|
|
86
|
-
decimals: 18
|
|
87
|
-
}, {
|
|
88
|
-
isoCode: "CLP", // in Pesos
|
|
89
|
-
decimals: 0
|
|
90
|
-
}, { baseCurrency: "CLP", quoteCurrency: "ETH", rate: 0.000000794})).toBe(0.0012594458438287153);
|
|
91
|
-
|
|
92
|
-
// 1 ETH = 1,000,000,000 GWEI (10^9)
|
|
93
|
-
// 1,000,000,000 GWEI = 1’259’445 CLP
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
describe('Price level', () => {
|
|
98
|
-
it('Should return empty array when country code is not specified', () => {
|
|
99
|
-
expect(getPriceLevels({product, currencyCode: "CHF"})).toHaveLength(0)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('Should return empty array when country code is not specified', () => {
|
|
103
|
-
expect(getPriceLevels({product, countryCode: "ET"})).toHaveLength(1)
|
|
104
|
-
expect(getPriceLevels({product, countryCode: "ET"})).toEqual([
|
|
105
|
-
{
|
|
106
|
-
amount: 20000,
|
|
107
|
-
maxQuantity: 2,
|
|
108
|
-
isTaxable: true,
|
|
109
|
-
isNetPrice: true,
|
|
110
|
-
currencyCode: 'ETB',
|
|
111
|
-
countryCode: 'ET'
|
|
112
|
-
}
|
|
113
|
-
])
|
|
114
|
-
expect(getPriceLevels({product, countryCode: "CH"})).toHaveLength(3)
|
|
115
|
-
expect(getPriceLevels({product, countryCode: "CH"})).toEqual([
|
|
116
|
-
{
|
|
117
|
-
amount: 1000,
|
|
118
|
-
maxQuantity: null,
|
|
119
|
-
isTaxable: false,
|
|
120
|
-
isNetPrice: false,
|
|
121
|
-
currencyCode: 'CHF',
|
|
122
|
-
countryCode: 'CH'
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
amount: 1,
|
|
126
|
-
maxQuantity: 1,
|
|
127
|
-
isTaxable: false,
|
|
128
|
-
isNetPrice: false,
|
|
129
|
-
currencyCode: 'ETH',
|
|
130
|
-
countryCode: 'CH'
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
amount: 750,
|
|
134
|
-
maxQuantity: 2,
|
|
135
|
-
isTaxable: false,
|
|
136
|
-
isNetPrice: false,
|
|
137
|
-
currencyCode: 'CHF',
|
|
138
|
-
countryCode: 'CH'
|
|
139
|
-
}
|
|
140
|
-
])
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
it('Should return all prices for a given country sorted by max quantity ASC', () => {
|
|
145
|
-
expect(getPriceLevels({product, countryCode: "CH"})).toEqual([
|
|
146
|
-
{
|
|
147
|
-
amount: 1000,
|
|
148
|
-
maxQuantity: null,
|
|
149
|
-
isTaxable: false,
|
|
150
|
-
isNetPrice: false,
|
|
151
|
-
currencyCode: 'CHF',
|
|
152
|
-
countryCode: 'CH'
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
amount: 1,
|
|
156
|
-
maxQuantity: 1,
|
|
157
|
-
isTaxable: false,
|
|
158
|
-
isNetPrice: false,
|
|
159
|
-
currencyCode: 'ETH',
|
|
160
|
-
countryCode: 'CH'
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
amount: 750,
|
|
164
|
-
maxQuantity: 2,
|
|
165
|
-
isTaxable: false,
|
|
166
|
-
isNetPrice: false,
|
|
167
|
-
currencyCode: 'CHF',
|
|
168
|
-
countryCode: 'CH'
|
|
169
|
-
}
|
|
170
|
-
])
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
it('Should return all prices currencyCode', () => {
|
|
174
|
-
expect(getPriceLevels({product, countryCode: "CH", currencyCode: "CHF"})).toHaveLength(2)
|
|
175
|
-
expect(getPriceLevels({product, countryCode: "CH", currencyCode: "ETH"})).toHaveLength(1)
|
|
176
|
-
|
|
177
|
-
})
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
describe('Price Range', () => {
|
|
183
|
-
it('Should return the minimum and maximum price of a product when there are multiple prices', () => {
|
|
184
|
-
expect(getPriceRange({productId: product._id, prices: getPriceLevels({product, countryCode: "CH", currencyCode: "CHF"}) })).toEqual({
|
|
185
|
-
minPrice: {
|
|
186
|
-
_id: '3e94daeb7a9600e9bb07b50c92c21ac9002da34a2d8fe799a6ce885404b545b9',
|
|
187
|
-
isTaxable: false,
|
|
188
|
-
isNetPrice: false,
|
|
189
|
-
amount: 750,
|
|
190
|
-
currencyCode: 'CHF'
|
|
191
|
-
},
|
|
192
|
-
maxPrice: {
|
|
193
|
-
_id: 'b6a9702eb217f07ad5fa8c3a378e072d49b667813db0e127fab7cf5e2c4b2639',
|
|
194
|
-
isTaxable: false,
|
|
195
|
-
isNetPrice: false,
|
|
196
|
-
amount: 1000,
|
|
197
|
-
currencyCode: 'CHF'
|
|
198
|
-
}
|
|
199
|
-
})
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
it('Should return the same price as minimum and maximum when only one price exist for a given currency', () => {
|
|
203
|
-
expect(getPriceRange({productId: product._id, prices: getPriceLevels({product, countryCode: "ET", currencyCode: "ETB"}) })).toEqual({
|
|
204
|
-
minPrice: {
|
|
205
|
-
_id: '1740965265959af6ecda7cc3e06454069d6ed4e21ae052791ab172a342c82fa0',
|
|
206
|
-
isTaxable: true,
|
|
207
|
-
isNetPrice: true,
|
|
208
|
-
amount: 20000,
|
|
209
|
-
currencyCode: 'ETB'
|
|
210
|
-
},
|
|
211
|
-
maxPrice: {
|
|
212
|
-
_id: '1740965265959af6ecda7cc3e06454069d6ed4e21ae052791ab172a342c82fa0',
|
|
213
|
-
isTaxable: true,
|
|
214
|
-
isNetPrice: true,
|
|
215
|
-
amount: 20000,
|
|
216
|
-
currencyCode: 'ETB'
|
|
217
|
-
}
|
|
218
|
-
})
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
it('Should still return and object with min and max price field when no price list is provided', () => {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
expect(getPriceRange({productId: product._id, prices: getPriceLevels({product, countryCode: "DE", currencyCode: "EUR"}) })).toEqual({
|
|
225
|
-
minPrice: {
|
|
226
|
-
_id: '00f750fe893f9f5e04c31a6a6f1a60f5d941182e388b7908a02e5bc855d16797',
|
|
227
|
-
isTaxable: false,
|
|
228
|
-
isNetPrice: false,
|
|
229
|
-
amount: NaN,
|
|
230
|
-
currencyCode: undefined
|
|
231
|
-
},
|
|
232
|
-
maxPrice: {
|
|
233
|
-
_id: '00f750fe893f9f5e04c31a6a6f1a60f5d941182e388b7908a02e5bc855d16797',
|
|
234
|
-
isTaxable: false,
|
|
235
|
-
isNetPrice: false,
|
|
236
|
-
amount: NaN,
|
|
237
|
-
currencyCode: undefined
|
|
238
|
-
}
|
|
239
|
-
})
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
it('Should return empty array when country code is not specified', () => {
|
|
243
|
-
expect(getPriceLevels({product, countryCode: "ET"})).toHaveLength(1)
|
|
244
|
-
expect(getPriceLevels({product, countryCode: "ET"})).toEqual([
|
|
245
|
-
{
|
|
246
|
-
amount: 20000,
|
|
247
|
-
maxQuantity: 2,
|
|
248
|
-
isTaxable: true,
|
|
249
|
-
isNetPrice: true,
|
|
250
|
-
currencyCode: 'ETB',
|
|
251
|
-
countryCode: 'ET'
|
|
252
|
-
}
|
|
253
|
-
])
|
|
254
|
-
expect(getPriceLevels({product, countryCode: "CH"})).toHaveLength(3)
|
|
255
|
-
expect(getPriceLevels({product, countryCode: "CH"})).toEqual([
|
|
256
|
-
{
|
|
257
|
-
amount: 1000,
|
|
258
|
-
maxQuantity: null,
|
|
259
|
-
isTaxable: false,
|
|
260
|
-
isNetPrice: false,
|
|
261
|
-
currencyCode: 'CHF',
|
|
262
|
-
countryCode: 'CH'
|
|
263
|
-
},
|
|
264
|
-
{
|
|
265
|
-
amount: 1,
|
|
266
|
-
maxQuantity: 1,
|
|
267
|
-
isTaxable: false,
|
|
268
|
-
isNetPrice: false,
|
|
269
|
-
currencyCode: 'ETH',
|
|
270
|
-
countryCode: 'CH'
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
amount: 750,
|
|
274
|
-
maxQuantity: 2,
|
|
275
|
-
isTaxable: false,
|
|
276
|
-
isNetPrice: false,
|
|
277
|
-
currencyCode: 'CHF',
|
|
278
|
-
countryCode: 'CH'
|
|
279
|
-
}
|
|
280
|
-
])
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
it('Should return all prices for a given country sorted by max quantity ASC', () => {
|
|
285
|
-
expect(getPriceLevels({product, countryCode: "CH"})).toEqual([
|
|
286
|
-
{
|
|
287
|
-
amount: 1000,
|
|
288
|
-
maxQuantity: null,
|
|
289
|
-
isTaxable: false,
|
|
290
|
-
isNetPrice: false,
|
|
291
|
-
currencyCode: 'CHF',
|
|
292
|
-
countryCode: 'CH'
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
amount: 1,
|
|
296
|
-
maxQuantity: 1,
|
|
297
|
-
isTaxable: false,
|
|
298
|
-
isNetPrice: false,
|
|
299
|
-
currencyCode: 'ETH',
|
|
300
|
-
countryCode: 'CH'
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
amount: 750,
|
|
304
|
-
maxQuantity: 2,
|
|
305
|
-
isTaxable: false,
|
|
306
|
-
isNetPrice: false,
|
|
307
|
-
currencyCode: 'CHF',
|
|
308
|
-
countryCode: 'CH'
|
|
309
|
-
}
|
|
310
|
-
])
|
|
311
|
-
})
|
|
312
|
-
|
|
313
|
-
it('Should return all prices currencyCode', () => {
|
|
314
|
-
expect(getPriceLevels({product, countryCode: "CH", currencyCode: "CHF"})).toHaveLength(2)
|
|
315
|
-
expect(getPriceLevels({product, countryCode: "CH", currencyCode: "ETH"})).toHaveLength(1)
|
|
316
|
-
|
|
317
|
-
})
|
|
318
|
-
})
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import {buildFindSelector} from "../lib/module/configureProductReviewsModule"
|
|
2
|
-
describe('Product Review', () => {
|
|
3
|
-
describe("buildFindSelector", () => {
|
|
4
|
-
it('Return correct filter object object when no parameter is passed', async () => {
|
|
5
|
-
expect(buildFindSelector({})).toEqual({deleted: null})
|
|
6
|
-
})
|
|
7
|
-
|
|
8
|
-
it('Return correct filter object object when passed authorId, productId, queryString & updated', async () => {
|
|
9
|
-
expect(buildFindSelector({authorId: "admin-id", productId: "product-id", queryString: "hello world", updated: {start: new Date("2022-12-04T14:54:51.184Z"), end: new Date("2022-12-04T14:54:51.184Z")}})).toEqual( {
|
|
10
|
-
productId: 'product-id',
|
|
11
|
-
authorId: 'admin-id',
|
|
12
|
-
deleted: null,
|
|
13
|
-
'$text': { '$search': 'hello world' },
|
|
14
|
-
|
|
15
|
-
updated: {
|
|
16
|
-
'$gte': new Date("2022-12-04T14:54:51.184Z"),
|
|
17
|
-
'$lte': new Date("2022-12-04T14:54:51.184Z")
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('Return correct filter object object when passed authorId, productId & queryString ', async () => {
|
|
23
|
-
expect(buildFindSelector({authorId: "admin-id", productId: "product-id", queryString: "hello world",})).toEqual( {
|
|
24
|
-
productId: 'product-id',
|
|
25
|
-
authorId: 'admin-id',
|
|
26
|
-
deleted: null,
|
|
27
|
-
'$text': { '$search': 'hello world' },
|
|
28
|
-
})
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('Return correct filter object object when passed authorId & productId ', async () => {
|
|
32
|
-
expect(buildFindSelector({authorId: "admin-id", productId: "product-id"})).toEqual( {
|
|
33
|
-
productId: 'product-id',
|
|
34
|
-
authorId: 'admin-id',
|
|
35
|
-
deleted: null,
|
|
36
|
-
})
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('Return correct filter object object when passed authorId ', async () => {
|
|
40
|
-
expect(buildFindSelector({authorId: "admin-id"})).toEqual( {
|
|
41
|
-
authorId: 'admin-id',
|
|
42
|
-
deleted: null,
|
|
43
|
-
})
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('Set created date filter to unix start time if created.start is not provided ', async () => {
|
|
47
|
-
expect(buildFindSelector({created: { end: new Date("2022-12-04T14:54:51.184Z")}})).toEqual({
|
|
48
|
-
deleted: null,
|
|
49
|
-
created: {
|
|
50
|
-
'$gte': new Date(0),
|
|
51
|
-
'$lte': new Date("2022-12-04T14:54:51.184Z")
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('Set updated date filter to unix start time if updated.start is not provided ', async () => {
|
|
57
|
-
expect(buildFindSelector({updated: { end: new Date("2022-12-04T14:54:51.184Z")}})).toEqual({
|
|
58
|
-
deleted: null,
|
|
59
|
-
updated: {
|
|
60
|
-
'$gte': new Date(0),
|
|
61
|
-
'$lte': new Date("2022-12-04T14:54:51.184Z")
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('Should filter created date greater that provided when created.end is not provided', async () => {
|
|
67
|
-
expect(buildFindSelector({created: { start: new Date("2022-12-04T14:54:51.184Z")}})).toEqual({ deleted: null, created: { '$gte': new Date("2022-12-04T14:54:51.184Z") } })
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('Should filter updated date greater that provided when updated.end is not provided', async () => {
|
|
71
|
-
expect(buildFindSelector({updated: { start: new Date("2022-12-04T14:54:51.184Z")}})).toEqual({ deleted: null, updated: { '$gte': new Date("2022-12-04T14:54:51.184Z") } })
|
|
72
|
-
});
|
|
73
|
-
})
|
|
74
|
-
});
|