Skip to content

Commit d9d7f8b

Browse files
authored
Merge pull request #21 from rigby-sh/cloud-changes
Cloud changes
2 parents c4e37db + 936a5fe commit d9d7f8b

11 files changed

Lines changed: 307 additions & 157 deletions

File tree

.env.example

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,13 @@ STRIPE_WEBHOOK_SECRET=YOUR_STRIPE_WEBHOOK_SECRET
2121

2222
# Resend
2323
RESEND_API_KEY=YOUR_RESEND_API_KEY
24-
RESEND_FROM_EMAIL=RESEND_FROM_EMAIL
24+
RESEND_FROM_EMAIL=RESEND_FROM_EMAIL
25+
26+
MEDUSA_FF_INDEX_ENGINE=true
27+
28+
# test env
29+
DB_HOST=localhost
30+
DB_PORT=5432
31+
DB_NAME=medusa
32+
DB_USER=medusa
33+
DB_PASSWORD=medusa

.env.test

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
DB_HOST=localhost
2+
DB_PORT=5432
3+
DB_NAME=medusa-test
4+
DB_USER=medusa
5+
DB_PASSWORD=medusa
6+
DATABASE_URL=postgresql://medusa:medusa@localhost:5432/medusa?sslmode=no-verify
7+
STORE_CORS=YOUR_STORE_CORS # for example: http://localhost:8000,http://localhost:3000,http://localhost:9000
8+
ADMIN_CORS=YOUR_ADMIN_CORS # for example: http://localhost:7000,http://localhost:7001,http://localhost:9000
9+
AUTH_CORS=YOUR_AUTH_CORS # for example: http://localhost:7000,http://localhost:7001,http://localhost:9000
10+
REDIS_URL=YOUR_REDIS_URL # for example: redis://localhost:6379
11+
JWT_SECRET=YOUR_JWT_SECRET # for example: supersecret
12+
COOKIE_SECRET=YOUR_COOKIE_SECRET # for example: supersecret
13+
DATABASE_URL=YOUR_DATABASE_URL # for dev env: postgresql://medusa:medusa@localhost:5432/medusa
14+
15+
# Space Storage
16+
DO_SPACE_URL=YOUR_DO_SPACE_URL
17+
DO_SPACE_ACCESS_KEY=YOUR_DO_SPACE_ACCESS_KEY
18+
DO_SPACE_SECRET_KEY=YOUR_DO_SPACE_SECRET_KEY
19+
DO_SPACE_ENDPOINT=YOUR_DO_SPACE_ENDPOINT
20+
DO_SPACE_BUCKET=YOUR_DO_SPACE_BUCKET
21+
DO_SPACE_CDN=YOUR_DO_SPACE_CDN
22+
DO_SPACE_REGION=YOUR_DO_SPACE_REGION
23+
24+
# Stripe
25+
STRIPE_API_KEY=YOUR_STRIPE_API_KEY
26+
STRIPE_WEBHOOK_SECRET=YOUR_STRIPE_WEBHOOK_SECRET
27+
28+
# Resend
29+
RESEND_API_KEY=YOUR_RESEND_API_KEY
30+
RESEND_FROM_EMAIL=RESEND_FROM_EMAIL
31+
32+
MEDUSA_FF_INDEX_ENGINE=true
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { medusaIntegrationTestRunner } from '@medusajs/test-utils';
2+
import { IProductModuleService, MedusaContainer } from '@medusajs/framework/types';
3+
import { Modules, ProductStatus } from '@medusajs/framework/utils';
4+
import { createProductsWorkflow } from '@medusajs/medusa/core-flows';
5+
6+
const SEARCH_PATH = '/store/search';
7+
8+
medusaIntegrationTestRunner({
9+
inApp: true,
10+
testSuite: ({ api, getContainer }) => {
11+
describe('Store Search Price Range Filter', () => {
12+
let container: MedusaContainer;
13+
14+
beforeAll(async () => {
15+
container = getContainer();
16+
});
17+
18+
beforeEach(async () => {
19+
const productModuleService = container.resolve<IProductModuleService>(Modules.PRODUCT);
20+
21+
// Czyścimy i tworzymy produkty testowe o różnych cenach
22+
await createProductsWorkflow(container).run({
23+
input: {
24+
products: [
25+
{
26+
title: 'Tani Produkt',
27+
status: ProductStatus.PUBLISHED,
28+
options: [{ title: 'Size', values: ['S'] }],
29+
variants: [
30+
{
31+
title: 'S',
32+
sku: 'CHEAP-1',
33+
prices: [{ currency_code: 'eur', amount: 100 }] // 1.00 EUR
34+
}
35+
]
36+
},
37+
{
38+
title: 'Średni Produkt',
39+
status: ProductStatus.PUBLISHED,
40+
options: [{ title: 'Size', values: ['M'] }],
41+
variants: [
42+
{
43+
title: 'M',
44+
sku: 'MEDIUM-1',
45+
prices: [{ currency_code: 'eur', amount: 500 }] // 5.00 EUR
46+
}
47+
]
48+
},
49+
{
50+
title: 'Drogi Produkt',
51+
status: ProductStatus.PUBLISHED,
52+
options: [{ title: 'Size', values: ['L'] }],
53+
variants: [
54+
{
55+
title: 'L',
56+
sku: 'EXPENSIVE-1',
57+
prices: [{ currency_code: 'eur', amount: 1000 }] // 10.00 EUR
58+
}
59+
]
60+
}
61+
]
62+
}
63+
});
64+
});
65+
66+
test('should return all products when no price filters are applied', async () => {
67+
const response = await api.get(SEARCH_PATH);
68+
expect(response.status).toEqual(200);
69+
expect(response.data.products.length).toBeGreaterThanOrEqual(3);
70+
});
71+
72+
test('should filter products by min_price', async () => {
73+
// Produkty droższe lub równe 500 (Średni i Drogi)
74+
const response = await api.get(`${SEARCH_PATH}?min_price=500`);
75+
76+
expect(response.status).toEqual(200);
77+
const titles = response.data.products.map((p) => p.title);
78+
expect(titles).toContain('Średni Produkt');
79+
expect(titles).toContain('Drogi Produkt');
80+
expect(titles).not.toContain('Tani Produkt');
81+
});
82+
83+
test('should filter products by max_price', async () => {
84+
// Produkty tańsze lub równe 500 (Tani i Średni)
85+
const response = await api.get(`${SEARCH_PATH}?max_price=500`);
86+
87+
expect(response.status).toEqual(200);
88+
const titles = response.data.products.map((p) => p.title);
89+
expect(titles).toContain('Tani Produkt');
90+
expect(titles).toContain('Średni Produkt');
91+
expect(titles).not.toContain('Drogi Produkt');
92+
});
93+
94+
test('should filter products by price range (min and max)', async () => {
95+
// Tylko Średni Produkt (cena 500)
96+
const response = await api.get(`${SEARCH_PATH}?min_price=400&max_price=600`);
97+
98+
expect(response.status).toEqual(200);
99+
expect(response.data.products.length).toEqual(1);
100+
expect(response.data.products[0].title).toEqual('Średni Produkt');
101+
});
102+
103+
test('should return empty list when no products match price range', async () => {
104+
const response = await api.get(`${SEARCH_PATH}?min_price=2000`);
105+
106+
expect(response.status).toEqual(200);
107+
expect(response.data.products.length).toEqual(0);
108+
});
109+
});
110+
}
111+
});
112+
113+
jest.setTimeout(120 * 1000);

jest.config.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,39 @@ loadEnv('test', process.cwd());
33

44
module.exports = {
55
transform: {
6-
'^.+\\.[jt]s$': [
6+
'^.+\\.(t|j)sx?$': [
77
'@swc/jest',
88
{
99
jsc: {
10-
parser: { syntax: 'typescript', decorators: true }
10+
parser: {
11+
syntax: 'typescript',
12+
decorators: true
13+
},
14+
target: 'es2022',
15+
transform: {
16+
hidden: {
17+
jest: true
18+
}
19+
}
20+
},
21+
module: {
22+
type: 'commonjs'
1123
}
1224
}
1325
]
1426
},
1527
testEnvironment: 'node',
1628
moduleFileExtensions: ['js', 'ts', 'json'],
17-
modulePathIgnorePatterns: ['dist/']
29+
modulePathIgnorePatterns: ['dist/', '<rootDir>/.medusa/'],
30+
moduleNameMapper: {
31+
'^@/(.*)$': '<rootDir>/src/$1'
32+
}
1833
};
1934

2035
if (process.env.TEST_TYPE === 'integration:http') {
2136
module.exports.testMatch = ['**/integration-tests/http/*.spec.[jt]s'];
37+
} else if (process.env.TEST_TYPE === 'integration:new') {
38+
module.exports.testMatch = ['**/integration-tests/new/*.integration.spec.[jt]s'];
2239
} else if (process.env.TEST_TYPE === 'integration:modules') {
2340
module.exports.testMatch = ['**/src/modules/*/__tests__/**/*.[jt]s'];
2441
} else if (process.env.TEST_TYPE === 'unit') {

medusa-config.ts

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,28 @@ const stripeWebhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
99

1010
const isStripeConfigured = Boolean(stripeApiKey) && Boolean(stripeWebhookSecret);
1111

12-
// if (isStripeConfigured) {
13-
// console.log('Stripe API key and webhook secret found. Enabling payment module');
14-
// dynamicModules[Modules.PAYMENT] = {
15-
// resolve: '@medusajs/medusa/payment',
16-
// options: {
17-
// providers: [
18-
// {
19-
// resolve: '@medusajs/medusa/payment-stripe',
20-
// id: 'stripe',
21-
// options: {
22-
// apiKey: stripeApiKey,
23-
// webhookSecret: stripeWebhookSecret
24-
// }
25-
// }
26-
// ]
27-
// }
28-
// };
29-
// }
12+
if (isStripeConfigured) {
13+
console.log('Stripe API key and webhook secret found. Enabling payment module');
14+
dynamicModules[Modules.PAYMENT] = {
15+
resolve: '@medusajs/medusa/payment',
16+
options: {
17+
providers: [
18+
{
19+
resolve: '@medusajs/medusa/payment-stripe',
20+
id: 'stripe',
21+
options: {
22+
apiKey: stripeApiKey,
23+
webhookSecret: stripeWebhookSecret
24+
}
25+
}
26+
]
27+
}
28+
};
29+
}
30+
3031

3132
const modules = {
33+
3234
[Modules.FILE]: {
3335
resolve: '@medusajs/medusa/file',
3436
options: {
@@ -63,7 +65,10 @@ const modules = {
6365
},
6466
],
6567
},
66-
}
68+
},
69+
[Modules.INDEX]: {
70+
resolve: "@medusajs/index",
71+
},
6772
};
6873

6974
module.exports = defineConfig({
@@ -79,7 +84,7 @@ module.exports = defineConfig({
7984
authCors: process.env.AUTH_CORS,
8085
jwtSecret: process.env.JWT_SECRET || 'supersecret',
8186
cookieSecret: process.env.COOKIE_SECRET || 'supersecret'
82-
}
87+
},
8388
},
8489
modules: {
8590
...dynamicModules,

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"dev": "medusa develop",
2121
"test:integration:http": "TEST_TYPE=integration:http NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --forceExit",
2222
"test:integration:modules": "TEST_TYPE=integration:modules NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --forceExit",
23+
"test:integration:new": "TEST_TYPE=integration:new NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --forceExit",
2324
"test:unit": "TEST_TYPE=unit NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --forceExit",
2425
"db:init": "yarn run db:migrate && yarn run db:sync-links && yarn run db:seed",
2526
"db:rollback": "medusa db:rollback",
@@ -31,6 +32,7 @@
3132
"@medusajs/admin-sdk": "2.12.5",
3233
"@medusajs/cli": "2.12.5",
3334
"@medusajs/framework": "2.12.5",
35+
"@medusajs/index": "^2.12.5",
3436
"@medusajs/medusa": "2.12.5",
3537
"@react-email/components": "1.0.4",
3638
"resend": "^6.7.0"

src/api/store/search/middlewares.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import { listProductQueryConfig } from './query-config';
55

66
export const storeSearchRoutesMiddlewares: MiddlewareRoute[] = [
77
{
8-
method: ['GET'],
8+
methods: ['GET'],
99
matcher: '/store/search',
10-
middlewares: [validateAndTransformQuery(StoreSearchProductsParams, listProductQueryConfig)]
10+
middlewares: [
11+
validateAndTransformQuery(StoreSearchProductsParams, listProductQueryConfig),
12+
]
1113
}
1214
];

src/api/store/search/query-config.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,34 @@
11
export const defaultStoreSearchProductFields = [
22
'id',
33
'title',
4+
'subtitle',
5+
'description',
46
'handle',
7+
'is_giftcard',
8+
'discountable',
59
'thumbnail',
10+
'collection_id',
11+
'type_id',
12+
'weight',
13+
'length',
14+
'height',
15+
'width',
16+
'hs_code',
17+
'origin_country',
18+
'mid_code',
19+
'material',
620
'created_at',
7-
'updated_at'
21+
'updated_at',
22+
'*type',
23+
'*collection',
24+
'*options',
25+
'*options.values',
26+
'*tags',
27+
'*images',
28+
'*variants',
29+
'*variants.options',
30+
'*variants.prices',
31+
'*variants.calculated_price',
832
];
933

1034
export const listProductQueryConfig = {

0 commit comments

Comments
 (0)