@reactionary/examples-node 0.2.1 → 0.2.3

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 CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@reactionary/examples-node",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "main": "index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "dependencies": {
7
- "@reactionary/core": "0.2.1",
8
- "@reactionary/provider-commercetools": "0.2.1",
9
- "@reactionary/provider-algolia": "0.2.1"
7
+ "@reactionary/core": "0.2.3",
8
+ "@reactionary/provider-commercetools": "0.2.3",
9
+ "@reactionary/provider-algolia": "0.2.3",
10
+ "@reactionary/provider-medusa": "0.2.3"
10
11
  },
11
12
  "type": "module"
12
13
  }
@@ -0,0 +1,159 @@
1
+ import 'dotenv/config';
2
+ import { assert, beforeEach, describe, expect, it, vi } from 'vitest';
3
+ import { createClient, PrimaryProvider } from '../utils.js';
4
+ import type { ProductSearchQueryCreateNavigationFilter } from '@reactionary/core';
5
+
6
+ const testData = {
7
+ searchTerm: '',
8
+ sku: '0766623301831'
9
+ };
10
+
11
+ describe.each([PrimaryProvider.COMMERCETOOLS])(
12
+ 'Order Search Capability - %s',
13
+ (provider) => {
14
+ let client: ReturnType<typeof createClient>;
15
+
16
+ beforeEach(() => {
17
+ client = createClient(provider);
18
+ });
19
+
20
+ // Technically, i should create a bunch of orders first, but a) that would make the test way longer, and b) they would all be on the same day with same statuses.
21
+ it('can be called by anonymous users', async () => {
22
+ const result = await client.orderSearch.queryByTerm({
23
+ search: {
24
+ term: testData.searchTerm,
25
+ paginationOptions: {
26
+ pageNumber: 1,
27
+ pageSize: 10,
28
+ },
29
+ filters: [],
30
+ },
31
+ });
32
+
33
+ if (!result.success) {
34
+ assert.fail(JSON.stringify(result.error));
35
+ }
36
+ });
37
+
38
+ it('can be called by guest users', async () => {
39
+ const updatedCart = await client.cart.add(
40
+ {
41
+ quantity: 1,
42
+ variant: {
43
+ sku: testData.sku
44
+ },
45
+ }
46
+ );
47
+ const identity = await client.identity.getSelf({});
48
+
49
+ if (!identity.success) {
50
+ assert.fail();
51
+ }
52
+
53
+ expect(identity.value.type).toBe('Guest');
54
+
55
+ const result = await client.orderSearch.queryByTerm({
56
+ search: {
57
+ term: testData.searchTerm,
58
+ paginationOptions: {
59
+ pageNumber: 1,
60
+ pageSize: 10,
61
+ },
62
+ filters: [],
63
+ },
64
+ });
65
+
66
+ if (!result.success) {
67
+ assert.fail(JSON.stringify(result.error));
68
+ }
69
+ });
70
+
71
+ it('can be called by an authenticated user', async () => {
72
+ const time = new Date().getTime();
73
+ const identity = await client.identity.register(
74
+ {
75
+ username: `test-user+${time}@example.com`,
76
+ password: 'love2test',
77
+ }
78
+ );
79
+
80
+ if (!identity.success) {
81
+ assert.fail();
82
+ }
83
+
84
+ expect(identity.value.type).toBe('Registered');
85
+ const result = await client.orderSearch.queryByTerm({
86
+ search: {
87
+ term: testData.searchTerm,
88
+ paginationOptions: {
89
+ pageNumber: 1,
90
+ pageSize: 10,
91
+ },
92
+ filters: [],
93
+ },
94
+ });
95
+
96
+ if (!result.success) {
97
+ assert.fail(JSON.stringify(result.error));
98
+ }
99
+
100
+ });
101
+ it.skip('can filter by startDate', async () => {
102
+ /** TODO */
103
+ });
104
+
105
+ it.skip('can filter by endDate', async () => {
106
+ /** TODO */
107
+ });
108
+
109
+ it.skip('can filter by orderStatus', async () => {
110
+ /** TODO */
111
+ });
112
+
113
+ it.skip('can filter by multiple orderStatuses', async () => {
114
+ /** TODO */
115
+ });
116
+
117
+ it.skip('can filter by partNumber', async () => {
118
+ /** TODO */
119
+ });
120
+
121
+
122
+ it.skip('can page the resultset', async () => {
123
+ const result = await client.orderSearch.queryByTerm({
124
+ search: {
125
+ term: testData.searchTerm,
126
+ paginationOptions: {
127
+ pageNumber: 1,
128
+ pageSize: 2,
129
+ },
130
+ filters: [],
131
+ },
132
+ });
133
+
134
+ if (!result.success) {
135
+ assert.fail(JSON.stringify(result.error));
136
+ }
137
+
138
+ const result2 = await client.orderSearch.queryByTerm({
139
+ search: {
140
+ term: testData.searchTerm,
141
+ paginationOptions: {
142
+ pageNumber: 2,
143
+ pageSize: 2,
144
+ },
145
+ filters: [],
146
+ },
147
+ });
148
+
149
+ if (!result2.success) {
150
+ assert.fail(JSON.stringify(result2.error));
151
+ }
152
+
153
+ expect(result.value.items[0].identifier).not.toBe(
154
+ result2.value.items[0].identifier
155
+ );
156
+ });
157
+ }
158
+
159
+ );
@@ -0,0 +1,91 @@
1
+ import 'dotenv/config';
2
+ import { assert, beforeEach, describe, expect, it, vi } from 'vitest';
3
+ import { createClient, PrimaryProvider } from '../utils.js';
4
+ import type { OrderIdentifier, ProductSearchQueryCreateNavigationFilter } from '@reactionary/core';
5
+
6
+ const testData = {
7
+ searchTerm: '',
8
+ sku: '0766623301831',
9
+ };
10
+
11
+ describe.each([PrimaryProvider.COMMERCETOOLS])(
12
+ 'Order Search Capability - %s',
13
+ (provider) => {
14
+ let client: ReturnType<typeof createClient>;
15
+
16
+ beforeEach(() => {
17
+ client = createClient(provider);
18
+ });
19
+
20
+ it.skip('can be called by guest users', async () => {
21
+ const updatedCart = await client.cart.add(
22
+ {
23
+ quantity: 1,
24
+ variant: {
25
+ sku: testData.sku
26
+ },
27
+ }
28
+ );
29
+ // create order....somehow.....
30
+
31
+ const orderId: OrderIdentifier = { key: '123456'};
32
+ const identity = await client.identity.getSelf({});
33
+ if (!identity.success) {
34
+ assert.fail();
35
+ }
36
+
37
+ expect(identity.value.type).toBe('Guest');
38
+ const result = await client.order.getById({ order: orderId });
39
+ if (!result.success) {
40
+ assert.fail(JSON.stringify(result.error));
41
+ }
42
+
43
+ const order = result.value;
44
+ expect(order.identifier.key).toBe(orderId.key);
45
+ expect(order.items.length).toBeGreaterThan(0);
46
+ expect(order.price.grandTotal.value).toBeGreaterThan(0);
47
+
48
+ });
49
+
50
+ it.skip('can be called by registered users', async () => {
51
+ const time = new Date().getTime();
52
+ const identity = await client.identity.register(
53
+ {
54
+ username: `test-user+${time}@example.com`,
55
+ password: 'love2test',
56
+ }
57
+ );
58
+
59
+ if (!identity.success) {
60
+ assert.fail();
61
+ }
62
+
63
+ expect(identity.value.type).toBe('Registered');
64
+
65
+ const updatedCart = await client.cart.add(
66
+ {
67
+ quantity: 1,
68
+ variant: {
69
+ sku: testData.sku
70
+ },
71
+ }
72
+ );
73
+ // create order....somehow.....
74
+
75
+ const orderId: OrderIdentifier = { key: '456789'};
76
+
77
+
78
+ expect(identity.value.type).toBe('Guest');
79
+ const result = await client.order.getById({ order: orderId });
80
+ if (!result.success) {
81
+ assert.fail(JSON.stringify(result.error));
82
+ }
83
+
84
+ const order = result.value;
85
+ expect(order.identifier.key).toBe(orderId.key);
86
+ expect(order.items.length).toBeGreaterThan(0);
87
+ expect(order.price.grandTotal.value).toBeGreaterThan(0);
88
+ });
89
+
90
+
91
+ });
@@ -1,28 +1,316 @@
1
1
  import 'dotenv/config';
2
2
  import { describe, expect, it, beforeEach, assert } from 'vitest';
3
3
  import { createClient, PrimaryProvider } from '../utils.js';
4
+ import { IdentityIdentifierSchema, type Address, type Identity, type IdentityIdentifier, type Profile } from '@reactionary/core';
4
5
 
5
- describe.each([PrimaryProvider.COMMERCETOOLS])('Profile Capability - %s', (provider) => {
6
- let client: ReturnType<typeof createClient>;
6
+ describe.each([PrimaryProvider.MEDUSA, PrimaryProvider.COMMERCETOOLS])(
7
+ 'Profile Capability - %s',
8
+ (provider) => {
9
+ let client: ReturnType<typeof createClient>;
10
+ let identity: Identity | null = null;
11
+ let identityIdentifier: IdentityIdentifier | null = null;
7
12
 
8
- beforeEach(() => {
9
- client = createClient(provider);
10
- });
13
+ beforeEach(async () => {
14
+ client = createClient(provider);
15
+ const time = new Date().getTime();
11
16
 
12
- it('should be able to fetch the profile for the current user', async () => {
13
- const time = new Date().getTime();
17
+ const identityResponse = await client.identity.register({
18
+ username: `martin.rogne+test-${time}@solteq.com`,
19
+ password: 'love2test',
20
+ });
14
21
 
15
- await client.identity.register({
16
- username: `martin.rogne+test-${time}@solteq.com`,
17
- password: 'love2test',
22
+ if (!identityResponse.success) {
23
+ assert.fail();
24
+ }
25
+
26
+ identity = identityResponse.value;
27
+ if (identity.type !== 'Registered') {
28
+ assert.fail();
29
+ }
30
+ identityIdentifier = identity.id;
31
+ });
32
+
33
+ it('should be able to fetch the profile for the current user', async () => {
34
+ const time = new Date().getTime();
35
+ if (!identity) {
36
+ assert.fail();
37
+ }
38
+
39
+ if (identity.type !== 'Registered') {
40
+ assert.fail();
41
+ }
42
+
43
+ const profile = await client.profile.getById({
44
+ identifier: identity.id,
45
+ });
46
+
47
+ if (!profile.success) {
48
+ console.log(profile.error);
49
+ assert.fail();
50
+ }
51
+
52
+ expect(profile.value.email).toContain('martin.rogne');
53
+ });
54
+
55
+ it('should be able to update the profile for the current user', async () => {
56
+
57
+ const time = new Date().getTime();
58
+ const updatedProfile = await client.profile.update({
59
+ identifier: identityIdentifier!,
60
+ phone: '+4712345678',
61
+ email: `martin.rogne+test-${time}-a@solteq.com`,
62
+ });
63
+
64
+ if (!updatedProfile.success) {
65
+ console.log(updatedProfile.error);
66
+ assert.fail();
67
+ }
68
+
69
+ expect(updatedProfile.value.email).toBe(
70
+ `martin.rogne+test-${time}-a@solteq.com`
71
+ );
72
+ expect(updatedProfile.value.phone).toBe('+4712345678');
73
+ expect(updatedProfile.value.billingAddress).toBeUndefined();
18
74
  });
19
75
 
20
- const profile = await client.profile.getSelf({});
76
+ it('should be able to set the billing address on the profile', async () => {
77
+ if (!identity) {
78
+ assert.fail();
79
+ }
21
80
 
22
- if (!profile.success) {
23
- assert.fail();
24
- }
81
+ if (identity.type !== 'Registered') {
82
+ assert.fail();
83
+ }
84
+ const newAddress: Address = {
85
+ identifier: {
86
+ nickName: 'Billing',
87
+ },
88
+ firstName: 'Jane',
89
+ lastName: 'Doe',
90
+ streetAddress: 'Second Street',
91
+ streetNumber: '456',
92
+ city: 'Gotham',
93
+ region: 'State',
94
+ postalCode: '67890',
95
+ countryCode: 'US',
96
+ };
97
+ const updatedProfile = await client.profile.setBillingAddress({
98
+ identifier: identity.id,
99
+ address: newAddress,
100
+ });
25
101
 
26
- expect(profile.value.email).toContain('martin.rogne');
27
- });
28
- });
102
+ if (!updatedProfile.success) {
103
+ console.log(updatedProfile.error);
104
+ assert.fail();
105
+ }
106
+ expect(updatedProfile.value.billingAddress).toMatchObject(newAddress);
107
+ });
108
+
109
+ it('cannot use same nickname for billing and shipping addresses', async () => {
110
+ if (!identity) {
111
+ assert.fail();
112
+ }
113
+
114
+ if (identity.type !== 'Registered') {
115
+ assert.fail();
116
+ }
117
+ const newAddress: Address = {
118
+ identifier: {
119
+ nickName: 'SameNick',
120
+ },
121
+ firstName: 'Jane',
122
+ lastName: 'Doe',
123
+ streetAddress: 'Second Street',
124
+ streetNumber: '456',
125
+ city: 'Gotham',
126
+ region: 'State',
127
+ postalCode: '67890',
128
+ countryCode: 'US',
129
+ };
130
+ const billingAddressResponse = await client.profile.setBillingAddress({
131
+ identifier: identity.id,
132
+ address: newAddress,
133
+ });
134
+
135
+ if (!billingAddressResponse.success) {
136
+ console.log(billingAddressResponse.error);
137
+ assert.fail();
138
+ }
139
+
140
+ const shippingAddressResponse = await client.profile.addShippingAddress({
141
+ identifier: identity.id,
142
+ address: newAddress,
143
+ });
144
+ expect(shippingAddressResponse.success).toBe(false);
145
+ });
146
+
147
+ it('cannot set the billing address to an existing shipping address', async () => {
148
+ if (!identity) {
149
+ assert.fail();
150
+ }
151
+
152
+ if (identity.type !== 'Registered') {
153
+ assert.fail();
154
+ }
155
+ const newAddress: Address = {
156
+ identifier: {
157
+ nickName: 'SameNick',
158
+ },
159
+ firstName: 'Jane',
160
+ lastName: 'Doe',
161
+ streetAddress: 'Second Street',
162
+ streetNumber: '456',
163
+ city: 'Gotham',
164
+ region: 'State',
165
+ postalCode: '67890',
166
+ countryCode: 'US',
167
+ };
168
+ const shippingAddressResponse = await client.profile.addShippingAddress({
169
+ identifier: identity.id,
170
+ address: newAddress,
171
+ });
172
+
173
+ if (!shippingAddressResponse.success) {
174
+ console.log(shippingAddressResponse.error);
175
+ assert.fail();
176
+ }
177
+
178
+ const billingAddress = await client.profile.setBillingAddress({
179
+ identifier: identity.id,
180
+ address: shippingAddressResponse.value.alternateShippingAddresses[0]
181
+ });
182
+ expect(billingAddress.success).toBe(false);
183
+ });
184
+
185
+
186
+ it('should be able to add a shipping address to the profile', async () => {
187
+ if (!identity) {
188
+ assert.fail();
189
+ }
190
+
191
+ if (identity.type !== 'Registered') {
192
+ assert.fail();
193
+ }
194
+
195
+ const newAddress: Address = {
196
+ identifier: {
197
+ nickName: 'Home',
198
+ },
199
+ firstName: 'John',
200
+ lastName: 'Doe',
201
+ streetAddress: 'Main Street',
202
+ streetNumber: '123',
203
+ city: 'Metropolis',
204
+ region: 'State',
205
+ postalCode: '12345',
206
+ countryCode: 'US',
207
+ };
208
+ const updatedProfile = await client.profile.addShippingAddress({
209
+ identifier: identity.id,
210
+ address: newAddress,
211
+ });
212
+
213
+ if (!updatedProfile.success) {
214
+ console.log(updatedProfile.error);
215
+ assert.fail();
216
+ }
217
+ expect(updatedProfile.value.shippingAddress).toBeUndefined();
218
+
219
+ expect(updatedProfile.value.alternateShippingAddresses.length).toBe(1);
220
+ expect(updatedProfile.value.alternateShippingAddresses[0]).toMatchObject(
221
+ newAddress
222
+ );
223
+ });
224
+
225
+ describe('Shipping Addresses', () => {
226
+ const newAddress: Address = {
227
+ identifier: {
228
+ nickName: 'Home',
229
+ },
230
+ firstName: 'John',
231
+ lastName: 'Doe',
232
+ streetAddress: 'Main Street',
233
+ streetNumber: '123',
234
+ city: 'Metropolis',
235
+ region: 'State',
236
+ postalCode: '12345',
237
+ countryCode: 'US',
238
+ };
239
+ let profile: Profile | null;
240
+
241
+ beforeEach(async () => {
242
+ const updatedProfile = await client.profile.addShippingAddress({
243
+ identifier: identityIdentifier!,
244
+ address: newAddress,
245
+ });
246
+
247
+ if (!updatedProfile.success) {
248
+ console.log(updatedProfile.error);
249
+ assert.fail();
250
+ }
251
+
252
+ profile = updatedProfile.value;
253
+ });
254
+
255
+ it('can make a shipping address the default address', async () => {
256
+ const addressToMakeDefault =
257
+ profile!.alternateShippingAddresses[0];
258
+
259
+ const updatedProfile = await client.profile.makeShippingAddressDefault({
260
+ identifier: identityIdentifier!,
261
+ addressIdentifier: addressToMakeDefault.identifier,
262
+ });
263
+
264
+ if (!updatedProfile.success) {
265
+ console.log(updatedProfile.error);
266
+ assert.fail();
267
+ }
268
+ expect(updatedProfile.value.shippingAddress).toBeDefined();
269
+ expect(updatedProfile.value.shippingAddress).toMatchObject(newAddress);
270
+ expect(updatedProfile.value.alternateShippingAddresses.length).toBe(0);
271
+ });
272
+
273
+ it('can remove a shipping address from the profile', async () => {
274
+ const addressToRemove =
275
+ profile!.alternateShippingAddresses[0];
276
+
277
+ const updatedProfile = await client.profile.removeShippingAddress({
278
+ identifier: identityIdentifier!,
279
+ addressIdentifier: addressToRemove.identifier,
280
+ });
281
+ if (!updatedProfile.success) {
282
+ console.log(updatedProfile.error);
283
+ assert.fail();
284
+ }
285
+
286
+ expect(updatedProfile.value.alternateShippingAddresses.length).toBe(0);
287
+ });
288
+
289
+ it('can remove a shipping address from the profile even if it is the default shipping address', async () => {
290
+ const makeDefaultResponse = await client.profile.makeShippingAddressDefault({
291
+ identifier: identityIdentifier!,
292
+ addressIdentifier: profile!.alternateShippingAddresses[0].identifier,
293
+ });
294
+ if (!makeDefaultResponse.success) {
295
+ console.log(makeDefaultResponse.error);
296
+ assert.fail();
297
+ }
298
+
299
+ const profileWithDefault = makeDefaultResponse.value;
300
+ const addressToRemove = profileWithDefault.shippingAddress!;
301
+
302
+ const updatedProfile = await client.profile.removeShippingAddress({
303
+ identifier: identityIdentifier!,
304
+ addressIdentifier: addressToRemove.identifier,
305
+ });
306
+
307
+ if (!updatedProfile.success) {
308
+ console.log(updatedProfile.error);
309
+ assert.fail();
310
+ }
311
+ expect(updatedProfile.value.shippingAddress).toBeUndefined();
312
+ expect(updatedProfile.value.alternateShippingAddresses.length).toBe(0);
313
+ });
314
+ });
315
+ }
316
+ );
package/src/utils.ts CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  import type { CommercetoolsConfiguration } from '@reactionary/provider-commercetools';
7
7
  import { withCommercetoolsCapabilities } from '@reactionary/provider-commercetools';
8
8
  import { withAlgoliaCapabilities } from '@reactionary/provider-algolia';
9
+ import { withMedusaCapabilities } from '@reactionary/provider-medusa';
9
10
 
10
11
  export function getAlgoliaTestConfiguration() {
11
12
  return {
@@ -63,22 +64,46 @@ export enum PrimaryProvider {
63
64
  export function createClient(provider: PrimaryProvider) {
64
65
  const context = createInitialRequestContext();
65
66
  let builder = new ClientBuilder(context)
66
- .withCache(new NoOpCache())
67
- .withCapability(
68
- withCommercetoolsCapabilities(getCommercetoolsTestConfiguration(), {
69
- cart: true,
70
- product: true,
71
- category: true,
72
- checkout: true,
73
- identity: true,
74
- inventory: true,
75
- order: true,
76
- price: true,
77
- productSearch: true,
78
- store: true,
79
- profile: true,
80
- })
81
- );
67
+ .withCache(new NoOpCache());
68
+
69
+ if (provider === PrimaryProvider.MEDUSA) {
70
+ builder = builder.withCapability(
71
+ withMedusaCapabilities( getMedusaTestConfiguration(), {
72
+ cart: true,
73
+ product: true,
74
+ category: true,
75
+ checkout: true,
76
+ identity: true,
77
+ inventory: true,
78
+ order: true,
79
+ price: true,
80
+ productSearch: true,
81
+ store: true,
82
+ profile: true
83
+ })
84
+ );
85
+ }
86
+
87
+
88
+
89
+ if (provider === PrimaryProvider.COMMERCETOOLS) {
90
+ builder = builder.withCapability(
91
+ withCommercetoolsCapabilities(getCommercetoolsTestConfiguration(), {
92
+ cart: true,
93
+ product: true,
94
+ category: true,
95
+ checkout: true,
96
+ identity: true,
97
+ inventory: true,
98
+ order: true,
99
+ price: true,
100
+ productSearch: true,
101
+ store: true,
102
+ profile: true,
103
+ })
104
+ );
105
+ }
106
+
82
107
 
83
108
  if (provider === PrimaryProvider.ALGOLIA) {
84
109
  builder = builder.withCapability(