@reactionary/examples-node 0.1.13 → 0.2.2
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/package.json +5 -5
- package/src/basic/basic-node-setup.spec.ts +6 -2
- package/src/capabilities/cart.spec.ts +109 -65
- package/src/capabilities/category.spec.ts +80 -45
- package/src/capabilities/checkout.spec.ts +237 -168
- package/src/capabilities/identity.spec.ts +36 -10
- package/src/capabilities/inventory.spec.ts +20 -20
- package/src/capabilities/price.spec.ts +45 -35
- package/src/capabilities/product-search.spec.ts +82 -29
- package/src/capabilities/product.spec.ts +90 -76
- package/src/capabilities/profile.spec.ts +307 -16
- package/src/capabilities/store.spec.ts +6 -2
- package/src/utils.ts +40 -25
|
@@ -1,41 +1,51 @@
|
|
|
1
1
|
import 'dotenv/config';
|
|
2
|
-
import { describe, expect, it, beforeEach } from 'vitest';
|
|
2
|
+
import { describe, expect, it, beforeEach, assert } from 'vitest';
|
|
3
3
|
import { createClient, PrimaryProvider } from '../utils.js';
|
|
4
4
|
|
|
5
5
|
const testData = {
|
|
6
|
-
skuWithoutTiers: '4049699458101'
|
|
7
|
-
}
|
|
8
|
-
|
|
6
|
+
skuWithoutTiers: '4049699458101',
|
|
7
|
+
};
|
|
9
8
|
|
|
10
9
|
// FIXME: Currently broken in terms of actually looking up anything...
|
|
11
|
-
describe.each([PrimaryProvider.COMMERCETOOLS])(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
10
|
+
describe.each([PrimaryProvider.COMMERCETOOLS])(
|
|
11
|
+
'Price Capability - %s',
|
|
12
|
+
(provider) => {
|
|
13
|
+
let client: ReturnType<typeof createClient>;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
client = createClient(provider);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should be able to get an offer price for a sku', async () => {
|
|
20
|
+
const result = await client.price.getCustomerPrice({
|
|
21
|
+
variant: { sku: testData.skuWithoutTiers },
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (!result.success) {
|
|
25
|
+
assert.fail();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
expect(result.value.identifier.variant.sku).toBe(
|
|
29
|
+
testData.skuWithoutTiers
|
|
30
|
+
);
|
|
31
|
+
expect(result.value.unitPrice.value).toBe(155.1);
|
|
32
|
+
expect(result.value.unitPrice.currency).toBe('USD');
|
|
33
|
+
expect(result.value.tieredPrices.length).toBe(0);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should be able to get a list price for a sku', async () => {
|
|
37
|
+
const result = await client.price.getListPrice({
|
|
38
|
+
variant: { sku: testData.skuWithoutTiers },
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (!result.success) {
|
|
42
|
+
assert.fail();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
expect(result.value.identifier.variant.sku).toBe(testData.skuWithoutTiers);
|
|
46
|
+
expect(result.value.unitPrice.value).toBeGreaterThan(200);
|
|
47
|
+
expect(result.value.unitPrice.currency).toBe('USD');
|
|
48
|
+
expect(result.value.tieredPrices.length).toBe(0);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import 'dotenv/config';
|
|
2
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { assert, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
import { createClient, PrimaryProvider } from '../utils.js';
|
|
4
4
|
import type { ProductSearchQueryCreateNavigationFilter } from '@reactionary/core';
|
|
5
5
|
|
|
@@ -29,7 +29,11 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
29
29
|
},
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
if (!result.success) {
|
|
33
|
+
assert.fail(JSON.stringify(result.error));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
expect(result.value.items.length).toBeGreaterThan(0);
|
|
33
37
|
});
|
|
34
38
|
|
|
35
39
|
it('should be able to get a result by term, paged', async () => {
|
|
@@ -45,8 +49,12 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
45
49
|
},
|
|
46
50
|
});
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
if (!result.success) {
|
|
53
|
+
assert.fail();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
expect(result.value.items.length).toBeGreaterThan(0);
|
|
57
|
+
expect(result.value.totalPages).toBeGreaterThan(1);
|
|
50
58
|
|
|
51
59
|
const result2 = await client.productSearch.queryByTerm({
|
|
52
60
|
search: {
|
|
@@ -60,10 +68,14 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
60
68
|
},
|
|
61
69
|
});
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
if (!result2.success) {
|
|
72
|
+
assert.fail();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
expect(result2.value.items.length).toBeGreaterThan(0);
|
|
76
|
+
expect(result2.value.totalPages).toBeGreaterThan(2);
|
|
77
|
+
expect(result2.value.items[0].identifier.key).not.toBe(
|
|
78
|
+
result.value.items[0].identifier.key
|
|
67
79
|
);
|
|
68
80
|
});
|
|
69
81
|
|
|
@@ -91,15 +103,18 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
91
103
|
filters: [],
|
|
92
104
|
},
|
|
93
105
|
});
|
|
106
|
+
|
|
107
|
+
if (!smallPage.success || !largePage.success) {
|
|
108
|
+
assert.fail();
|
|
109
|
+
}
|
|
94
110
|
|
|
95
|
-
expect(smallPage.items.length).toBe(2);
|
|
96
|
-
expect(smallPage.pageSize).toBe(2);
|
|
97
|
-
expect(largePage.items.length).toBe(30);
|
|
98
|
-
expect(largePage.pageSize).toBe(30);
|
|
111
|
+
expect(smallPage.value.items.length).toBe(2);
|
|
112
|
+
expect(smallPage.value.pageSize).toBe(2);
|
|
113
|
+
expect(largePage.value.items.length).toBe(30);
|
|
114
|
+
expect(largePage.value.pageSize).toBe(30);
|
|
99
115
|
});
|
|
100
116
|
|
|
101
117
|
it('should be able to apply facets', async () => {
|
|
102
|
-
|
|
103
118
|
const initial = await client.productSearch.queryByTerm({
|
|
104
119
|
search: {
|
|
105
120
|
term: "",
|
|
@@ -112,7 +127,11 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
112
127
|
},
|
|
113
128
|
});
|
|
114
129
|
|
|
115
|
-
|
|
130
|
+
if (!initial.success) {
|
|
131
|
+
assert.fail();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
expect(initial.value.facets.length).toBeGreaterThan(0);
|
|
116
135
|
|
|
117
136
|
const filtered = await client.productSearch.queryByTerm({
|
|
118
137
|
search: {
|
|
@@ -121,13 +140,17 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
121
140
|
pageNumber: 1,
|
|
122
141
|
pageSize: 2,
|
|
123
142
|
},
|
|
124
|
-
facets: [initial.facets[0].values[0].identifier],
|
|
143
|
+
facets: [initial.value.facets[0].values[0].identifier],
|
|
125
144
|
filters: [],
|
|
126
145
|
},
|
|
127
146
|
});
|
|
128
147
|
|
|
129
|
-
|
|
130
|
-
|
|
148
|
+
if (!filtered.success) {
|
|
149
|
+
assert.fail();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
expect(initial.value.totalCount).toBeGreaterThan(filtered.value.totalCount);
|
|
153
|
+
expect(filtered.value.totalCount).toBeGreaterThan(0);
|
|
131
154
|
});
|
|
132
155
|
|
|
133
156
|
it('should not return facets with no values', async () => {
|
|
@@ -143,7 +166,11 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
143
166
|
},
|
|
144
167
|
});
|
|
145
168
|
|
|
146
|
-
|
|
169
|
+
if (!result.success) {
|
|
170
|
+
assert.fail();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
for (const facet of result.value.facets) {
|
|
147
174
|
expect(facet.values.length).toBeGreaterThan(0);
|
|
148
175
|
}
|
|
149
176
|
});
|
|
@@ -162,7 +189,11 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
162
189
|
},
|
|
163
190
|
});
|
|
164
191
|
|
|
165
|
-
|
|
192
|
+
if (!result.success) {
|
|
193
|
+
assert.fail();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const categoryFacet = result.value.facets.find(
|
|
166
197
|
(f) => f.identifier.key === 'categories'
|
|
167
198
|
);
|
|
168
199
|
expect(categoryFacet).toBeDefined();
|
|
@@ -179,9 +210,14 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
179
210
|
filters: [],
|
|
180
211
|
},
|
|
181
212
|
});
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
213
|
+
|
|
214
|
+
if (!narrowedResult.success) {
|
|
215
|
+
assert.fail();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
expect(narrowedResult.value.totalCount).toBeLessThan(result.value.totalCount);
|
|
219
|
+
expect(narrowedResult.value.totalCount).toBeGreaterThan(0);
|
|
220
|
+
expect(narrowedResult.value.totalCount).toBe(chosenFacet.count);
|
|
185
221
|
|
|
186
222
|
});
|
|
187
223
|
|
|
@@ -209,21 +245,34 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
209
245
|
},
|
|
210
246
|
});
|
|
211
247
|
|
|
212
|
-
|
|
248
|
+
if (!unfilteredSearch.success || !categories.success) {
|
|
249
|
+
assert.fail();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
expect(unfilteredSearch.value.totalCount).toBeGreaterThan(0);
|
|
213
253
|
|
|
214
254
|
const breadCrumb = await client.category.getBreadcrumbPathToCategory({
|
|
215
|
-
id: categories.items[1].identifier,
|
|
255
|
+
id: categories.value.items[1].identifier,
|
|
216
256
|
});
|
|
217
|
-
|
|
257
|
+
|
|
258
|
+
if (!breadCrumb.success) {
|
|
259
|
+
assert.fail();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
expect(breadCrumb.value.length).toBeGreaterThan(0);
|
|
218
263
|
|
|
219
264
|
const categoryFilter = await client.productSearch.createCategoryNavigationFilter({
|
|
220
|
-
categoryPath: breadCrumb,
|
|
265
|
+
categoryPath: breadCrumb.value,
|
|
221
266
|
} satisfies ProductSearchQueryCreateNavigationFilter);
|
|
222
267
|
|
|
268
|
+
if (!categoryFilter.success) {
|
|
269
|
+
assert.fail();
|
|
270
|
+
}
|
|
271
|
+
|
|
223
272
|
const filteredSearch = await client.productSearch.queryByTerm({
|
|
224
273
|
search: {
|
|
225
274
|
term: "",
|
|
226
|
-
categoryFilter: categoryFilter,
|
|
275
|
+
categoryFilter: categoryFilter.value,
|
|
227
276
|
paginationOptions: {
|
|
228
277
|
pageNumber: 1,
|
|
229
278
|
pageSize: 1,
|
|
@@ -233,8 +282,12 @@ describe.each([PrimaryProvider.ALGOLIA, PrimaryProvider.COMMERCETOOLS])(
|
|
|
233
282
|
},
|
|
234
283
|
});
|
|
235
284
|
|
|
236
|
-
|
|
237
|
-
|
|
285
|
+
if (!filteredSearch.success) {
|
|
286
|
+
assert.fail();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
expect(filteredSearch.value.totalCount).toBeLessThan(unfilteredSearch.value.totalCount);
|
|
290
|
+
expect(filteredSearch.value.totalCount).toBeGreaterThan(0);
|
|
238
291
|
});
|
|
239
292
|
}
|
|
240
293
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import 'dotenv/config';
|
|
2
|
-
import { describe, expect, it, beforeEach } from 'vitest';
|
|
2
|
+
import { describe, expect, it, beforeEach, assert } from 'vitest';
|
|
3
3
|
import { createClient, PrimaryProvider } from '../utils.js';
|
|
4
4
|
|
|
5
5
|
const testData = {
|
|
@@ -12,97 +12,111 @@ const testData = {
|
|
|
12
12
|
},
|
|
13
13
|
productWithMultiVariants: {
|
|
14
14
|
slug: 'hp-gk859aa-mouse-office-bluetooth-laser-1600-dpi-1377612',
|
|
15
|
-
}
|
|
15
|
+
},
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
describe.each([PrimaryProvider.COMMERCETOOLS])(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
client = createClient(provider);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should be able to get a product by id', async () => {
|
|
26
|
-
const result = await client.product.getById({ identifier: { key: testData.product.id } });
|
|
18
|
+
describe.each([PrimaryProvider.COMMERCETOOLS])(
|
|
19
|
+
'Product Capability - %s',
|
|
20
|
+
(provider) => {
|
|
21
|
+
let client: ReturnType<typeof createClient>;
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
expect(result.name).toBe(testData.product.name);
|
|
32
|
-
expect(result.mainVariant.images[0].sourceUrl).toBe(testData.product.image);
|
|
33
|
-
expect(result.mainVariant.name).toBeTruthy();
|
|
34
|
-
});
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
client = createClient(provider);
|
|
25
|
+
});
|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
it('should be able to get a product by id', async () => {
|
|
28
|
+
const response = await client.product.getById({
|
|
29
|
+
identifier: { key: testData.product.id },
|
|
30
|
+
});
|
|
38
31
|
|
|
39
|
-
|
|
32
|
+
if (!response.success) {
|
|
33
|
+
assert.fail();
|
|
34
|
+
}
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
expect(
|
|
43
|
-
expect(
|
|
44
|
-
expect(result.name).toBe(testData.product.name);
|
|
45
|
-
expect(result.mainVariant.images[0].sourceUrl).toBe(
|
|
36
|
+
expect(response.value.identifier.key).toBe(testData.product.id);
|
|
37
|
+
expect(response.value.name).toBe(testData.product.name);
|
|
38
|
+
expect(response.value.mainVariant.images[0].sourceUrl).toBe(
|
|
46
39
|
testData.product.image
|
|
47
40
|
);
|
|
48
|
-
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should be able to get a multivariant product by slug', async () => {
|
|
52
|
-
const result = await client.product.getBySlug({ slug: testData.productWithMultiVariants.slug });
|
|
53
|
-
expect(result).toBeTruthy();
|
|
54
|
-
if (result) {
|
|
55
|
-
expect(result.meta.placeholder).toBe(false);
|
|
56
|
-
expect(result.identifier.key).toBeTruthy();
|
|
57
|
-
expect(result.slug).toBe(testData.productWithMultiVariants.slug);
|
|
58
|
-
expect(result.mainVariant).toBeDefined();
|
|
59
|
-
expect(result.variants.length).toBeGreaterThan(0);
|
|
60
|
-
expect(result.variants[0].identifier.sku).toBeTruthy();
|
|
61
|
-
expect(result.variants[0].identifier.sku).not.toBe(result.mainVariant.identifier.sku);
|
|
62
|
-
expect(result!.sharedAttributes.length).toBeGreaterThan(1);
|
|
63
|
-
expect(result!.sharedAttributes[1].values.length).toBeGreaterThan(0);
|
|
64
|
-
expect(result!.sharedAttributes[1].values[0].value).toBeTruthy();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
it('should be able to get a product by sku', async () => {
|
|
70
|
-
const result = await client.product.getBySKU({
|
|
71
|
-
variant: { sku: testData.product.sku },
|
|
41
|
+
expect(response.value.mainVariant.name).toBeTruthy();
|
|
72
42
|
});
|
|
73
43
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
44
|
+
it('should be able to get a product by slug', async () => {
|
|
45
|
+
const response = await client.product.getBySlug({
|
|
46
|
+
slug: testData.product.slug,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!response.success) {
|
|
50
|
+
assert.fail();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
expect(response.value.identifier.key).toBe(testData.product.id);
|
|
54
|
+
expect(response.value.name).toBe(testData.product.name);
|
|
55
|
+
expect(response.value.mainVariant.images[0].sourceUrl).toBe(
|
|
80
56
|
testData.product.image
|
|
81
57
|
);
|
|
82
|
-
}
|
|
83
|
-
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should be able to get a multivariant product by slug', async () => {
|
|
61
|
+
const response = await client.product.getBySlug({
|
|
62
|
+
slug: testData.productWithMultiVariants.slug,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (!response.success) {
|
|
66
|
+
assert.fail();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
expect(response.value.identifier.key).toBeTruthy();
|
|
70
|
+
expect(response.value.slug).toBe(testData.productWithMultiVariants.slug);
|
|
71
|
+
expect(response.value.mainVariant).toBeDefined();
|
|
72
|
+
expect(response.value.variants.length).toBeGreaterThan(0);
|
|
73
|
+
expect(response.value.variants[0].identifier.sku).toBeTruthy();
|
|
74
|
+
expect(response.value.variants[0].identifier.sku).not.toBe(
|
|
75
|
+
response.value.mainVariant.identifier.sku
|
|
76
|
+
);
|
|
77
|
+
expect(response.value.sharedAttributes.length).toBeGreaterThan(1);
|
|
78
|
+
expect(response.value.sharedAttributes[1].values.length).toBeGreaterThan(0);
|
|
79
|
+
expect(response.value.sharedAttributes[1].values[0].value).toBeTruthy();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should be able to get a product by sku', async () => {
|
|
83
|
+
const response = await client.product.getBySKU({
|
|
84
|
+
variant: { sku: testData.product.sku },
|
|
85
|
+
});
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
if (!response.success) {
|
|
88
|
+
assert.fail();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
expect(response.value.identifier.key).toBe(testData.product.id);
|
|
92
|
+
expect(response.value.name).toBe(testData.product.name);
|
|
93
|
+
expect(response.value.mainVariant.images[0].sourceUrl).toBe(
|
|
94
|
+
testData.product.image
|
|
95
|
+
);
|
|
88
96
|
});
|
|
89
97
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
})
|
|
98
|
+
it('should contain both product level and variant level attributes', async () => {
|
|
99
|
+
const response = await client.product.getBySKU({
|
|
100
|
+
variant: { sku: testData.product.sku },
|
|
101
|
+
});
|
|
95
102
|
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
if (!response.success) {
|
|
104
|
+
assert.fail();
|
|
105
|
+
}
|
|
98
106
|
|
|
99
|
-
|
|
100
|
-
|
|
107
|
+
expect(response.value.sharedAttributes.length).toBeGreaterThan(1);
|
|
108
|
+
expect(response.value.sharedAttributes[1].values.length).toBeGreaterThan(0);
|
|
109
|
+
expect(response.value.sharedAttributes[1].values[0].value).toBeTruthy();
|
|
110
|
+
});
|
|
101
111
|
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
it('should return an error of NotFound for unknown slug', async () => {
|
|
113
|
+
const response = await client.product.getBySlug({ slug: 'unknown-slug' });
|
|
114
|
+
|
|
115
|
+
if (response.success) {
|
|
116
|
+
assert.fail();
|
|
117
|
+
}
|
|
104
118
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
119
|
+
expect(response.error.type).toBe('NotFound');
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
);
|