@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.
- package/.claude/settings.local.json +28 -0
- package/.env-template +8 -5
- package/.vscode/settings.json +5 -0
- package/README.md +41 -0
- package/core/package.json +3 -1
- package/core/src/cache/cache.interface.ts +14 -18
- package/core/src/cache/memory-cache.ts +56 -0
- package/core/src/cache/noop-cache.ts +5 -23
- package/core/src/cache/redis-cache.ts +28 -38
- package/core/src/client/client-builder.ts +3 -3
- package/core/src/client/client.ts +11 -9
- package/core/src/decorators/reactionary.decorator.ts +80 -8
- package/core/src/index.ts +5 -29
- package/core/src/initialization.ts +43 -0
- package/core/src/providers/analytics.provider.ts +1 -1
- package/core/src/providers/base.provider.ts +61 -25
- package/core/src/providers/cart-payment.provider.ts +57 -0
- package/core/src/providers/cart.provider.ts +131 -8
- package/core/src/providers/category.provider.ts +9 -9
- package/core/src/providers/identity.provider.ts +8 -7
- package/core/src/providers/index.ts +12 -0
- package/core/src/providers/inventory.provider.ts +4 -4
- package/core/src/providers/price.provider.ts +7 -7
- package/core/src/providers/product.provider.ts +17 -5
- package/core/src/providers/profile.provider.ts +22 -0
- package/core/src/providers/search.provider.ts +4 -4
- package/core/src/providers/store.provider.ts +14 -0
- package/core/src/schemas/capabilities.schema.ts +3 -1
- package/core/src/schemas/models/analytics.model.ts +1 -1
- package/core/src/schemas/models/cart.model.ts +16 -3
- package/core/src/schemas/models/identifiers.model.ts +90 -22
- package/core/src/schemas/models/identity.model.ts +23 -7
- package/core/src/schemas/models/index.ts +15 -0
- package/core/src/schemas/models/payment.model.ts +41 -0
- package/core/src/schemas/models/profile.model.ts +35 -0
- package/core/src/schemas/models/shipping-method.model.ts +14 -0
- package/core/src/schemas/models/store.model.ts +11 -0
- package/core/src/schemas/mutations/cart-payment.mutation.ts +21 -0
- package/core/src/schemas/mutations/cart.mutation.ts +62 -3
- package/core/src/schemas/mutations/identity.mutation.ts +8 -1
- package/core/src/schemas/mutations/index.ts +10 -0
- package/core/src/schemas/mutations/profile.mutation.ts +9 -0
- package/core/src/schemas/queries/cart-payment.query.ts +12 -0
- package/core/src/schemas/queries/cart.query.ts +1 -1
- package/core/src/schemas/queries/identity.query.ts +1 -1
- package/core/src/schemas/queries/index.ts +3 -0
- package/core/src/schemas/queries/inventory.query.ts +4 -12
- package/core/src/schemas/queries/price.query.ts +1 -1
- package/core/src/schemas/queries/profile.query.ts +7 -0
- package/core/src/schemas/queries/search.query.ts +1 -1
- package/core/src/schemas/queries/store.query.ts +11 -0
- package/core/src/schemas/session.schema.ts +31 -6
- package/eslint.config.mjs +7 -0
- package/examples/next/src/app/page.tsx +4 -12
- package/examples/node/package.json +1 -3
- package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +9 -8
- package/examples/node/src/basic/basic-node-provider-query-extension.spec.ts +4 -3
- package/examples/node/src/basic/basic-node-setup.spec.ts +4 -5
- package/nx.json +1 -0
- package/otel/src/metrics.ts +2 -1
- package/otel/src/provider-instrumentation.ts +2 -1
- package/otel/src/tracer.ts +7 -6
- package/otel/src/trpc-middleware.ts +3 -2
- package/package.json +2 -1
- package/providers/algolia/src/core/initialize.ts +4 -3
- package/providers/algolia/src/providers/product.provider.ts +15 -13
- package/providers/algolia/src/providers/search.provider.ts +9 -9
- package/providers/algolia/src/schema/capabilities.schema.ts +1 -1
- package/providers/algolia/src/test/search.provider.spec.ts +10 -10
- package/providers/algolia/src/test/test-utils.ts +9 -4
- package/providers/commercetools/README.md +27 -0
- package/providers/commercetools/src/core/client.ts +164 -117
- package/providers/commercetools/src/core/initialize.ts +24 -14
- package/providers/commercetools/src/providers/cart-payment.provider.ts +193 -0
- package/providers/commercetools/src/providers/cart.provider.ts +402 -125
- package/providers/commercetools/src/providers/category.provider.ts +35 -35
- package/providers/commercetools/src/providers/identity.provider.ts +23 -75
- package/providers/commercetools/src/providers/index.ts +2 -0
- package/providers/commercetools/src/providers/inventory.provider.ts +69 -40
- package/providers/commercetools/src/providers/price.provider.ts +79 -47
- package/providers/commercetools/src/providers/product.provider.ts +36 -30
- package/providers/commercetools/src/providers/profile.provider.ts +61 -0
- package/providers/commercetools/src/providers/search.provider.ts +16 -12
- package/providers/commercetools/src/providers/store.provider.ts +78 -0
- package/providers/commercetools/src/schema/capabilities.schema.ts +3 -1
- package/providers/commercetools/src/schema/commercetools.schema.ts +18 -0
- package/providers/commercetools/src/schema/configuration.schema.ts +2 -1
- package/providers/commercetools/src/test/cart-payment.provider.spec.ts +145 -0
- package/providers/commercetools/src/test/cart.provider.spec.ts +82 -22
- package/providers/commercetools/src/test/category.provider.spec.ts +18 -17
- package/providers/commercetools/src/test/identity.provider.spec.ts +88 -0
- package/providers/commercetools/src/test/inventory.provider.spec.ts +41 -0
- package/providers/commercetools/src/test/price.provider.spec.ts +9 -8
- package/providers/commercetools/src/test/product.provider.spec.ts +33 -5
- package/providers/commercetools/src/test/profile.provider.spec.ts +49 -0
- package/providers/commercetools/src/test/search.provider.spec.ts +8 -7
- package/providers/commercetools/src/test/store.provider.spec.ts +37 -0
- package/providers/commercetools/src/test/test-utils.ts +7 -31
- package/providers/fake/src/core/initialize.ts +96 -38
- package/providers/fake/src/providers/analytics.provider.ts +6 -5
- package/providers/fake/src/providers/cart.provider.ts +66 -19
- package/providers/fake/src/providers/category.provider.ts +12 -12
- package/providers/fake/src/providers/identity.provider.ts +22 -14
- package/providers/fake/src/providers/index.ts +1 -0
- package/providers/fake/src/providers/inventory.provider.ts +13 -13
- package/providers/fake/src/providers/price.provider.ts +13 -13
- package/providers/fake/src/providers/product.provider.ts +13 -10
- package/providers/fake/src/providers/search.provider.ts +7 -5
- package/providers/fake/src/providers/store.provider.ts +47 -0
- package/providers/fake/src/schema/capabilities.schema.ts +4 -1
- package/providers/fake/src/test/cart.provider.spec.ts +18 -18
- package/providers/fake/src/test/category.provider.spec.ts +55 -37
- package/providers/fake/src/test/price.provider.spec.ts +9 -14
- package/providers/fake/src/test/product.provider.spec.ts +27 -0
- package/providers/fake/src/test/test-utils.ts +2 -28
- package/providers/posthog/src/core/initialize.ts +3 -3
- package/providers/posthog/src/schema/capabilities.schema.ts +1 -1
- package/trpc/src/client.ts +42 -41
- package/trpc/src/index.ts +4 -3
- package/trpc/src/integration.spec.ts +11 -11
- package/trpc/src/server.ts +26 -24
- package/trpc/src/test-utils.ts +9 -4
- package/trpc/src/types.ts +24 -22
- package/core/src/cache/cache-evaluation.interface.ts +0 -19
- package/examples/node/src/test-utils.ts +0 -26
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Product,
|
|
2
|
+
type Product,
|
|
3
|
+
type ProductQueryById,
|
|
4
|
+
type ProductQueryBySlug,
|
|
5
|
+
type RequestContext,
|
|
6
|
+
type Cache as ReactinaryCache,
|
|
3
7
|
ProductProvider,
|
|
4
|
-
|
|
5
|
-
ProductQueryBySlug,
|
|
6
|
-
Session,
|
|
7
|
-
Cache as ReactinaryCache,
|
|
8
|
+
Reactionary,
|
|
8
9
|
} from '@reactionary/core';
|
|
9
|
-
import z from 'zod';
|
|
10
|
-
import { FakeConfiguration } from '../schema/configuration.schema';
|
|
10
|
+
import type z from 'zod';
|
|
11
|
+
import type { FakeConfiguration } from '../schema/configuration.schema';
|
|
11
12
|
import { base, en, Faker } from '@faker-js/faker';
|
|
12
|
-
import { traced } from '@reactionary/otel';
|
|
13
13
|
|
|
14
14
|
export class FakeProductProvider<
|
|
15
15
|
T extends Product = Product
|
|
@@ -22,16 +22,19 @@ export class FakeProductProvider<
|
|
|
22
22
|
this.config = config;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
@Reactionary({})
|
|
25
26
|
public override async getById(
|
|
26
27
|
payload: ProductQueryById,
|
|
27
|
-
|
|
28
|
+
_reqCtx: RequestContext
|
|
28
29
|
): Promise<T> {
|
|
29
30
|
return this.parseSingle(payload);
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
// FIXME: Should we have a get-by-sku here? Since thats whats coming back on cart items...
|
|
34
|
+
|
|
32
35
|
public override async getBySlug(
|
|
33
36
|
payload: ProductQueryBySlug,
|
|
34
|
-
|
|
37
|
+
_reqCtx: RequestContext
|
|
35
38
|
): Promise<T> {
|
|
36
39
|
return this.parseSingle(payload);
|
|
37
40
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
SearchProvider
|
|
2
|
+
SearchProvider
|
|
3
|
+
} from '@reactionary/core';
|
|
4
|
+
import type {
|
|
3
5
|
SearchResult,
|
|
4
6
|
SearchResultFacet,
|
|
5
7
|
SearchResultProduct,
|
|
6
8
|
Cache as ReactionaryCache,
|
|
7
9
|
} from '@reactionary/core';
|
|
8
|
-
import type {
|
|
9
|
-
import z from 'zod';
|
|
10
|
-
import { FakeConfiguration } from '../schema/configuration.schema';
|
|
10
|
+
import type { RequestContext, SearchQueryByTerm } from '@reactionary/core';
|
|
11
|
+
import type z from 'zod';
|
|
12
|
+
import type { FakeConfiguration } from '../schema/configuration.schema';
|
|
11
13
|
import { Faker, en, base } from '@faker-js/faker';
|
|
12
14
|
import { jitter } from '../utilities/jitter';
|
|
13
15
|
import { traced } from '@reactionary/otel';
|
|
@@ -26,7 +28,7 @@ export class FakeSearchProvider<
|
|
|
26
28
|
@traced()
|
|
27
29
|
public override async queryByTerm(
|
|
28
30
|
payload: SearchQueryByTerm,
|
|
29
|
-
|
|
31
|
+
_reqCtx: RequestContext
|
|
30
32
|
): Promise<SearchResult> {
|
|
31
33
|
await jitter(this.config.jitter.mean, this.config.jitter.deviation);
|
|
32
34
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Inventory,
|
|
3
|
+
Cache,
|
|
4
|
+
RequestContext,
|
|
5
|
+
StoreQueryByProximity,
|
|
6
|
+
Store,
|
|
7
|
+
} from '@reactionary/core';
|
|
8
|
+
import { InventoryProvider, StoreProvider } from '@reactionary/core';
|
|
9
|
+
import type z from 'zod';
|
|
10
|
+
import type { FakeConfiguration } from '../schema/configuration.schema';
|
|
11
|
+
import { base, en, Faker } from '@faker-js/faker';
|
|
12
|
+
|
|
13
|
+
export class FakeStoreProvider<
|
|
14
|
+
T extends Store = Store
|
|
15
|
+
> extends StoreProvider<T> {
|
|
16
|
+
protected config: FakeConfiguration;
|
|
17
|
+
|
|
18
|
+
constructor(config: FakeConfiguration, schema: z.ZodType<T>, cache: Cache) {
|
|
19
|
+
super(schema, cache);
|
|
20
|
+
|
|
21
|
+
this.config = config;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public override async queryByProximity(
|
|
25
|
+
payload: StoreQueryByProximity,
|
|
26
|
+
reqCtx: RequestContext
|
|
27
|
+
): Promise<T[]> {
|
|
28
|
+
const generator = new Faker({
|
|
29
|
+
seed: 42,
|
|
30
|
+
locale: [en, base],
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const results = [];
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < payload.limit; i++) {
|
|
36
|
+
const model = this.newModel();
|
|
37
|
+
|
|
38
|
+
model.name = generator.company.name();
|
|
39
|
+
model.identifier.key = '' + i;
|
|
40
|
+
model.fulfillmentCenter.key = '' + i;
|
|
41
|
+
|
|
42
|
+
results.push(model);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CapabilitiesSchema } from "@reactionary/core";
|
|
2
|
-
import { z } from 'zod';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
export const FakeCapabilitiesSchema = CapabilitiesSchema.pick({
|
|
5
5
|
product: true,
|
|
@@ -7,6 +7,9 @@ export const FakeCapabilitiesSchema = CapabilitiesSchema.pick({
|
|
|
7
7
|
identity: true,
|
|
8
8
|
category: true,
|
|
9
9
|
cart: true,
|
|
10
|
+
inventory: true,
|
|
11
|
+
store: true,
|
|
12
|
+
price: true,
|
|
10
13
|
}).partial();
|
|
11
14
|
|
|
12
15
|
export type FakeCapabilities = z.infer<typeof FakeCapabilitiesSchema>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import 'dotenv/config';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import type { RequestContext} from '@reactionary/core';
|
|
3
|
+
import { CartSchema, IdentitySchema, NoOpCache, createInitialRequestContext } from '@reactionary/core';
|
|
4
|
+
import { getFakerTestConfiguration } from './test-utils';
|
|
4
5
|
import { FakeCartProvider } from '../providers/cart.provider';
|
|
5
6
|
import { FakeIdentityProvider } from '../providers';
|
|
6
7
|
|
|
@@ -13,7 +14,7 @@ const testData = {
|
|
|
13
14
|
describe('Fake Cart Provider', () => {
|
|
14
15
|
let provider: FakeCartProvider;
|
|
15
16
|
let identityProvider: FakeIdentityProvider;
|
|
16
|
-
let
|
|
17
|
+
let reqCtx: RequestContext;
|
|
17
18
|
|
|
18
19
|
beforeAll( () => {
|
|
19
20
|
provider = new FakeCartProvider(getFakerTestConfiguration(), CartSchema, new NoOpCache());
|
|
@@ -21,14 +22,14 @@ describe('Fake Cart Provider', () => {
|
|
|
21
22
|
});
|
|
22
23
|
|
|
23
24
|
beforeEach( () => {
|
|
24
|
-
|
|
25
|
+
reqCtx = createInitialRequestContext()
|
|
25
26
|
});
|
|
26
27
|
|
|
27
28
|
describe('anonymous sessions', () => {
|
|
28
29
|
it('should be able to get an empty cart', async () => {
|
|
29
30
|
const cart = await provider.getById({
|
|
30
31
|
cart: { key: '' },
|
|
31
|
-
},
|
|
32
|
+
}, reqCtx);
|
|
32
33
|
|
|
33
34
|
expect(cart.identifier.key).toBeFalsy();
|
|
34
35
|
expect(cart.items.length).toBe(0);
|
|
@@ -39,22 +40,22 @@ describe('Fake Cart Provider', () => {
|
|
|
39
40
|
it('should be able to add an item to a cart', async () => {
|
|
40
41
|
const cart = await provider.add({
|
|
41
42
|
cart: { key: '' },
|
|
42
|
-
|
|
43
|
+
sku: {
|
|
43
44
|
key: testData.skuWithoutTiers,
|
|
44
45
|
},
|
|
45
46
|
quantity: 1
|
|
46
|
-
},
|
|
47
|
+
}, reqCtx);
|
|
47
48
|
|
|
48
49
|
expect(cart.identifier.key).toBeDefined();
|
|
49
50
|
expect(cart.items.length).toBe(1);
|
|
50
|
-
expect(cart.items[0].
|
|
51
|
+
expect(cart.items[0].sku.key).toBe(testData.skuWithoutTiers);
|
|
51
52
|
expect(cart.items[0].quantity).toBe(1);
|
|
52
53
|
|
|
53
54
|
expect(cart.items[0].price.totalPrice.value).toBeGreaterThan(0);
|
|
54
|
-
expect(cart.items[0].price.totalPrice.currency).toBe(
|
|
55
|
+
expect(cart.items[0].price.totalPrice.currency).toBe(reqCtx.languageContext.currencyCode);
|
|
55
56
|
|
|
56
57
|
expect(cart.price.grandTotal.value).toBeGreaterThan(0);
|
|
57
|
-
expect(cart.price.grandTotal.currency).toBe(
|
|
58
|
+
expect(cart.price.grandTotal.currency).toBe(reqCtx.languageContext.currencyCode);
|
|
58
59
|
|
|
59
60
|
expect(cart.price.grandTotal.value).toBe(cart.items[0].price.totalPrice.value);
|
|
60
61
|
|
|
@@ -68,23 +69,22 @@ describe('Fake Cart Provider', () => {
|
|
|
68
69
|
|
|
69
70
|
const cart = await provider.add({
|
|
70
71
|
cart: { key: '' },
|
|
71
|
-
|
|
72
|
+
sku: {
|
|
72
73
|
key: testData.skuWithoutTiers,
|
|
73
74
|
},
|
|
74
75
|
quantity: 1
|
|
75
|
-
},
|
|
76
|
+
}, reqCtx);
|
|
76
77
|
|
|
77
78
|
const updatedCart = await provider.changeQuantity({
|
|
78
79
|
cart: cart.identifier,
|
|
79
80
|
item: cart.items[0].identifier,
|
|
80
81
|
quantity: 3
|
|
81
|
-
},
|
|
82
|
+
}, reqCtx);
|
|
82
83
|
|
|
83
84
|
expect(updatedCart.identifier.key).toBe(cart.identifier.key);
|
|
84
85
|
expect(updatedCart.items.length).toBe(1);
|
|
85
|
-
expect(updatedCart.items[0].
|
|
86
|
+
expect(updatedCart.items[0].sku.key).toBe(testData.skuWithoutTiers);
|
|
86
87
|
expect(updatedCart.items[0].quantity).toBe(3);
|
|
87
|
-
|
|
88
88
|
expect(updatedCart.items[0].price.totalPrice.value).toBe(cart.items[0].price.totalPrice.value * 3);
|
|
89
89
|
expect(updatedCart.items[0].price.unitPrice.value).toBe(cart.items[0].price.unitPrice.value);
|
|
90
90
|
|
|
@@ -95,16 +95,16 @@ describe('Fake Cart Provider', () => {
|
|
|
95
95
|
|
|
96
96
|
const cart = await provider.add({
|
|
97
97
|
cart: { key: '' },
|
|
98
|
-
|
|
98
|
+
sku: {
|
|
99
99
|
key: testData.skuWithoutTiers,
|
|
100
100
|
},
|
|
101
101
|
quantity: 1
|
|
102
|
-
},
|
|
102
|
+
}, reqCtx);
|
|
103
103
|
|
|
104
104
|
const updatedCart = await provider.remove({
|
|
105
105
|
cart: cart.identifier,
|
|
106
106
|
item: cart.items[0].identifier,
|
|
107
|
-
},
|
|
107
|
+
}, reqCtx);
|
|
108
108
|
expect(updatedCart.identifier.key).toBe(cart.identifier.key);
|
|
109
109
|
expect(updatedCart.items.length).toBe(0);
|
|
110
110
|
});
|
|
@@ -1,25 +1,29 @@
|
|
|
1
|
-
import 'dotenv/config'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { CategorySchema, NoOpCache, Session } from '@reactionary/core';
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import type { RequestContext } from '@reactionary/core';
|
|
3
|
+
import { CategorySchema, MemoryCache , createInitialRequestContext,} from '@reactionary/core';
|
|
5
4
|
import { FakeCategoryProvider } from '../providers';
|
|
6
|
-
import {
|
|
5
|
+
import { getFakerTestConfiguration } from './test-utils';
|
|
6
|
+
|
|
7
7
|
describe('Faker Category Provider', () => {
|
|
8
8
|
let provider: FakeCategoryProvider;
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
let reqCtx: RequestContext;
|
|
10
|
+
const cache = new MemoryCache();
|
|
11
|
+
|
|
12
|
+
beforeAll(() => {
|
|
13
|
+
provider = new FakeCategoryProvider(
|
|
14
|
+
getFakerTestConfiguration(),
|
|
15
|
+
CategorySchema,
|
|
16
|
+
cache
|
|
17
|
+
);
|
|
15
18
|
});
|
|
16
19
|
|
|
17
20
|
beforeEach( () => {
|
|
18
|
-
|
|
21
|
+
reqCtx = createInitialRequestContext();
|
|
22
|
+
cache.clear();
|
|
19
23
|
})
|
|
20
24
|
|
|
21
25
|
it('should be able to get top-categories', async () => {
|
|
22
|
-
const result = await provider.findTopCategories({ paginationOptions: { pageSize: 10, pageNumber: 1 }},
|
|
26
|
+
const result = await provider.findTopCategories({ paginationOptions: { pageSize: 10, pageNumber: 1 }}, reqCtx);
|
|
23
27
|
|
|
24
28
|
expect(result.items.length).toBeGreaterThan(0);
|
|
25
29
|
expect(result.items[0].identifier.key).toBe('grocery');
|
|
@@ -30,7 +34,7 @@ describe('Faker Category Provider', () => {
|
|
|
30
34
|
});
|
|
31
35
|
|
|
32
36
|
it('should be able to get child categories for a category', async () => {
|
|
33
|
-
const result = await provider.findChildCategories({ parentId: { key: 'grocery' }, paginationOptions: { pageSize: 10, pageNumber: 1 }},
|
|
37
|
+
const result = await provider.findChildCategories({ parentId: { key: 'grocery' }, paginationOptions: { pageSize: 10, pageNumber: 1 }}, reqCtx);
|
|
34
38
|
|
|
35
39
|
expect(result.items.length).toBeGreaterThan(0);
|
|
36
40
|
expect(result.items[0].identifier.key).toBe('grocery-0');
|
|
@@ -38,12 +42,10 @@ describe('Faker Category Provider', () => {
|
|
|
38
42
|
|
|
39
43
|
expect(result.items[1].identifier.key).toBe('grocery-1');
|
|
40
44
|
expect(result.items[1].name).toBe('Grocery-1');
|
|
41
|
-
|
|
42
45
|
});
|
|
43
46
|
|
|
44
|
-
|
|
45
47
|
it('should be able to get child categories for a category, paged', async () => {
|
|
46
|
-
let result = await provider.findChildCategories({ parentId: { key: 'grocery' }, paginationOptions: { pageSize: 1, pageNumber: 1 }},
|
|
48
|
+
let result = await provider.findChildCategories({ parentId: { key: 'grocery' }, paginationOptions: { pageSize: 1, pageNumber: 1 }}, reqCtx);
|
|
47
49
|
|
|
48
50
|
expect(result.items.length).toBeGreaterThan(0);
|
|
49
51
|
expect(result.items[0].identifier.key).toBe('grocery-0');
|
|
@@ -53,7 +55,7 @@ describe('Faker Category Provider', () => {
|
|
|
53
55
|
expect(result.pageSize).toBe(1);
|
|
54
56
|
expect(result.pageNumber).toBe(1);
|
|
55
57
|
|
|
56
|
-
result = await provider.findChildCategories({ parentId: { key: 'grocery' }, paginationOptions: { pageSize: 1, pageNumber: 2 }},
|
|
58
|
+
result = await provider.findChildCategories({ parentId: { key: 'grocery' }, paginationOptions: { pageSize: 1, pageNumber: 2 }}, reqCtx);
|
|
57
59
|
|
|
58
60
|
expect(result.items.length).toBeGreaterThan(0);
|
|
59
61
|
expect(result.items[0].identifier.key).toBe('grocery-1');
|
|
@@ -64,9 +66,8 @@ describe('Faker Category Provider', () => {
|
|
|
64
66
|
expect(result.pageNumber).toBe(2);
|
|
65
67
|
});
|
|
66
68
|
|
|
67
|
-
|
|
68
69
|
it('can load all breadcrumbs for a category', async () => {
|
|
69
|
-
const result = await provider.getBreadcrumbPathToCategory({ id: { key: 'grocery-0-0' } },
|
|
70
|
+
const result = await provider.getBreadcrumbPathToCategory({ id: { key: 'grocery-0-0' } }, reqCtx);
|
|
70
71
|
|
|
71
72
|
expect(result.length).toBeGreaterThan(2);
|
|
72
73
|
expect(result[0].identifier.key).toBe('grocery');
|
|
@@ -80,53 +81,70 @@ describe('Faker Category Provider', () => {
|
|
|
80
81
|
expect(result[2].identifier.key).toBe('grocery-0-0');
|
|
81
82
|
expect(result[2].name).toBe('Grocery-0-0');
|
|
82
83
|
expect(result[2].slug).toBe('grocery-0-0-slug');
|
|
83
|
-
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
|
|
87
86
|
it('should be able to get a category by slug', async () => {
|
|
88
|
-
const result = await provider.getBySlug({ slug: 'grocery-slug' },
|
|
87
|
+
const result = await provider.getBySlug({ slug: 'grocery-slug' }, reqCtx);
|
|
89
88
|
expect(result).toBeTruthy();
|
|
90
89
|
if (result) {
|
|
91
90
|
expect(result.identifier.key).toBe('grocery');
|
|
92
91
|
expect(result.name).toBe('Grocery');
|
|
93
92
|
expect(result.slug).toBe('grocery-slug');
|
|
94
93
|
expect(result.parentCategory).toBeUndefined();
|
|
95
|
-
expect(result.text).not.toBe(
|
|
94
|
+
expect(result.text).not.toBe('');
|
|
96
95
|
expect(result.meta.placeholder).toBe(false);
|
|
97
96
|
}
|
|
98
97
|
});
|
|
99
98
|
|
|
100
99
|
it('returns null if looking for slug that does not exist', async () => {
|
|
101
|
-
const result = await provider.getBySlug({ slug: 'non-existent-slug' },
|
|
100
|
+
const result = await provider.getBySlug({ slug: 'non-existent-slug' }, reqCtx);
|
|
102
101
|
expect(result).toBeNull();
|
|
103
102
|
});
|
|
104
103
|
|
|
105
|
-
|
|
106
|
-
|
|
107
104
|
it('should be able to get a category by id', async () => {
|
|
108
|
-
const result = await provider.getById({ id: { key: 'grocery'}},
|
|
105
|
+
const result = await provider.getById({ id: { key: 'grocery'}}, reqCtx);
|
|
109
106
|
|
|
110
107
|
expect(result.identifier.key).toBe('grocery');
|
|
111
108
|
expect(result.name).toBe('Grocery');
|
|
112
109
|
expect(result.slug).toBe('grocery-slug');
|
|
113
110
|
expect(result.parentCategory).toBeUndefined();
|
|
114
111
|
|
|
115
|
-
expect(result.text).not.toBe(
|
|
112
|
+
expect(result.text).not.toBe('');
|
|
116
113
|
expect(result.meta.placeholder).toBe(false);
|
|
117
|
-
|
|
118
114
|
});
|
|
119
115
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
116
|
it('returns a placeholder if you search for a category that does not exist', async () => {
|
|
125
|
-
const result = await provider.getById({ id: { key: 'non-existent-category'}},
|
|
117
|
+
const result = await provider.getById({ id: { key: 'non-existent-category'}}, reqCtx);
|
|
126
118
|
expect(result.identifier.key).toBe('non-existent-category');
|
|
127
119
|
expect(result.meta.placeholder).toBe(true);
|
|
128
|
-
|
|
129
120
|
});
|
|
130
121
|
|
|
131
|
-
|
|
122
|
+
describe('caching', () => {
|
|
123
|
+
// TODO: These should probably be elsewhere, since they are really testing the caches and the decorator together.
|
|
124
|
+
// Perhaps as an integration test
|
|
125
|
+
|
|
126
|
+
it('should cache the results for byId', async () => {
|
|
127
|
+
const first = await provider.getById({ id: { key: 'grocery' } }, reqCtx);
|
|
128
|
+
expect(first.meta.cache.hit).toBe(false);
|
|
129
|
+
|
|
130
|
+
const second = await provider.getById(
|
|
131
|
+
{ id: { key: 'grocery' } },
|
|
132
|
+
reqCtx
|
|
133
|
+
);
|
|
134
|
+
expect(second.meta.cache.hit).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('can clear a cache entry by dependency id', async () => {
|
|
138
|
+
const first = await provider.getById({ id: { key: 'grocery' } }, reqCtx);
|
|
139
|
+
|
|
140
|
+
const dependencyIds = provider.generateDependencyIdsForModel(first);
|
|
141
|
+
await cache.invalidate(dependencyIds);
|
|
142
|
+
|
|
143
|
+
const second = await provider.getById(
|
|
144
|
+
{ id: { key: 'grocery' } },
|
|
145
|
+
reqCtx
|
|
146
|
+
);
|
|
147
|
+
expect(second.meta.cache.hit).toBe(false);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
132
150
|
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import 'dotenv/config';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import { createAnonymousTestSession, getFakerTestConfiguration } from './test-utils';
|
|
6
|
-
|
|
2
|
+
import type { RequestContext} from '@reactionary/core';
|
|
3
|
+
import { NoOpCache, PriceSchema, createInitialRequestContext } from '@reactionary/core';
|
|
4
|
+
import { getFakerTestConfiguration } from './test-utils';
|
|
7
5
|
import { FakePriceProvider } from '../providers/price.provider';
|
|
8
6
|
|
|
9
7
|
const testData = {
|
|
@@ -11,23 +9,20 @@ const testData = {
|
|
|
11
9
|
skuWithTiers: 'GMCT-01-with-tiers'
|
|
12
10
|
}
|
|
13
11
|
|
|
14
|
-
|
|
15
12
|
describe('Fake Price Provider', () => {
|
|
16
13
|
let provider: FakePriceProvider;
|
|
17
|
-
let
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
let reqCtx: RequestContext;
|
|
20
15
|
|
|
21
16
|
beforeAll( () => {
|
|
22
17
|
provider = new FakePriceProvider(getFakerTestConfiguration(), PriceSchema, new NoOpCache());
|
|
23
18
|
});
|
|
24
19
|
|
|
25
20
|
beforeEach( () => {
|
|
26
|
-
|
|
21
|
+
reqCtx = createInitialRequestContext()
|
|
27
22
|
})
|
|
28
23
|
|
|
29
24
|
it('should be able to get prices for a product without tiers', async () => {
|
|
30
|
-
const result = await provider.getBySKU({ sku: { key: testData.skuWithoutTiers }},
|
|
25
|
+
const result = await provider.getBySKU({ sku: { key: testData.skuWithoutTiers }}, reqCtx);
|
|
31
26
|
|
|
32
27
|
expect(result).toBeTruthy();
|
|
33
28
|
if (result) {
|
|
@@ -39,7 +34,7 @@ describe('Fake Price Provider', () => {
|
|
|
39
34
|
});
|
|
40
35
|
|
|
41
36
|
it('should be able to get prices for a product with tiers', async () => {
|
|
42
|
-
const result = await provider.getBySKU({ sku: { key: testData.skuWithTiers }},
|
|
37
|
+
const result = await provider.getBySKU({ sku: { key: testData.skuWithTiers }}, reqCtx);
|
|
43
38
|
|
|
44
39
|
expect(result).toBeTruthy();
|
|
45
40
|
if (result) {
|
|
@@ -56,7 +51,7 @@ describe('Fake Price Provider', () => {
|
|
|
56
51
|
});
|
|
57
52
|
|
|
58
53
|
it('should return a placeholder price for an unknown SKU', async () => {
|
|
59
|
-
const result = await provider.getBySKU({ sku: { key: 'unknown-sku' }},
|
|
54
|
+
const result = await provider.getBySKU({ sku: { key: 'unknown-sku' }}, reqCtx);
|
|
60
55
|
|
|
61
56
|
expect(result).toBeTruthy();
|
|
62
57
|
if (result) {
|
|
@@ -70,7 +65,7 @@ describe('Fake Price Provider', () => {
|
|
|
70
65
|
|
|
71
66
|
it('can look up multiple prices at once', async () => {
|
|
72
67
|
const skus = [testData.skuWithTiers, testData.skuWithoutTiers, 'unknown-sku'];
|
|
73
|
-
const results = await Promise.all(skus.map( sku => provider.getBySKU({ sku: { key: sku }},
|
|
68
|
+
const results = await Promise.all(skus.map( sku => provider.getBySKU({ sku: { key: sku }}, reqCtx)));
|
|
74
69
|
|
|
75
70
|
expect(results).toHaveLength(skus.length);
|
|
76
71
|
expect(results[0].identifier.sku.key).toBe(testData.skuWithTiers);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
|
|
3
|
+
import type { Session } from '@reactionary/core';
|
|
4
|
+
import { MemoryCache, ProductSchema } from '@reactionary/core';
|
|
5
|
+
import { createAnonymousTestSession, getFakerTestConfiguration } from './test-utils';
|
|
6
|
+
import { FakeProductProvider } from '../providers';
|
|
7
|
+
|
|
8
|
+
describe('Fake Product Provider', () => {
|
|
9
|
+
let provider: FakeProductProvider;
|
|
10
|
+
let session: Session;
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
provider = new FakeProductProvider(getFakerTestConfiguration(), ProductSchema, new MemoryCache());
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
beforeEach( () => {
|
|
17
|
+
session = createAnonymousTestSession()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should cache repeat product lookups by id', async () => {
|
|
21
|
+
const first = await provider.getById({ id: '1234' }, session);
|
|
22
|
+
expect(first.meta.cache.hit).toBe(false);
|
|
23
|
+
|
|
24
|
+
const second = await provider.getById({ id: '1234' }, session);
|
|
25
|
+
expect(second.meta.cache.hit).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FakeConfiguration } from "../schema/configuration.schema";
|
|
1
|
+
import type { FakeConfiguration } from '../schema/configuration.schema';
|
|
3
2
|
|
|
4
3
|
export function getFakerTestConfiguration(): FakeConfiguration {
|
|
5
4
|
return {
|
|
@@ -11,32 +10,7 @@ export function getFakerTestConfiguration(): FakeConfiguration {
|
|
|
11
10
|
product: 1,
|
|
12
11
|
search: 1,
|
|
13
12
|
category: 1,
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export function createAnonymousTestSession(): Session {
|
|
20
|
-
return {
|
|
21
|
-
id: 'test-session-id',
|
|
22
|
-
identity: {
|
|
23
|
-
type: 'Anonymous',
|
|
24
|
-
meta: {
|
|
25
|
-
cache: { hit: false, key: '' },
|
|
26
|
-
placeholder: false,
|
|
27
|
-
},
|
|
28
|
-
id: '',
|
|
29
|
-
token: undefined,
|
|
30
|
-
issued: new Date(),
|
|
31
|
-
expiry: new Date(new Date().getTime() + 3600 * 1000), // 1 hour from now
|
|
32
|
-
},
|
|
33
|
-
languageContext: {
|
|
34
|
-
locale: 'en-US',
|
|
35
|
-
currencyCode: 'USD',
|
|
36
|
-
countryCode: 'US',
|
|
37
|
-
},
|
|
38
|
-
storeIdentifier: {
|
|
39
|
-
key: 'the-good-store',
|
|
40
13
|
},
|
|
41
14
|
};
|
|
42
15
|
}
|
|
16
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Client, Cache } from "@reactionary/core";
|
|
2
|
-
import { PosthogConfiguration } from "../schema/configuration.schema";
|
|
3
|
-
import { PosthogCapabilities } from "../schema/capabilities.schema";
|
|
1
|
+
import type { Client, Cache } from "@reactionary/core";
|
|
2
|
+
import type { PosthogConfiguration } from "../schema/configuration.schema";
|
|
3
|
+
import type { PosthogCapabilities } from "../schema/capabilities.schema";
|
|
4
4
|
|
|
5
5
|
export function withPosthogCapabilities(_configuration: PosthogConfiguration, _capabilities: PosthogCapabilities) {
|
|
6
6
|
return (_cache: Cache) => {
|