@reactionary/source 0.0.41 → 0.0.48

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.
Files changed (125) hide show
  1. package/.claude/settings.local.json +28 -0
  2. package/.env-template +8 -5
  3. package/.vscode/settings.json +5 -0
  4. package/README.md +41 -0
  5. package/core/package.json +3 -1
  6. package/core/src/cache/cache.interface.ts +14 -18
  7. package/core/src/cache/memory-cache.ts +56 -0
  8. package/core/src/cache/noop-cache.ts +5 -23
  9. package/core/src/cache/redis-cache.ts +28 -38
  10. package/core/src/client/client-builder.ts +3 -3
  11. package/core/src/client/client.ts +11 -9
  12. package/core/src/decorators/reactionary.decorator.ts +80 -8
  13. package/core/src/index.ts +5 -29
  14. package/core/src/initialization.ts +43 -0
  15. package/core/src/providers/analytics.provider.ts +1 -1
  16. package/core/src/providers/base.provider.ts +61 -25
  17. package/core/src/providers/cart-payment.provider.ts +57 -0
  18. package/core/src/providers/cart.provider.ts +131 -8
  19. package/core/src/providers/category.provider.ts +9 -9
  20. package/core/src/providers/identity.provider.ts +8 -7
  21. package/core/src/providers/index.ts +12 -0
  22. package/core/src/providers/inventory.provider.ts +4 -4
  23. package/core/src/providers/price.provider.ts +7 -7
  24. package/core/src/providers/product.provider.ts +17 -5
  25. package/core/src/providers/profile.provider.ts +22 -0
  26. package/core/src/providers/search.provider.ts +4 -4
  27. package/core/src/providers/store.provider.ts +14 -0
  28. package/core/src/schemas/capabilities.schema.ts +3 -1
  29. package/core/src/schemas/models/analytics.model.ts +1 -1
  30. package/core/src/schemas/models/cart.model.ts +16 -3
  31. package/core/src/schemas/models/identifiers.model.ts +90 -22
  32. package/core/src/schemas/models/identity.model.ts +23 -7
  33. package/core/src/schemas/models/index.ts +15 -0
  34. package/core/src/schemas/models/payment.model.ts +41 -0
  35. package/core/src/schemas/models/profile.model.ts +35 -0
  36. package/core/src/schemas/models/shipping-method.model.ts +14 -0
  37. package/core/src/schemas/models/store.model.ts +11 -0
  38. package/core/src/schemas/mutations/cart-payment.mutation.ts +21 -0
  39. package/core/src/schemas/mutations/cart.mutation.ts +62 -3
  40. package/core/src/schemas/mutations/identity.mutation.ts +8 -1
  41. package/core/src/schemas/mutations/index.ts +10 -0
  42. package/core/src/schemas/mutations/profile.mutation.ts +9 -0
  43. package/core/src/schemas/queries/cart-payment.query.ts +12 -0
  44. package/core/src/schemas/queries/cart.query.ts +1 -1
  45. package/core/src/schemas/queries/identity.query.ts +1 -1
  46. package/core/src/schemas/queries/index.ts +3 -0
  47. package/core/src/schemas/queries/inventory.query.ts +4 -12
  48. package/core/src/schemas/queries/price.query.ts +1 -1
  49. package/core/src/schemas/queries/profile.query.ts +7 -0
  50. package/core/src/schemas/queries/search.query.ts +1 -1
  51. package/core/src/schemas/queries/store.query.ts +11 -0
  52. package/core/src/schemas/session.schema.ts +31 -6
  53. package/eslint.config.mjs +7 -0
  54. package/examples/next/src/app/page.tsx +4 -12
  55. package/examples/node/package.json +1 -3
  56. package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +9 -8
  57. package/examples/node/src/basic/basic-node-provider-query-extension.spec.ts +4 -3
  58. package/examples/node/src/basic/basic-node-setup.spec.ts +4 -5
  59. package/nx.json +1 -0
  60. package/otel/src/metrics.ts +2 -1
  61. package/otel/src/provider-instrumentation.ts +2 -1
  62. package/otel/src/tracer.ts +7 -6
  63. package/otel/src/trpc-middleware.ts +3 -2
  64. package/package.json +2 -1
  65. package/providers/algolia/src/core/initialize.ts +4 -3
  66. package/providers/algolia/src/providers/product.provider.ts +15 -13
  67. package/providers/algolia/src/providers/search.provider.ts +9 -9
  68. package/providers/algolia/src/schema/capabilities.schema.ts +1 -1
  69. package/providers/algolia/src/test/search.provider.spec.ts +10 -10
  70. package/providers/algolia/src/test/test-utils.ts +9 -4
  71. package/providers/commercetools/README.md +27 -0
  72. package/providers/commercetools/src/core/client.ts +164 -117
  73. package/providers/commercetools/src/core/initialize.ts +24 -14
  74. package/providers/commercetools/src/providers/cart-payment.provider.ts +193 -0
  75. package/providers/commercetools/src/providers/cart.provider.ts +402 -125
  76. package/providers/commercetools/src/providers/category.provider.ts +35 -35
  77. package/providers/commercetools/src/providers/identity.provider.ts +23 -75
  78. package/providers/commercetools/src/providers/index.ts +2 -0
  79. package/providers/commercetools/src/providers/inventory.provider.ts +69 -40
  80. package/providers/commercetools/src/providers/price.provider.ts +79 -47
  81. package/providers/commercetools/src/providers/product.provider.ts +36 -30
  82. package/providers/commercetools/src/providers/profile.provider.ts +61 -0
  83. package/providers/commercetools/src/providers/search.provider.ts +16 -12
  84. package/providers/commercetools/src/providers/store.provider.ts +78 -0
  85. package/providers/commercetools/src/schema/capabilities.schema.ts +3 -1
  86. package/providers/commercetools/src/schema/commercetools.schema.ts +18 -0
  87. package/providers/commercetools/src/schema/configuration.schema.ts +2 -1
  88. package/providers/commercetools/src/test/cart-payment.provider.spec.ts +145 -0
  89. package/providers/commercetools/src/test/cart.provider.spec.ts +82 -22
  90. package/providers/commercetools/src/test/category.provider.spec.ts +18 -17
  91. package/providers/commercetools/src/test/identity.provider.spec.ts +88 -0
  92. package/providers/commercetools/src/test/inventory.provider.spec.ts +41 -0
  93. package/providers/commercetools/src/test/price.provider.spec.ts +9 -8
  94. package/providers/commercetools/src/test/product.provider.spec.ts +33 -5
  95. package/providers/commercetools/src/test/profile.provider.spec.ts +49 -0
  96. package/providers/commercetools/src/test/search.provider.spec.ts +8 -7
  97. package/providers/commercetools/src/test/store.provider.spec.ts +37 -0
  98. package/providers/commercetools/src/test/test-utils.ts +7 -31
  99. package/providers/fake/src/core/initialize.ts +96 -38
  100. package/providers/fake/src/providers/analytics.provider.ts +6 -5
  101. package/providers/fake/src/providers/cart.provider.ts +66 -19
  102. package/providers/fake/src/providers/category.provider.ts +12 -12
  103. package/providers/fake/src/providers/identity.provider.ts +22 -14
  104. package/providers/fake/src/providers/index.ts +1 -0
  105. package/providers/fake/src/providers/inventory.provider.ts +13 -13
  106. package/providers/fake/src/providers/price.provider.ts +13 -13
  107. package/providers/fake/src/providers/product.provider.ts +13 -10
  108. package/providers/fake/src/providers/search.provider.ts +7 -5
  109. package/providers/fake/src/providers/store.provider.ts +47 -0
  110. package/providers/fake/src/schema/capabilities.schema.ts +4 -1
  111. package/providers/fake/src/test/cart.provider.spec.ts +18 -18
  112. package/providers/fake/src/test/category.provider.spec.ts +55 -37
  113. package/providers/fake/src/test/price.provider.spec.ts +9 -14
  114. package/providers/fake/src/test/product.provider.spec.ts +27 -0
  115. package/providers/fake/src/test/test-utils.ts +2 -28
  116. package/providers/posthog/src/core/initialize.ts +3 -3
  117. package/providers/posthog/src/schema/capabilities.schema.ts +1 -1
  118. package/trpc/src/client.ts +42 -41
  119. package/trpc/src/index.ts +4 -3
  120. package/trpc/src/integration.spec.ts +11 -11
  121. package/trpc/src/server.ts +26 -24
  122. package/trpc/src/test-utils.ts +9 -4
  123. package/trpc/src/types.ts +24 -22
  124. package/core/src/cache/cache-evaluation.interface.ts +0 -19
  125. package/examples/node/src/test-utils.ts +0 -26
@@ -1,15 +1,13 @@
1
1
  import {
2
- ProductProvider,
3
- Product,
4
- ProductQueryById,
5
- ProductQueryBySlug,
6
- Session,
7
- Cache,
2
+ ProductProvider
8
3
  } from '@reactionary/core';
9
4
  import { CommercetoolsClient } from '../core/client';
10
- import { z } from 'zod';
11
- import { CommercetoolsConfiguration } from '../schema/configuration.schema';
12
- import { ProductProjection } from '@commercetools/platform-sdk';
5
+ import type { z } from 'zod';
6
+ import type { CommercetoolsConfiguration } from '../schema/configuration.schema';
7
+ import type { ProductProjection } from '@commercetools/platform-sdk';
8
+ import { traced } from '@reactionary/otel';
9
+ import type { Product, ProductQueryById, ProductQueryBySlug, RequestContext } from '@reactionary/core';
10
+ import type { Cache } from '@reactionary/core';
13
11
 
14
12
  export class CommercetoolsProductProvider<
15
13
  T extends Product = Product
@@ -22,29 +20,37 @@ export class CommercetoolsProductProvider<
22
20
  this.config = config;
23
21
  }
24
22
 
25
- public getClient(session: Session) {
26
- return new CommercetoolsClient(this.config).getClient(session.identity?.token).withProjectKey({ projectKey: this.config.projectKey }).productProjections();
23
+ protected async getClient(reqCtx: RequestContext) {
24
+
25
+ const client = await new CommercetoolsClient(this.config).getClient(reqCtx);
26
+ return client.withProjectKey({ projectKey: this.config.projectKey }).productProjections();
27
27
  }
28
28
 
29
+ @traced()
29
30
  public override async getById(
30
31
  payload: ProductQueryById,
31
- session: Session
32
+ reqCtx: RequestContext
32
33
  ): Promise<T> {
33
- const client = this.getClient(session);
34
+ const client = await this.getClient(reqCtx);
34
35
 
35
- const remote = await client
36
- .withId({ ID: payload.id })
37
- .get()
38
- .execute();
36
+ try {
37
+ const remote = await client
38
+ .withId({ ID: payload.id })
39
+ .get()
40
+ .execute();
39
41
 
40
- return this.parseSingle(remote.body, session);
42
+ return this.parseSingle(remote.body, reqCtx);
43
+ } catch(error) {
44
+ return this.createEmptyProduct(payload.id);
45
+ }
41
46
  }
42
47
 
48
+ @traced()
43
49
  public override async getBySlug(
44
50
  payload: ProductQueryBySlug,
45
- session: Session
46
- ): Promise<T> {
47
- const client = this.getClient(session);
51
+ reqCtx: RequestContext
52
+ ): Promise<T | null> {
53
+ const client = await this.getClient(reqCtx);
48
54
 
49
55
  const remote = await client
50
56
  .get({
@@ -55,23 +61,23 @@ export class CommercetoolsProductProvider<
55
61
  })
56
62
  .execute();
57
63
 
58
- if (remote.body.results.length === 0) {
59
- throw new Error(`Product with slug '${payload.slug}' not found`);
64
+ if (remote.body.count === 0) {
65
+ return null;
60
66
  }
61
-
62
- return this.parseSingle(remote.body.results[0], session);
67
+ return this.parseSingle(remote.body.results[0], reqCtx);
63
68
  }
64
69
 
65
- protected override parseSingle(dataIn: unknown, session: Session): T {
70
+ protected override parseSingle(dataIn: unknown, reqCtx: RequestContext): T {
66
71
  const data = dataIn as ProductProjection;
67
72
  const base = this.newModel();
68
73
 
74
+
69
75
  base.identifier = { key: data.id };
70
- base.name = data.name[session.languageContext.locale];
71
- base.slug = data.slug[session.languageContext.locale];
76
+ base.name = data.name[reqCtx.languageContext.locale];
77
+ base.slug = data.slug[reqCtx.languageContext.locale];
72
78
 
73
79
  if (data.description) {
74
- base.description = data.description[session.languageContext.locale];
80
+ base.description = data.description[reqCtx.languageContext.locale];
75
81
  }
76
82
 
77
83
  if (data.masterVariant.images && data.masterVariant.images.length > 0) {
@@ -92,7 +98,7 @@ export class CommercetoolsProductProvider<
92
98
  }
93
99
 
94
100
  base.meta = {
95
- cache: { hit: false, key: this.generateCacheKeySingle(base.identifier, session) },
101
+ cache: { hit: false, key: this.generateCacheKeySingle(base.identifier, reqCtx) },
96
102
  placeholder: false
97
103
  };
98
104
 
@@ -0,0 +1,61 @@
1
+ import type {
2
+ Profile,
3
+ ProfileMutationUpdate,
4
+ ProfileQuerySelf,
5
+ RequestContext,
6
+ } from '@reactionary/core';
7
+ import { ProfileProvider } from '@reactionary/core';
8
+ import type z from 'zod';
9
+ import { CommercetoolsClient } from '../core/client';
10
+ import type { CommercetoolsConfiguration } from '../schema/configuration.schema';
11
+ import type { Cache } from '@reactionary/core';
12
+ import type { Customer } from '@commercetools/platform-sdk';
13
+
14
+ export class CommercetoolsProfileProvider<
15
+ T extends Profile = Profile
16
+ > extends ProfileProvider<T> {
17
+ protected config: CommercetoolsConfiguration;
18
+
19
+ constructor(
20
+ config: CommercetoolsConfiguration,
21
+ schema: z.ZodType<T>,
22
+ cache: Cache
23
+ ) {
24
+ super(schema, cache);
25
+
26
+ this.config = config;
27
+ }
28
+
29
+ protected async getClient(reqCtx: RequestContext) {
30
+ const client = await new CommercetoolsClient(this.config).getClient(reqCtx);
31
+ return client.withProjectKey({ projectKey: this.config.projectKey });
32
+ }
33
+
34
+ public override async getSelf(
35
+ payload: ProfileQuerySelf,
36
+ reqCtx: RequestContext
37
+ ): Promise<T> {
38
+ const client = await this.getClient(reqCtx);
39
+
40
+ const remote = await client.me().get().execute();
41
+ const model = this.parseSingle(remote.body, reqCtx);
42
+
43
+ return model;
44
+ }
45
+
46
+ public override async update(
47
+ payload: ProfileMutationUpdate,
48
+ reqCtx: RequestContext
49
+ ): Promise<T> {
50
+ throw new Error('Method not implemented.');
51
+ }
52
+
53
+ protected override parseSingle(body: Customer, reqCtx: RequestContext): T {
54
+ const model = this.newModel();
55
+
56
+ model.email = body.email;
57
+ model.emailVerified = body.isEmailVerified;
58
+
59
+ return model;
60
+ }
61
+ }
@@ -4,12 +4,12 @@ import type {
4
4
  SearchResultProduct,
5
5
  Cache,
6
6
  SearchQueryByTerm,
7
- Session,
7
+ Session, RequestContext,
8
8
  } from '@reactionary/core';
9
9
 
10
10
  import { CommercetoolsClient } from '../core/client';
11
- import z from 'zod';
12
- import { CommercetoolsConfiguration } from '../schema/configuration.schema';
11
+ import type z from 'zod';
12
+ import type { CommercetoolsConfiguration } from '../schema/configuration.schema';
13
13
  import { traced } from '@reactionary/otel';
14
14
 
15
15
  export class CommercetoolsSearchProvider<
@@ -28,32 +28,36 @@ export class CommercetoolsSearchProvider<
28
28
  }
29
29
 
30
30
  @traced()
31
+ protected async getClient(reqCtx: RequestContext) {
32
+ const client = await new CommercetoolsClient(this.config).getClient(reqCtx);
33
+ return client.withProjectKey({ projectKey: this.config.projectKey }).productProjections();
34
+ }
35
+
36
+
31
37
  public override async queryByTerm(
32
38
  payload: SearchQueryByTerm,
33
- session: Session
39
+ reqCtx: RequestContext
34
40
  ): Promise<T> {
35
- const client = new CommercetoolsClient(this.config).createAnonymousClient();
41
+ const client = await this.getClient(reqCtx);
36
42
 
37
43
  const remote = await client
38
- .withProjectKey({ projectKey: this.config.projectKey })
39
- .productProjections()
40
44
  .search()
41
45
  .get({
42
46
  queryArgs: {
43
47
  limit: payload.search.pageSize,
44
48
  offset: (payload.search.page - 1) * payload.search.pageSize,
45
- [`text.${session.languageContext.locale}`]: payload.search.term,
49
+ [`text.${reqCtx.languageContext.locale}`]: payload.search.term,
46
50
  },
47
51
  })
48
52
  .execute();
49
53
 
50
- return this.parseSearchResult(remote, payload, session);
54
+ return this.parseSearchResult(remote, payload, reqCtx);
51
55
  }
52
56
 
53
57
  protected parseSearchResult(
54
58
  remote: unknown,
55
59
  payload: SearchQueryByTerm,
56
- session: Session
60
+ reqCtx: RequestContext
57
61
  ): T {
58
62
  const result = this.newModel();
59
63
  const remoteData = remote as {
@@ -73,8 +77,8 @@ export class CommercetoolsSearchProvider<
73
77
  for (const p of remoteData.body.results) {
74
78
  const product: SearchResultProduct = {
75
79
  identifier: { key: p.id },
76
- name: p.name[session.languageContext.locale] || p.id,
77
- slug: p.slug?.[session.languageContext.locale] || p.id,
80
+ name: p.name[reqCtx.languageContext.locale] || p.id,
81
+ slug: p.slug?.[reqCtx.languageContext.locale] || p.id,
78
82
  image: p.masterVariant.images?.[0]?.url || 'https://placehold.co/400',
79
83
  };
80
84
 
@@ -0,0 +1,78 @@
1
+ import type {
2
+ RequestContext,
3
+ Cache,
4
+ StoreQueryByProximity,
5
+ } from '@reactionary/core';
6
+ import { StoreProvider } from '@reactionary/core';
7
+ import type z from 'zod';
8
+ import type { CommercetoolsConfiguration } from '../schema/configuration.schema';
9
+ import { CommercetoolsClient } from '../core/client';
10
+ import type { Channel, InventoryEntry } from '@commercetools/platform-sdk';
11
+ import type { Store } from '@reactionary/core';
12
+
13
+ export class CommercetoolsStoreProvider<
14
+ T extends Store = Store
15
+ > extends StoreProvider<T> {
16
+ protected config: CommercetoolsConfiguration;
17
+
18
+ constructor(
19
+ config: CommercetoolsConfiguration,
20
+ schema: z.ZodType<T>,
21
+ cache: Cache
22
+ ) {
23
+ super(schema, cache);
24
+
25
+ this.config = config;
26
+ }
27
+
28
+ protected async getClient(reqCtx: RequestContext) {
29
+ const client = await new CommercetoolsClient(this.config).getClient(reqCtx);
30
+ return client
31
+ .withProjectKey({ projectKey: this.config.projectKey });
32
+ }
33
+
34
+ public override async queryByProximity(
35
+ payload: StoreQueryByProximity,
36
+ reqCtx: RequestContext
37
+ ): Promise<Array<T>> {
38
+ const client = await this.getClient(reqCtx);
39
+
40
+ const remote = await client
41
+ .channels()
42
+ .get({
43
+ queryArgs: {
44
+ limit: payload.limit,
45
+ where: `geoLocation within circle(${ payload.longitude }, ${ payload.latitude }, ${payload.distance * 1000}) AND roles contains any ("InventorySupply")`
46
+ }
47
+ }).execute();
48
+
49
+ const results = [];
50
+
51
+ for (const r of remote.body.results) {
52
+ results.push(this.parseSingle(r, reqCtx));
53
+ }
54
+
55
+ return results;
56
+ }
57
+
58
+ protected override parseSingle(
59
+ body: Channel,
60
+ reqCtx: RequestContext
61
+ ): T {
62
+ const model = this.newModel();
63
+
64
+ if (body.name && body.name['la']) {
65
+ model.name = body.name['la'];
66
+ }
67
+
68
+ model.identifier = {
69
+ key: body.key
70
+ };
71
+
72
+ model.fulfillmentCenter = {
73
+ key: body.key
74
+ };
75
+
76
+ return model;
77
+ }
78
+ }
@@ -1,14 +1,16 @@
1
1
  import { CapabilitiesSchema } from "@reactionary/core";
2
- import { z } from 'zod';
2
+ import type { z } from 'zod';
3
3
 
4
4
  export const CommercetoolsCapabilitiesSchema = CapabilitiesSchema.pick({
5
5
  product: true,
6
6
  search: true,
7
7
  identity: true,
8
8
  cart: true,
9
+ cartPayment: true,
9
10
  inventory: true,
10
11
  price: true,
11
12
  category: true,
13
+ store: true,
12
14
  }).partial();
13
15
 
14
16
  export type CommercetoolsCapabilities = z.infer<typeof CommercetoolsCapabilitiesSchema>;
@@ -0,0 +1,18 @@
1
+ import { CartIdentifierSchema, OrderIdentifierSchema, PaymentInstructionIdentifierSchema } from "@reactionary/core";
2
+ import z from "zod";
3
+
4
+ export const CommercetoolsCartIdentifierSchema = CartIdentifierSchema.extend({
5
+ version: z.number().default(0)
6
+ });
7
+
8
+ export const CommercetoolsCartPaymentInstructionIdentifierSchema = PaymentInstructionIdentifierSchema.extend({
9
+ version: z.number().default(0),
10
+ });
11
+
12
+ export const CommercetoolsOrderIdentifierSchema = OrderIdentifierSchema.extend({
13
+ version: z.number().default(0)
14
+ });
15
+
16
+ export type CommercetoolsCartIdentifier = z.infer<typeof CommercetoolsCartIdentifierSchema>;
17
+ export type CommercetoolsCartPaymentInstructionIdentifier = z.infer<typeof CommercetoolsCartPaymentInstructionIdentifierSchema>;
18
+ export type CommercetoolsOrderIdentifier = z.infer<typeof CommercetoolsOrderIdentifierSchema>;
@@ -5,7 +5,8 @@ export const CommercetoolsConfigurationSchema = z.looseObject({
5
5
  authUrl: z.string(),
6
6
  apiUrl: z.string(),
7
7
  clientId: z.string(),
8
- clientSecret: z.string()
8
+ clientSecret: z.string(),
9
+ scopes: z.array(z.string()).default(() => []),
9
10
  });
10
11
 
11
12
  export type CommercetoolsConfiguration = z.infer<typeof CommercetoolsConfigurationSchema>;
@@ -0,0 +1,145 @@
1
+ import 'dotenv/config';
2
+ import type {
3
+ Cart, RequestContext} from '@reactionary/core';
4
+ import { CartPaymentInstructionSchema,
5
+ CartSchema,
6
+ IdentitySchema,
7
+ NoOpCache, createInitialRequestContext
8
+ } from '@reactionary/core';
9
+ import {
10
+ getCommercetoolsTestConfiguration,
11
+ } from './test-utils';
12
+ import { CommercetoolsCartProvider } from '../providers/cart.provider';
13
+ import { CommercetoolsIdentityProvider } from '../providers/identity.provider';
14
+ import { CommercetoolsCartPaymentProvider } from '../providers/cart-payment.provider';
15
+
16
+ const testData = {
17
+ skuWithoutTiers: 'SGB-01',
18
+ skuWithTiers: 'GMCT-01',
19
+ };
20
+
21
+ describe('Commercetools Cart Payment Provider', () => {
22
+ let provider: CommercetoolsCartPaymentProvider;
23
+ let cartProvider: CommercetoolsCartProvider;
24
+ let identityProvider: CommercetoolsIdentityProvider;
25
+ let reqCtx: RequestContext;
26
+
27
+ beforeAll(() => {
28
+ provider = new CommercetoolsCartPaymentProvider(
29
+ getCommercetoolsTestConfiguration(),
30
+ CartPaymentInstructionSchema,
31
+ new NoOpCache()
32
+ );
33
+ cartProvider = new CommercetoolsCartProvider(
34
+ getCommercetoolsTestConfiguration(),
35
+ CartSchema,
36
+ new NoOpCache()
37
+ );
38
+ identityProvider = new CommercetoolsIdentityProvider(
39
+ getCommercetoolsTestConfiguration(),
40
+ IdentitySchema,
41
+ new NoOpCache()
42
+ );
43
+ });
44
+
45
+ beforeEach(() => {
46
+ reqCtx = createInitialRequestContext();
47
+ });
48
+
49
+ describe('anonymous sessions', () => {
50
+ let cart: Cart;
51
+
52
+ beforeEach(async () => {
53
+ cart = await cartProvider.add(
54
+ {
55
+ cart: { key: '', version: 0 },
56
+ sku: {
57
+ key: testData.skuWithoutTiers,
58
+ },
59
+ quantity: 1,
60
+ },
61
+ reqCtx
62
+ );
63
+ });
64
+
65
+ it('a new cart will return 0 payment instructions', async () => {
66
+ const payments = await provider.getByCartIdentifier(
67
+ { cart: cart.identifier, status: undefined },
68
+ reqCtx
69
+ );
70
+ expect(payments.length).toBe(0);
71
+ });
72
+
73
+ it('can initiate a new payment', async () => {
74
+ const payment = await provider.initiatePaymentForCart(
75
+ {
76
+ cart: cart.identifier,
77
+ paymentInstruction: {
78
+ paymentMethod: {
79
+ method: 'stripe',
80
+ name: 'Stripe',
81
+ paymentProcessor: 'stripe',
82
+ },
83
+ amount: {
84
+ value: cart.price.grandTotal.value,
85
+ currency: cart.price.grandTotal.currency,
86
+ },
87
+ protocolData: [{ key: 'test-key', value: 'test-value' }],
88
+ },
89
+ },
90
+ reqCtx
91
+ );
92
+
93
+ expect(payment.identifier.key).toBeDefined();
94
+
95
+ // verify that we can fetch it again.
96
+ const payments = await provider.getByCartIdentifier(
97
+ { cart: cart.identifier, status: undefined },
98
+ reqCtx
99
+ );
100
+ expect(payments.length).toBe(1);
101
+ expect(payments[0].identifier.key).toBe(payment.identifier.key);
102
+ });
103
+
104
+
105
+ it('can cancel an in-progress payment', async () => {
106
+ const payment = await provider.initiatePaymentForCart(
107
+ {
108
+ cart: cart.identifier,
109
+ paymentInstruction: {
110
+ paymentMethod: {
111
+ method: 'stripe',
112
+ name: 'Stripe',
113
+ paymentProcessor: 'stripe',
114
+ },
115
+ amount: {
116
+ value: cart.price.grandTotal.value,
117
+ currency: cart.price.grandTotal.currency,
118
+ },
119
+ protocolData: [{ key: 'test-key', value: 'test-value' }],
120
+ },
121
+ },
122
+ reqCtx
123
+ );
124
+ expect(payment.identifier.key).toBeDefined();
125
+
126
+ const cancelledPayment = await provider.cancelPaymentInstruction(
127
+ {
128
+ cart: cart.identifier,
129
+ paymentInstruction: payment.identifier
130
+ },
131
+ reqCtx
132
+ );
133
+ expect(cancelledPayment.status).toBe('canceled');
134
+
135
+
136
+ // verify that it is gone
137
+ const payments = await provider.getByCartIdentifier(
138
+ { cart: cart.identifier, status: undefined },
139
+ reqCtx
140
+ );
141
+ expect(payments.length).toBe(0);
142
+ expect(payments[0].identifier.key).toBe(payment.identifier.key);
143
+ });
144
+ });
145
+ });