Merge release/next
This commit is contained in:
@@ -1,34 +1,34 @@
|
||||
const path = require("path");
|
||||
const express = require("express");
|
||||
const getPort = require("get-port");
|
||||
const importFrom = require("import-from");
|
||||
const path = require("path")
|
||||
const express = require("express")
|
||||
const getPort = require("get-port")
|
||||
const importFrom = require("import-from")
|
||||
|
||||
const initialize = async () => {
|
||||
const app = express();
|
||||
const app = express()
|
||||
|
||||
const cwd = process.cwd();
|
||||
const loaders = importFrom(cwd, "@medusajs/medusa/dist/loaders").default;
|
||||
const cwd = process.cwd()
|
||||
const loaders = importFrom(cwd, "@medusajs/medusa/dist/loaders").default
|
||||
|
||||
const { dbConnection } = await loaders({
|
||||
directory: path.resolve(process.cwd()),
|
||||
expressApp: app,
|
||||
});
|
||||
})
|
||||
|
||||
const PORT = await getPort();
|
||||
const PORT = await getPort()
|
||||
|
||||
return {
|
||||
db: dbConnection,
|
||||
app,
|
||||
port: PORT,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const setup = async () => {
|
||||
const { app, port } = await initialize();
|
||||
const { app, port } = await initialize()
|
||||
|
||||
app.listen(port, (err) => {
|
||||
process.send(port);
|
||||
});
|
||||
};
|
||||
process.send(port)
|
||||
})
|
||||
}
|
||||
|
||||
setup();
|
||||
setup()
|
||||
|
||||
+22
-22
@@ -1,26 +1,26 @@
|
||||
const { dropDatabase, createDatabase } = require("pg-god");
|
||||
const { createConnection } = require("typeorm");
|
||||
const { dropDatabase, createDatabase } = require("pg-god")
|
||||
const { createConnection } = require("typeorm")
|
||||
|
||||
const path = require("path");
|
||||
const path = require("path")
|
||||
|
||||
const DbTestUtil = {
|
||||
db_: null,
|
||||
|
||||
setDb: function (connection) {
|
||||
this.db_ = connection;
|
||||
this.db_ = connection
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
return this.db_.synchronize(true);
|
||||
return this.db_.synchronize(true)
|
||||
},
|
||||
|
||||
shutdown: async function () {
|
||||
await this.db_.close();
|
||||
return dropDatabase({ databaseName });
|
||||
await this.db_.close()
|
||||
return dropDatabase({ databaseName })
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const instance = DbTestUtil;
|
||||
const instance = DbTestUtil
|
||||
|
||||
module.exports = {
|
||||
initDb: async function ({ cwd }) {
|
||||
@@ -33,19 +33,19 @@ module.exports = {
|
||||
`dist`,
|
||||
`migrations`
|
||||
)
|
||||
);
|
||||
)
|
||||
|
||||
const databaseName = "medusa-fixtures";
|
||||
await createDatabase({ databaseName });
|
||||
const databaseName = "medusa-fixtures"
|
||||
await createDatabase({ databaseName })
|
||||
|
||||
const connection = await createConnection({
|
||||
type: "postgres",
|
||||
url: "postgres://localhost/medusa-fixtures",
|
||||
migrations: [`${migrationDir}/*.js`],
|
||||
});
|
||||
})
|
||||
|
||||
await connection.runMigrations();
|
||||
await connection.close();
|
||||
await connection.runMigrations()
|
||||
await connection.close()
|
||||
|
||||
const modelsLoader = require(path.join(
|
||||
cwd,
|
||||
@@ -55,19 +55,19 @@ module.exports = {
|
||||
`dist`,
|
||||
`loaders`,
|
||||
`models`
|
||||
)).default;
|
||||
)).default
|
||||
|
||||
const entities = modelsLoader({}, { register: false });
|
||||
const entities = modelsLoader({}, { register: false })
|
||||
const dbConnection = await createConnection({
|
||||
type: "postgres",
|
||||
url: "postgres://localhost/medusa-fixtures",
|
||||
entities,
|
||||
});
|
||||
})
|
||||
|
||||
instance.setDb(dbConnection);
|
||||
return dbConnection;
|
||||
instance.setDb(dbConnection)
|
||||
return dbConnection
|
||||
},
|
||||
useDb: function () {
|
||||
return instance;
|
||||
return instance
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
# Uploading images to S3
|
||||
|
||||
In order to work with images in Medusa, you need a file service plugin responsible for hosting. Following this guide will allow you to upload images to AWS S3.
|
||||
|
||||
### Before you start
|
||||
|
||||
At this point, you should have an instance of our store engine running. If not, we have a [full guide](https://docs.medusa-commerce.com/tutorial/set-up-your-development-environment) for setting up your local environment.
|
||||
|
||||
### Set up up AWS
|
||||
|
||||
#### Create an S3 bucket
|
||||
|
||||
In the AWS console navigate to S3 and create a bucket for your images. Make sure to uncheck "Block _all_ public access".
|
||||
|
||||
Additionally, you need to add a policy to your bucket, that will allow public access to objects that are uploaded. Navigate to the permissions tab of your bucket and add the following policy:
|
||||
|
||||
```shell=
|
||||
{
|
||||
"Id": "Policy1397632521960",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Stmt1397633323327",
|
||||
"Action": [
|
||||
"s3:GetObject"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*",
|
||||
"Principal": {
|
||||
"AWS": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Be aware, that this will allow for anyone to acces your bucket. Avoid storing sensitive data.
|
||||
|
||||
#### Generate access keys
|
||||
|
||||
Navigate to the IAM section of your AWS console and perform the following steps:
|
||||
|
||||
- Add a new user with programmatic access
|
||||
- Add the existing **AmazonS3FullAccess** policy to the user
|
||||
- Submit the details
|
||||
|
||||
Upon successfull creation of the user, you are presented with an **Access key ID** and a **Secret access key**. Note both of them down for later use.
|
||||
|
||||
### Installation
|
||||
|
||||
First, install the plugin using your preferred package manager:
|
||||
|
||||
```
|
||||
yarn add medusa-file-s3
|
||||
```
|
||||
|
||||
Then configure your `medusa-config.js` to include the plugin alongside the required options:
|
||||
|
||||
```=javascript
|
||||
{
|
||||
resolve: `medusa-file-s3`,
|
||||
options: {
|
||||
s3_url: "https://s3-guide-test.s3.eu-west-1.amazonaws.com",
|
||||
bucket: "test",
|
||||
region: "eu-west-1"
|
||||
access_key_id: "YOUR-ACCESS-KEY",
|
||||
secret_access_key: "YOUR-SECRET-KEY",
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
In the above options, an `s3_url` is included. The url has the following format:
|
||||
|
||||
```shell=
|
||||
https://[bucket].s3.[region].amazonaws.com
|
||||
```
|
||||
|
||||
The two access keys in the options are the ones created in the previous section.
|
||||
|
||||
> Make sure to use an environment variable for the secret key in a live environment.
|
||||
|
||||
### Try it out
|
||||
|
||||
Finally, run your Medusa server alongside our admin system to try out your new file service. Upon editing or creating products, you can now upload thumbnails and images, that are stored in an AWS S3 bucket.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Uploading images to Spaces
|
||||
In order to work with images in Medusa, you need a file service plugin responsible for hosting. Following this guide will allow you to upload images to DigitalOcean Spaces.
|
||||
|
||||
### Before you start
|
||||
At this point, you should have an instance of our store engine running. If not, we have a [full guide](https://docs.medusa-commerce.com/tutorial/set-up-your-development-environment) for setting up your local environment.
|
||||
|
||||
### Set up up DigitalOcean
|
||||
#### Create a Space
|
||||
Create an account on DigitalOcean and navigate to Spaces. Create a new Space with the default settings.
|
||||
|
||||
#### Generate access keys
|
||||
Navigate to API in the left sidebar. Generate a new Spaces access key. This should provide you with an access key id and a secret key. Note them both down.
|
||||
|
||||
### Installation
|
||||
First, install the plugin using your preferred package manager:
|
||||
```
|
||||
yarn add medusa-file-spaces
|
||||
```
|
||||
Then configure your `medusa-config.js` to include the plugin alongside the required options:
|
||||
```=javascript
|
||||
{
|
||||
resolve: `medusa-file-spaces`,
|
||||
options: {
|
||||
spaces_url: "https://test.fra1.digitaloceanspaces.com",
|
||||
bucket: "test",
|
||||
endpoint: "fra1.digitaloceanspaces.com",
|
||||
access_key_id: "YOUR-ACCESS-KEY",
|
||||
secret_access_key: "YOUR-SECRET-KEY",
|
||||
},
|
||||
},
|
||||
```
|
||||
In the above options, a `spaces_url` is included. This can be found in your Space overview. The `bucket` should point to the name you gave your Space. The `endpoint` identifies the region in which you created the Space. And finally the two keys are the ones created in the previous section.
|
||||
> Make sure to use an environment variable for the secret key in a live environment.
|
||||
|
||||
### Try it out!
|
||||
Finally, run your Medusa server alongside our admin system to try out your new file service. Upon editing or creating products, you can now upload thumbnails and images, that are stored in DigitalOcean Spaces.
|
||||
@@ -0,0 +1,16 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`/admin/discounts creates admin session correctly 1`] = `
|
||||
Object {
|
||||
"api_token": "test_token",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"email": "admin@medusa.js",
|
||||
"first_name": null,
|
||||
"id": "admin_user",
|
||||
"last_name": null,
|
||||
"metadata": null,
|
||||
"updated_at": Any<String>,
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`/admin/products GET /admin/products returns a list of products with child entities 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"collection": Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"handle": "test-collection",
|
||||
"id": StringMatching /\\^test-\\*/,
|
||||
"metadata": null,
|
||||
"title": "Test collection",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
"collection_id": "test-collection",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"description": "test-product-description",
|
||||
"discountable": true,
|
||||
"handle": "test-product",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": StringMatching /\\^test-\\*/,
|
||||
"images": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-\\*/,
|
||||
"metadata": null,
|
||||
"updated_at": Any<String>,
|
||||
"url": "test-image.png",
|
||||
},
|
||||
],
|
||||
"is_giftcard": false,
|
||||
"length": null,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"options": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-\\*/,
|
||||
"metadata": null,
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"title": "test-option",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
],
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "draft",
|
||||
"subtitle": null,
|
||||
"tags": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^tag\\*/,
|
||||
"metadata": null,
|
||||
"updated_at": Any<String>,
|
||||
"value": "123",
|
||||
},
|
||||
],
|
||||
"thumbnail": null,
|
||||
"title": "Test product",
|
||||
"type": Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-\\*/,
|
||||
"metadata": null,
|
||||
"updated_at": Any<String>,
|
||||
"value": "test-type",
|
||||
},
|
||||
"type_id": "test-type",
|
||||
"updated_at": Any<String>,
|
||||
"variants": Array [
|
||||
Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-variant",
|
||||
"inventory_quantity": 10,
|
||||
"length": null,
|
||||
"manage_inventory": true,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"options": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-variant-option\\*/,
|
||||
"metadata": null,
|
||||
"option_id": StringMatching /\\^test-opt\\*/,
|
||||
"updated_at": Any<String>,
|
||||
"value": "Default variant",
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"origin_country": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
"created_at": Any<String>,
|
||||
"currency_code": "usd",
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-price\\*/,
|
||||
"region_id": null,
|
||||
"sale_amount": null,
|
||||
"updated_at": Any<String>,
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku",
|
||||
"title": "Test variant",
|
||||
"upc": "test-upc",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean2",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-variant_2",
|
||||
"inventory_quantity": 10,
|
||||
"length": null,
|
||||
"manage_inventory": true,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"options": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-variant-option\\*/,
|
||||
"metadata": null,
|
||||
"option_id": StringMatching /\\^test-opt\\*/,
|
||||
"updated_at": Any<String>,
|
||||
"value": "Default variant 2",
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"origin_country": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
"created_at": Any<String>,
|
||||
"currency_code": "usd",
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-price\\*/,
|
||||
"region_id": null,
|
||||
"sale_amount": null,
|
||||
"updated_at": Any<String>,
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku2",
|
||||
"title": "Test variant rank (2)",
|
||||
"upc": "test-upc2",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": "test-barcode 1",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean1",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-variant_1",
|
||||
"inventory_quantity": 10,
|
||||
"length": null,
|
||||
"manage_inventory": true,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"options": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-variant-option\\*/,
|
||||
"metadata": null,
|
||||
"option_id": StringMatching /\\^test-opt\\*/,
|
||||
"updated_at": Any<String>,
|
||||
"value": "Default variant 1",
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"origin_country": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
"created_at": Any<String>,
|
||||
"currency_code": "usd",
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-price\\*/,
|
||||
"region_id": null,
|
||||
"sale_amount": null,
|
||||
"updated_at": Any<String>,
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku1",
|
||||
"title": "Test variant rank (1)",
|
||||
"upc": "test-upc1",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
],
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
Object {
|
||||
"collection": Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"handle": "test-collection",
|
||||
"id": StringMatching /\\^test-\\*/,
|
||||
"metadata": null,
|
||||
"title": "Test collection",
|
||||
"updated_at": Any<String>,
|
||||
},
|
||||
"collection_id": "test-collection",
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"description": "test-product-description1",
|
||||
"discountable": true,
|
||||
"handle": "test-product1",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": StringMatching /\\^test-\\*/,
|
||||
"images": Array [],
|
||||
"is_giftcard": false,
|
||||
"length": null,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"options": Array [],
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "draft",
|
||||
"subtitle": null,
|
||||
"tags": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^tag\\*/,
|
||||
"metadata": null,
|
||||
"updated_at": Any<String>,
|
||||
"value": "123",
|
||||
},
|
||||
],
|
||||
"thumbnail": null,
|
||||
"title": "Test product1",
|
||||
"type": Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-\\*/,
|
||||
"metadata": null,
|
||||
"updated_at": Any<String>,
|
||||
"value": "test-type",
|
||||
},
|
||||
"type_id": "test-type",
|
||||
"updated_at": Any<String>,
|
||||
"variants": Array [
|
||||
Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean4",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-variant_4",
|
||||
"inventory_quantity": 10,
|
||||
"length": null,
|
||||
"manage_inventory": true,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"options": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-variant-option\\*/,
|
||||
"metadata": null,
|
||||
"option_id": StringMatching /\\^test-opt\\*/,
|
||||
"updated_at": Any<String>,
|
||||
"value": "Default variant 4",
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"origin_country": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
"created_at": Any<String>,
|
||||
"currency_code": "usd",
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-price\\*/,
|
||||
"region_id": null,
|
||||
"sale_amount": null,
|
||||
"updated_at": Any<String>,
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku4",
|
||||
"title": "Test variant rank (2)",
|
||||
"upc": "test-upc4",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
Object {
|
||||
"allow_backorder": false,
|
||||
"barcode": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"ean": "test-ean3",
|
||||
"height": null,
|
||||
"hs_code": null,
|
||||
"id": "test-variant_3",
|
||||
"inventory_quantity": 10,
|
||||
"length": null,
|
||||
"manage_inventory": true,
|
||||
"material": null,
|
||||
"metadata": null,
|
||||
"mid_code": null,
|
||||
"options": Array [
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-variant-option\\*/,
|
||||
"metadata": null,
|
||||
"option_id": StringMatching /\\^test-opt\\*/,
|
||||
"updated_at": Any<String>,
|
||||
"value": "Default variant 3",
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"origin_country": null,
|
||||
"prices": Array [
|
||||
Object {
|
||||
"amount": 100,
|
||||
"created_at": Any<String>,
|
||||
"currency_code": "usd",
|
||||
"deleted_at": null,
|
||||
"id": StringMatching /\\^test-price\\*/,
|
||||
"region_id": null,
|
||||
"sale_amount": null,
|
||||
"updated_at": Any<String>,
|
||||
"variant_id": StringMatching /\\^test-variant\\*/,
|
||||
},
|
||||
],
|
||||
"product_id": StringMatching /\\^test-\\*/,
|
||||
"sku": "test-sku3",
|
||||
"title": "Test variant rank (2)",
|
||||
"upc": "test-upc3",
|
||||
"updated_at": Any<String>,
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
],
|
||||
"weight": null,
|
||||
"width": null,
|
||||
},
|
||||
]
|
||||
`;
|
||||
@@ -0,0 +1,16 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`/admin/return-reasons POST /admin/return-reasons creates a return_reason 1`] = `
|
||||
Object {
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"description": "Use this if the size was too big",
|
||||
"id": Any<String>,
|
||||
"label": "Too Big",
|
||||
"parent_return_reason": null,
|
||||
"parent_return_reason_id": null,
|
||||
"return_reason_children": Array [],
|
||||
"updated_at": Any<String>,
|
||||
"value": "too_big",
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,54 @@
|
||||
const path = require("path")
|
||||
const { Region, DiscountRule, Discount } = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
const { exportAllDeclaration } = require("@babel/types")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/auth", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (e) {
|
||||
throw e
|
||||
}
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
it("creates admin session correctly", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post("/admin/auth", {
|
||||
email: "admin@medusa.js",
|
||||
password: "secret_password",
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.user.password_hash).toEqual(undefined)
|
||||
expect(response.data.user).toMatchSnapshot({
|
||||
email: "admin@medusa.js",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,50 +1,50 @@
|
||||
const { dropDatabase } = require("pg-god");
|
||||
const path = require("path");
|
||||
const { dropDatabase } = require("pg-god")
|
||||
const path = require("path")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server");
|
||||
const { useApi } = require("../../../helpers/use-api");
|
||||
const { useDb, initDb } = require("../../../helpers/use-db");
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { useDb, initDb } = require("../../../helpers/use-db")
|
||||
|
||||
const customerSeeder = require("../../helpers/customer-seeder");
|
||||
const adminSeeder = require("../../helpers/admin-seeder");
|
||||
const customerSeeder = require("../../helpers/customer-seeder")
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
|
||||
jest.setTimeout(30000);
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/customers", () => {
|
||||
let medusaProcess;
|
||||
let dbConnection;
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."));
|
||||
dbConnection = await initDb({ cwd });
|
||||
medusaProcess = await setupServer({ cwd });
|
||||
});
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb();
|
||||
await db.shutdown();
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill();
|
||||
});
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("GET /admin/customers", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection);
|
||||
await customerSeeder(dbConnection);
|
||||
await adminSeeder(dbConnection)
|
||||
await customerSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb();
|
||||
await db.teardown();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("lists customers and query count", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/customers", {
|
||||
@@ -53,11 +53,11 @@ describe("/admin/customers", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.count).toEqual(3);
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(4)
|
||||
expect(response.data.customers).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
@@ -69,25 +69,28 @@ describe("/admin/customers", () => {
|
||||
expect.objectContaining({
|
||||
id: "test-customer-3",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "test-customer-has_account",
|
||||
}),
|
||||
])
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("lists customers with specific query", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/customers?q=test2@email.com", {
|
||||
.get("/admin/customers?q=est2@", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.count).toEqual(1);
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.customers).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
@@ -95,11 +98,11 @@ describe("/admin/customers", () => {
|
||||
email: "test2@email.com",
|
||||
}),
|
||||
])
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("lists customers with expand query", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/customers?q=test1@email.com&expand=shipping_addresses", {
|
||||
@@ -108,11 +111,11 @@ describe("/admin/customers", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.count).toEqual(1);
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.customers).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
@@ -126,7 +129,54 @@ describe("/admin/customers", () => {
|
||||
]),
|
||||
}),
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/customers/:id", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
await customerSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("Correctly updates customer", async () => {
|
||||
const api = useApi()
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/customers/test-customer-3",
|
||||
{
|
||||
first_name: "newf",
|
||||
last_name: "newl",
|
||||
email: "new@email.com",
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).toEqual(
|
||||
expect.objectContaining({
|
||||
first_name: "newf",
|
||||
last_name: "newl",
|
||||
email: "new@email.com",
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,6 +24,67 @@ describe("/admin/discounts", () => {
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("GET /admin/discounts", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
await manager.insert(DiscountRule, {
|
||||
id: "test-discount-rule",
|
||||
description: "Test discount rule",
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
})
|
||||
await manager.insert(Discount, {
|
||||
id: "test-discount",
|
||||
code: "TESTING",
|
||||
rule_id: "test-discount-rule",
|
||||
is_dynamic: false,
|
||||
is_disabled: false,
|
||||
})
|
||||
await manager.insert(Discount, {
|
||||
id: "messi-discount",
|
||||
code: "BARCA100",
|
||||
rule_id: "test-discount-rule",
|
||||
is_dynamic: false,
|
||||
is_disabled: false,
|
||||
})
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should list discounts that match a specific query in a case insensitive manner", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/discounts?q=barca", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toEqual(1)
|
||||
expect(response.data.discounts).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "messi-discount",
|
||||
code: "BARCA100",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/discounts", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
@@ -97,6 +158,193 @@ describe("/admin/discounts", () => {
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("creates a discount with start and end dates", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/discounts",
|
||||
{
|
||||
code: "HELLOWORLD",
|
||||
rule: {
|
||||
description: "test",
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
usage_limit: 10,
|
||||
starts_at: new Date("09/15/2021 11:50"),
|
||||
ends_at: new Date("09/15/2021 17:50"),
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.discount).toEqual(
|
||||
expect.objectContaining({
|
||||
code: "HELLOWORLD",
|
||||
usage_limit: 10,
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
})
|
||||
)
|
||||
|
||||
expect(new Date(response.data.discount.starts_at)).toEqual(
|
||||
new Date("09/15/2021 11:50")
|
||||
)
|
||||
|
||||
expect(new Date(response.data.discount.ends_at)).toEqual(
|
||||
new Date("09/15/2021 17:50")
|
||||
)
|
||||
|
||||
const updated = await api
|
||||
.post(
|
||||
`/admin/discounts/${response.data.discount.id}`,
|
||||
{
|
||||
usage_limit: 20,
|
||||
starts_at: new Date("09/14/2021 11:50"),
|
||||
ends_at: new Date("09/17/2021 17:50"),
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(updated.status).toEqual(200)
|
||||
expect(updated.data.discount).toEqual(
|
||||
expect.objectContaining({
|
||||
code: "HELLOWORLD",
|
||||
usage_limit: 20,
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
})
|
||||
)
|
||||
|
||||
expect(new Date(updated.data.discount.starts_at)).toEqual(
|
||||
new Date("09/14/2021 11:50")
|
||||
)
|
||||
|
||||
expect(new Date(updated.data.discount.ends_at)).toEqual(
|
||||
new Date("09/17/2021 17:50")
|
||||
)
|
||||
})
|
||||
|
||||
it("fails to update end date to a date before start date", async () => {
|
||||
expect.assertions(6)
|
||||
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/discounts",
|
||||
{
|
||||
code: "HELLOWORLD",
|
||||
rule: {
|
||||
description: "test",
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
usage_limit: 10,
|
||||
starts_at: new Date("09/15/2021 11:50"),
|
||||
ends_at: new Date("09/15/2021 17:50"),
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.discount).toEqual(
|
||||
expect.objectContaining({
|
||||
code: "HELLOWORLD",
|
||||
usage_limit: 10,
|
||||
starts_at: expect.any(String),
|
||||
ends_at: expect.any(String),
|
||||
})
|
||||
)
|
||||
|
||||
expect(new Date(response.data.discount.starts_at)).toEqual(
|
||||
new Date("09/15/2021 11:50")
|
||||
)
|
||||
|
||||
expect(new Date(response.data.discount.ends_at)).toEqual(
|
||||
new Date("09/15/2021 17:50")
|
||||
)
|
||||
|
||||
await api
|
||||
.post(
|
||||
`/admin/discounts/${response.data.discount.id}`,
|
||||
{
|
||||
usage_limit: 20,
|
||||
ends_at: new Date("09/11/2021 17:50"),
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(400)
|
||||
expect(err.response.data.message).toEqual(
|
||||
`"ends_at" must be greater than "starts_at"`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("fails to create discount with end date before start date", async () => {
|
||||
expect.assertions(2)
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/discounts",
|
||||
{
|
||||
code: "HELLOWORLD",
|
||||
rule: {
|
||||
description: "test",
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
usage_limit: 10,
|
||||
starts_at: new Date("09/15/2021 11:50"),
|
||||
ends_at: new Date("09/14/2021 17:50"),
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(400)
|
||||
expect(err.response.data.message).toEqual([
|
||||
expect.objectContaining({
|
||||
message: `"ends_at" must be greater than "ref:starts_at"`,
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("testing for soft-deletion + uniqueness on discount codes", () => {
|
||||
@@ -225,6 +473,21 @@ describe("/admin/discounts", () => {
|
||||
is_dynamic: true,
|
||||
is_disabled: false,
|
||||
rule_id: "test-discount-rule",
|
||||
valid_duration: "P2Y",
|
||||
})
|
||||
await manager.insert(DiscountRule, {
|
||||
id: "test-discount-rule1",
|
||||
description: "Dynamic rule",
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
})
|
||||
await manager.insert(Discount, {
|
||||
id: "test-discount1",
|
||||
code: "DYNAMICCode",
|
||||
is_dynamic: true,
|
||||
is_disabled: false,
|
||||
rule_id: "test-discount-rule1",
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
@@ -237,7 +500,7 @@ describe("/admin/discounts", () => {
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("creates a dynamic discount", async () => {
|
||||
it("creates a dynamic discount with ends_at", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
@@ -257,6 +520,40 @@ describe("/admin/discounts", () => {
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.discount).toEqual(
|
||||
expect.objectContaining({
|
||||
code: "HELLOWORLD",
|
||||
ends_at: expect.any(String),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("creates a dynamic discount without ends_at", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/discounts/test-discount1/dynamic-codes",
|
||||
{
|
||||
code: "HELLOWORLD",
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
// console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.discount).toEqual(
|
||||
expect.objectContaining({
|
||||
code: "HELLOWORLD",
|
||||
ends_at: null,
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,54 +1,162 @@
|
||||
const path = require("path");
|
||||
const { Region } = require("@medusajs/medusa");
|
||||
const path = require("path")
|
||||
const { Region, GiftCard } = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server");
|
||||
const { useApi } = require("../../../helpers/use-api");
|
||||
const { initDb, useDb } = require("../../../helpers/use-db");
|
||||
const adminSeeder = require("../../helpers/admin-seeder");
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
|
||||
jest.setTimeout(30000);
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/gift-cards", () => {
|
||||
let medusaProcess;
|
||||
let dbConnection;
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."));
|
||||
dbConnection = await initDb({ cwd });
|
||||
medusaProcess = await setupServer({ cwd });
|
||||
});
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb();
|
||||
await db.shutdown();
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill();
|
||||
});
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("GET /admin/gift-cards", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
await manager.insert(Region, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
await manager.insert(GiftCard, {
|
||||
id: "gift_test",
|
||||
code: "GC_TEST",
|
||||
value: 20000,
|
||||
balance: 20000,
|
||||
region_id: "test-region",
|
||||
})
|
||||
await manager.insert(GiftCard, {
|
||||
id: "another_gift_test",
|
||||
code: "CARD_TEST",
|
||||
value: 200000,
|
||||
balance: 200000,
|
||||
region_id: "test-region",
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("lists gift cards and query count", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/gift-cards", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.gift_cards).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "gift_test",
|
||||
code: "GC_TEST",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "another_gift_test",
|
||||
code: "CARD_TEST",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("lists gift cards with specific query", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/gift-cards?q=gc", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.gift_cards.length).toEqual(1)
|
||||
expect(response.data.gift_cards).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "gift_test",
|
||||
code: "GC_TEST",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("lists no gift cards on query for non-existing gift card code", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/gift-cards?q=bla", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.gift_cards.length).toEqual(0)
|
||||
expect(response.data.gift_cards).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/gift-cards", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager;
|
||||
const manager = dbConnection.manager
|
||||
try {
|
||||
await adminSeeder(dbConnection);
|
||||
await adminSeeder(dbConnection)
|
||||
await manager.insert(Region, {
|
||||
id: "region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
});
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb();
|
||||
await db.teardown();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("creates a gift card", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
@@ -64,13 +172,13 @@ describe("/admin/gift-cards", () => {
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.gift_card.value).toEqual(1000);
|
||||
expect(response.data.gift_card.balance).toEqual(1000);
|
||||
expect(response.data.gift_card.region_id).toEqual("region");
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.gift_card.value).toEqual(1000)
|
||||
expect(response.data.gift_card.balance).toEqual(1000)
|
||||
expect(response.data.gift_card.region_id).toEqual("region")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
const path = require("path")
|
||||
const { Note } = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
const note = {
|
||||
id: "note1",
|
||||
value: "note text",
|
||||
resource_id: "resource1",
|
||||
resource_type: "type",
|
||||
author: { id: "admin_user" },
|
||||
}
|
||||
|
||||
describe("/admin/notes", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("GET /admin/notes/:id", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
await manager.insert(Note, note)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("properly retrieves note", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.get("/admin/notes/note1", {
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
|
||||
expect(response.data).toMatchObject({
|
||||
note: {
|
||||
id: "note1",
|
||||
resource_id: "resource1",
|
||||
resource_type: "type",
|
||||
value: "note text",
|
||||
author: { id: "admin_user" },
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/notes", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("creates a note", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post(
|
||||
"/admin/notes",
|
||||
{
|
||||
resource_id: "resource-id",
|
||||
resource_type: "resource-type",
|
||||
value: "my note",
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.data).toMatchObject({
|
||||
note: {
|
||||
id: expect.stringMatching(/^note_*/),
|
||||
resource_id: "resource-id",
|
||||
resource_type: "resource-type",
|
||||
value: "my note",
|
||||
author_id: "admin_user",
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("GET /admin/notes", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
await manager.insert(Note, { ...note, id: "note1" })
|
||||
await manager.insert(Note, { ...note, id: "note2" })
|
||||
await manager.insert(Note, {
|
||||
...note,
|
||||
id: "note3",
|
||||
resource_id: "resource2",
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("lists notes only related to wanted resource", async () => {
|
||||
const api = useApi()
|
||||
const response = await api
|
||||
.get("/admin/notes?resource_id=resource1", {
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.data.notes.length).toEqual(2)
|
||||
expect(response.data).toMatchObject({
|
||||
notes: [
|
||||
{
|
||||
id: "note1",
|
||||
resource_id: "resource1",
|
||||
resource_type: "type",
|
||||
value: "note text",
|
||||
author: { id: "admin_user" },
|
||||
},
|
||||
{
|
||||
id: "note2",
|
||||
resource_id: "resource1",
|
||||
resource_type: "type",
|
||||
value: "note text",
|
||||
author: { id: "admin_user" },
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/notes/:id", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
await manager.insert(Note, note)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("updates the content of the note", async () => {
|
||||
const api = useApi()
|
||||
|
||||
await api
|
||||
.post(
|
||||
"/admin/notes/note1",
|
||||
{ value: "new text" },
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const response = await api
|
||||
.get("/admin/notes/note1", {
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.data.note.value).toEqual("new text")
|
||||
})
|
||||
})
|
||||
|
||||
describe("DELETE /admin/notes/:id", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
|
||||
await manager.insert(Note, note)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("deletes the wanted note", async () => {
|
||||
const api = useApi()
|
||||
|
||||
await api
|
||||
.delete("/admin/notes/note1", {
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
let error
|
||||
await api
|
||||
.get("/admin/notes/note1", {
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => (error = err))
|
||||
|
||||
expect(error.response.status).toEqual(404)
|
||||
})
|
||||
})
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,73 @@ describe("/admin/products", () => {
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("returns a list of products with all statuses when no status or invalid status is provided", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const res = await api
|
||||
.get("/admin/products?status%5B%5D=null", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
expect(res.data.products).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "test-product",
|
||||
status: "draft",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: "test-product1",
|
||||
status: "draft",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("returns a list of products where status is proposed", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
status: "proposed",
|
||||
}
|
||||
|
||||
//update test-product status to proposed
|
||||
await api
|
||||
.post("/admin/products/test-product", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const response = await api
|
||||
.get("/admin/products?status%5B%5D=proposed", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.products).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "test-product",
|
||||
status: "proposed",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("returns a list of products with child entities", async () => {
|
||||
const api = useApi()
|
||||
|
||||
@@ -297,6 +364,7 @@ describe("/admin/products", () => {
|
||||
discountable: true,
|
||||
is_giftcard: false,
|
||||
handle: "test",
|
||||
status: "draft",
|
||||
images: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
url: "test-image.png",
|
||||
@@ -455,7 +523,7 @@ describe("/admin/products", () => {
|
||||
)
|
||||
})
|
||||
|
||||
it("updates a product (update prices, tags, delete collection, delete type, replaces images)", async () => {
|
||||
it("updates a product (update prices, tags, update status, delete collection, delete type, replaces images)", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
@@ -476,6 +544,7 @@ describe("/admin/products", () => {
|
||||
tags: [{ value: "123" }],
|
||||
images: ["test-image-2.png"],
|
||||
type: { value: "test-type-2" },
|
||||
status: "published",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
@@ -514,6 +583,7 @@ describe("/admin/products", () => {
|
||||
}),
|
||||
],
|
||||
type: null,
|
||||
status: "published",
|
||||
collection: null,
|
||||
type: expect.objectContaining({
|
||||
value: "test-type-2",
|
||||
@@ -522,6 +592,25 @@ describe("/admin/products", () => {
|
||||
)
|
||||
})
|
||||
|
||||
it("fails to update product with invalid status", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
status: null,
|
||||
}
|
||||
|
||||
try {
|
||||
await api.post("/admin/products/test-product", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
} catch (e) {
|
||||
expect(e.response.status).toEqual(400)
|
||||
expect(e.response.data.type).toEqual("invalid_data")
|
||||
}
|
||||
})
|
||||
|
||||
it("updates a product (variant ordering)", async () => {
|
||||
const api = useApi()
|
||||
|
||||
|
||||
@@ -1,53 +1,55 @@
|
||||
const path = require("path");
|
||||
const { match } = require("assert")
|
||||
const path = require("path")
|
||||
const { RepositoryNotTreeError } = require("typeorm")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server");
|
||||
const { useApi } = require("../../../helpers/use-api");
|
||||
const { initDb, useDb } = require("../../../helpers/use-db");
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const adminSeeder = require("../../helpers/admin-seeder");
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
|
||||
jest.setTimeout(30000);
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/return-reasons", () => {
|
||||
let medusaProcess;
|
||||
let dbConnection;
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."));
|
||||
dbConnection = await initDb({ cwd });
|
||||
medusaProcess = await setupServer({ cwd });
|
||||
});
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb();
|
||||
await db.shutdown();
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill();
|
||||
});
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("POST /admin/return-reasons", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection);
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb();
|
||||
await db.teardown();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("creates a return_reason", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
};
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
@@ -56,10 +58,172 @@ describe("/admin/return-reasons", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.return_reason).toMatchSnapshot({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
parent_return_reason: null,
|
||||
parent_return_reason_id: null,
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
})
|
||||
})
|
||||
|
||||
it("creates a nested return reason", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Wrong size",
|
||||
description: "Use this if the size was too big",
|
||||
value: "wrong_size",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
label: "Wrong size",
|
||||
description: "Use this if the size was too big",
|
||||
value: "wrong_size",
|
||||
})
|
||||
)
|
||||
|
||||
const nested_payload = {
|
||||
parent_return_reason_id: response.data.return_reason.id,
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
}
|
||||
|
||||
const nested_response = await api
|
||||
.post("/admin/return-reasons", nested_payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(nested_response.status).toEqual(200)
|
||||
|
||||
expect(nested_response.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
parent_return_reason_id: response.data.return_reason.id,
|
||||
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("fails to create a doubly nested return reason", async () => {
|
||||
expect.assertions(5)
|
||||
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Wrong size",
|
||||
description: "Use this if the size was too big",
|
||||
value: "wrong_size",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
label: "Wrong size",
|
||||
description: "Use this if the size was too big",
|
||||
value: "wrong_size",
|
||||
})
|
||||
)
|
||||
|
||||
const nested_payload = {
|
||||
parent_return_reason_id: response.data.return_reason.id,
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
}
|
||||
|
||||
const nested_response = await api
|
||||
.post("/admin/return-reasons", nested_payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const dbl_nested_payload = {
|
||||
parent_return_reason_id: nested_response.data.return_reason.id,
|
||||
label: "Too large size",
|
||||
description: "Use this if the size was too big",
|
||||
value: "large_size",
|
||||
}
|
||||
|
||||
const dbl_nested_response = await api
|
||||
.post("/admin/return-reasons", dbl_nested_payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(400)
|
||||
expect(err.response.data.type).toEqual("invalid_data")
|
||||
expect(err.response.data.message).toEqual(
|
||||
"Doubly nested return reasons is not supported"
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
it("deletes a return_reason", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
@@ -67,17 +231,37 @@ describe("/admin/return-reasons", () => {
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
})
|
||||
);
|
||||
});
|
||||
)
|
||||
|
||||
const deleteResponse = await api
|
||||
.delete(`/admin/return-reasons/${response.data.return_reason.id}`, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(deleteResponse.data).toEqual(
|
||||
expect.objectContaining({
|
||||
id: response.data.return_reason.id,
|
||||
object: "return_reason",
|
||||
deleted: true,
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("update a return reason", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Too Big Typo",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
};
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
@@ -86,10 +270,10 @@ describe("/admin/return-reasons", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
@@ -97,7 +281,7 @@ describe("/admin/return-reasons", () => {
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
})
|
||||
);
|
||||
)
|
||||
|
||||
const newResponse = await api
|
||||
.post(
|
||||
@@ -113,8 +297,8 @@ describe("/admin/return-reasons", () => {
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(newResponse.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
@@ -122,17 +306,81 @@ describe("/admin/return-reasons", () => {
|
||||
description: "new desc",
|
||||
value: "too_big",
|
||||
})
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("lists nested return reasons", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Wrong size",
|
||||
description: "Use this if the size was too big",
|
||||
value: "wrong_size",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const nested_payload = {
|
||||
parent_return_reason_id: response.data.return_reason.id,
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
}
|
||||
|
||||
const resp = await api
|
||||
.post("/admin/return-reasons", nested_payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const nested_response = await api
|
||||
.get("/admin/return-reasons", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(nested_response.status).toEqual(200)
|
||||
|
||||
expect(nested_response.data.return_reasons).toEqual([
|
||||
expect.objectContaining({
|
||||
label: "Wrong size",
|
||||
description: "Use this if the size was too big",
|
||||
value: "wrong_size",
|
||||
return_reason_children: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("list return reasons", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Too Big Typo",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
};
|
||||
}
|
||||
|
||||
await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
@@ -141,8 +389,8 @@ describe("/admin/return-reasons", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const response = await api
|
||||
.get("/admin/return-reasons", {
|
||||
@@ -151,15 +399,191 @@ describe("/admin/return-reasons", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.return_reasons).toEqual([
|
||||
expect.objectContaining({
|
||||
value: "too_big",
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("DELETE /admin/return-reasons", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("deletes single return reason", async () => {
|
||||
expect.assertions(6)
|
||||
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
})
|
||||
)
|
||||
|
||||
const deleteResult = await api.delete(
|
||||
`/admin/return-reasons/${response.data.return_reason.id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
expect(deleteResult.status).toEqual(200)
|
||||
|
||||
expect(deleteResult.data).toEqual({
|
||||
id: response.data.return_reason.id,
|
||||
object: "return_reason",
|
||||
deleted: true,
|
||||
})
|
||||
|
||||
const getResult = await api
|
||||
.get(`/admin/return-reasons/${response.data.return_reason.id}`, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(404)
|
||||
expect(err.response.data.type).toEqual("not_found")
|
||||
})
|
||||
})
|
||||
|
||||
it("deletes cascade through nested return reasons", async () => {
|
||||
expect.assertions(10)
|
||||
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
label: "Wrong Size",
|
||||
description: "Use this if the size was wrong",
|
||||
value: "wrong_size",
|
||||
}
|
||||
|
||||
const response = await api
|
||||
.post("/admin/return-reasons", payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
label: "Wrong Size",
|
||||
description: "Use this if the size was wrong",
|
||||
value: "wrong_size",
|
||||
})
|
||||
)
|
||||
|
||||
const payload_child = {
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
parent_return_reason_id: response.data.return_reason.id,
|
||||
}
|
||||
|
||||
const response_child = await api
|
||||
.post("/admin/return-reasons", payload_child, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response_child.status).toEqual(200)
|
||||
|
||||
expect(response_child.data.return_reason).toEqual(
|
||||
expect.objectContaining({
|
||||
label: "Too Big",
|
||||
description: "Use this if the size was too big",
|
||||
value: "too_big",
|
||||
parent_return_reason_id: response.data.return_reason.id,
|
||||
})
|
||||
)
|
||||
|
||||
const deleteResult = await api
|
||||
.delete(`/admin/return-reasons/${response.data.return_reason.id}`, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.response.data)
|
||||
})
|
||||
|
||||
expect(deleteResult.status).toEqual(200)
|
||||
|
||||
expect(deleteResult.data).toEqual({
|
||||
id: response.data.return_reason.id,
|
||||
object: "return_reason",
|
||||
deleted: true,
|
||||
})
|
||||
|
||||
await api
|
||||
.get(`/admin/return-reasons/${response.data.return_reason.id}`, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(404)
|
||||
expect(err.response.data.type).toEqual("not_found")
|
||||
})
|
||||
|
||||
await api
|
||||
.get(`/admin/return-reasons/${response_child.data.return_reason.id}`, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
expect(err.response.status).toEqual(404)
|
||||
expect(err.response.data.type).toEqual("not_found")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,102 +1,53 @@
|
||||
const path = require("path");
|
||||
const path = require("path")
|
||||
const {
|
||||
Region,
|
||||
ShippingProfile,
|
||||
ShippingOption,
|
||||
ShippingOptionRequirement,
|
||||
} = require("@medusajs/medusa");
|
||||
} = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server");
|
||||
const { useApi } = require("../../../helpers/use-api");
|
||||
const { initDb, useDb } = require("../../../helpers/use-db");
|
||||
const adminSeeder = require("../../helpers/admin-seeder");
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
const shippingOptionSeeder = require("../../helpers/shipping-option-seeder")
|
||||
|
||||
jest.setTimeout(30000);
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/shipping-options", () => {
|
||||
let medusaProcess;
|
||||
let dbConnection;
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."));
|
||||
dbConnection = await initDb({ cwd });
|
||||
medusaProcess = await setupServer({ cwd });
|
||||
});
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb();
|
||||
await db.shutdown();
|
||||
medusaProcess.kill();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("POST /admin/shipping-options", () => {
|
||||
describe("POST /admin/shipping-options/:id", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager;
|
||||
|
||||
try {
|
||||
await adminSeeder(dbConnection);
|
||||
|
||||
await manager.insert(Region, {
|
||||
id: "region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
});
|
||||
|
||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||
type: "default",
|
||||
});
|
||||
|
||||
await manager.insert(ShippingOption, {
|
||||
id: "test-out",
|
||||
name: "Test out",
|
||||
profile_id: defaultProfile.id,
|
||||
region_id: "region",
|
||||
provider_id: "test-ful",
|
||||
data: {},
|
||||
price_type: "flat_rate",
|
||||
amount: 2000,
|
||||
is_return: false,
|
||||
});
|
||||
|
||||
await manager.insert(ShippingOption, {
|
||||
id: "test-option-req",
|
||||
name: "With req",
|
||||
profile_id: defaultProfile.id,
|
||||
region_id: "region",
|
||||
provider_id: "test-ful",
|
||||
data: {},
|
||||
price_type: "flat_rate",
|
||||
amount: 2000,
|
||||
is_return: false,
|
||||
});
|
||||
|
||||
await manager.insert(ShippingOptionRequirement, {
|
||||
id: "option-req",
|
||||
shipping_option_id: "test-option-req",
|
||||
type: "min_subtotal",
|
||||
amount: 5,
|
||||
});
|
||||
|
||||
await manager.insert(ShippingOptionRequirement, {
|
||||
id: "option-req-2",
|
||||
shipping_option_id: "test-option-req",
|
||||
type: "max_subtotal",
|
||||
amount: 10,
|
||||
});
|
||||
await adminSeeder(dbConnection)
|
||||
await shippingOptionSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
throw err;
|
||||
console.error(err)
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb();
|
||||
await db.teardown();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("updates a shipping option with no existing requirements", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
name: "Test option",
|
||||
@@ -111,36 +62,36 @@ describe("/admin/shipping-options", () => {
|
||||
amount: 2,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const res = await api.post(`/admin/shipping-options/test-out`, payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
const requirements = res.data.shipping_option.requirements;
|
||||
const requirements = res.data.shipping_option.requirements
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(requirements.length).toEqual(2);
|
||||
expect(res.status).toEqual(200)
|
||||
expect(requirements.length).toEqual(2)
|
||||
expect(requirements[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
type: "min_subtotal",
|
||||
shipping_option_id: "test-out",
|
||||
amount: 1,
|
||||
})
|
||||
);
|
||||
)
|
||||
expect(requirements[1]).toEqual(
|
||||
expect.objectContaining({
|
||||
type: "max_subtotal",
|
||||
shipping_option_id: "test-out",
|
||||
amount: 2,
|
||||
})
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("fails as it is not allowed to set id from client side", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
name: "Test option",
|
||||
@@ -157,7 +108,7 @@ describe("/admin/shipping-options", () => {
|
||||
amount: 2,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const res = await api
|
||||
.post(`/admin/shipping-options/test-out`, payload, {
|
||||
@@ -166,15 +117,15 @@ describe("/admin/shipping-options", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
return err.response;
|
||||
});
|
||||
return err.response
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(400);
|
||||
expect(res.data.message).toEqual("ID does not exist");
|
||||
});
|
||||
expect(res.status).toEqual(400)
|
||||
expect(res.data.message).toEqual("ID does not exist")
|
||||
})
|
||||
|
||||
it("it succesfully updates a set of existing requirements", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
requirements: [
|
||||
@@ -190,7 +141,7 @@ describe("/admin/shipping-options", () => {
|
||||
},
|
||||
],
|
||||
amount: 200,
|
||||
};
|
||||
}
|
||||
|
||||
const res = await api
|
||||
.post(`/admin/shipping-options/test-option-req`, payload, {
|
||||
@@ -199,14 +150,14 @@ describe("/admin/shipping-options", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.response.data.message);
|
||||
});
|
||||
console.log(err.response.data.message)
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
});
|
||||
expect(res.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("it succesfully updates a set of existing requirements by updating one and deleting the other", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
requirements: [
|
||||
@@ -216,7 +167,7 @@ describe("/admin/shipping-options", () => {
|
||||
amount: 15,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const res = await api
|
||||
.post(`/admin/shipping-options/test-option-req`, payload, {
|
||||
@@ -225,14 +176,14 @@ describe("/admin/shipping-options", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.response.data.message);
|
||||
});
|
||||
console.log(err.response.data.message)
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
});
|
||||
expect(res.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("succesfully updates a set of requirements because max. subtotal >= min. subtotal", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
requirements: [
|
||||
@@ -247,7 +198,7 @@ describe("/admin/shipping-options", () => {
|
||||
amount: 200,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const res = await api
|
||||
.post(`/admin/shipping-options/test-option-req`, payload, {
|
||||
@@ -256,16 +207,16 @@ describe("/admin/shipping-options", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.response.data.message);
|
||||
});
|
||||
console.log(err.response.data.message)
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.data.shipping_option.requirements[0].amount).toEqual(150);
|
||||
expect(res.data.shipping_option.requirements[1].amount).toEqual(200);
|
||||
});
|
||||
expect(res.status).toEqual(200)
|
||||
expect(res.data.shipping_option.requirements[0].amount).toEqual(150)
|
||||
expect(res.data.shipping_option.requirements[1].amount).toEqual(200)
|
||||
})
|
||||
|
||||
it("fails to updates a set of requirements because max. subtotal <= min. subtotal", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const payload = {
|
||||
requirements: [
|
||||
@@ -280,7 +231,7 @@ describe("/admin/shipping-options", () => {
|
||||
amount: 200,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const res = await api
|
||||
.post(`/admin/shipping-options/test-option-req`, payload, {
|
||||
@@ -289,13 +240,147 @@ describe("/admin/shipping-options", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
return err.response;
|
||||
});
|
||||
return err.response
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(400);
|
||||
expect(res.status).toEqual(400)
|
||||
expect(res.data.message).toEqual(
|
||||
"Max. subtotal must be greater than Min. subtotal"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/shipping-options", () => {
|
||||
let payload
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection)
|
||||
await shippingOptionSeeder(dbConnection)
|
||||
|
||||
const api = useApi()
|
||||
await api.post(
|
||||
`/admin/regions/region`,
|
||||
{
|
||||
fulfillment_providers: ["test-ful"],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const manager = dbConnection.manager
|
||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||
type: "default",
|
||||
})
|
||||
|
||||
payload = {
|
||||
name: "Test option",
|
||||
amount: 100,
|
||||
price_type: "flat_rate",
|
||||
region_id: "region",
|
||||
provider_id: "test-ful",
|
||||
data: {},
|
||||
profile_id: defaultProfile.id,
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("creates a shipping option with requirements", async () => {
|
||||
const api = useApi()
|
||||
payload.requirements = [
|
||||
{
|
||||
type: "max_subtotal",
|
||||
amount: 2,
|
||||
},
|
||||
{
|
||||
type: "min_subtotal",
|
||||
amount: 1,
|
||||
},
|
||||
]
|
||||
|
||||
const res = await api.post(`/admin/shipping-options`, payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
expect(res.data.shipping_option.requirements.length).toEqual(2)
|
||||
})
|
||||
|
||||
it("creates a shipping option with no requirements", async () => {
|
||||
const api = useApi()
|
||||
const res = await api.post(`/admin/shipping-options`, payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
expect(res.data.shipping_option.requirements.length).toEqual(0)
|
||||
})
|
||||
|
||||
it("fails on same requirement types", async () => {
|
||||
const api = useApi()
|
||||
payload.requirements = [
|
||||
{
|
||||
type: "max_subtotal",
|
||||
amount: 2,
|
||||
},
|
||||
{
|
||||
type: "max_subtotal",
|
||||
amount: 1,
|
||||
},
|
||||
]
|
||||
|
||||
try {
|
||||
await api.post(`/admin/shipping-options`, payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
expect(error.response.data.message).toEqual(
|
||||
"Only one requirement of each type is allowed"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it("fails when min_subtotal > max_subtotal", async () => {
|
||||
const api = useApi()
|
||||
payload.requirements = [
|
||||
{
|
||||
type: "max_subtotal",
|
||||
amount: 2,
|
||||
},
|
||||
{
|
||||
type: "min_subtotal",
|
||||
amount: 4,
|
||||
},
|
||||
]
|
||||
|
||||
try {
|
||||
await api.post(`/admin/shipping-options`, payload, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
expect(error.response.data.message).toEqual(
|
||||
"Max. subtotal must be greater than Min. subtotal"
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
const path = require("path");
|
||||
const path = require("path")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server");
|
||||
const { useApi } = require("../../../helpers/use-api");
|
||||
const { initDb, useDb } = require("../../../helpers/use-db");
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const orderSeeder = require("../../helpers/order-seeder");
|
||||
const swapSeeder = require("../../helpers/swap-seeder");
|
||||
const adminSeeder = require("../../helpers/admin-seeder");
|
||||
const orderSeeder = require("../../helpers/order-seeder")
|
||||
const swapSeeder = require("../../helpers/swap-seeder")
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
|
||||
jest.setTimeout(30000);
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/swaps", () => {
|
||||
let medusaProcess;
|
||||
let dbConnection;
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."));
|
||||
dbConnection = await initDb({ cwd });
|
||||
medusaProcess = await setupServer({ cwd });
|
||||
});
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb();
|
||||
await db.shutdown();
|
||||
medusaProcess.kill();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("GET /admin/swaps/:id", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection);
|
||||
await orderSeeder(dbConnection);
|
||||
await swapSeeder(dbConnection);
|
||||
await adminSeeder(dbConnection)
|
||||
await orderSeeder(dbConnection)
|
||||
await swapSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
throw err;
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb();
|
||||
await db.teardown();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("gets a swap with cart and totals", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/swaps/test-swap", {
|
||||
@@ -52,46 +52,46 @@ describe("/admin/swaps", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
expect(response.status).toEqual(200);
|
||||
console.log(err)
|
||||
})
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.swap).toEqual(
|
||||
expect.objectContaining({
|
||||
id: "test-swap",
|
||||
})
|
||||
);
|
||||
)
|
||||
|
||||
expect(response.data.swap.cart).toEqual(
|
||||
expect.objectContaining({
|
||||
id: "test-cart",
|
||||
id: "test-cart-w-swap",
|
||||
shipping_total: 1000,
|
||||
subtotal: 1000,
|
||||
total: 2000,
|
||||
})
|
||||
);
|
||||
expect(response.data.swap.cart).toHaveProperty("discount_total");
|
||||
expect(response.data.swap.cart).toHaveProperty("gift_card_total");
|
||||
});
|
||||
});
|
||||
)
|
||||
expect(response.data.swap.cart).toHaveProperty("discount_total")
|
||||
expect(response.data.swap.cart).toHaveProperty("gift_card_total")
|
||||
})
|
||||
})
|
||||
|
||||
describe("GET /admin/swaps/", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await adminSeeder(dbConnection);
|
||||
await orderSeeder(dbConnection);
|
||||
await swapSeeder(dbConnection);
|
||||
await adminSeeder(dbConnection)
|
||||
await orderSeeder(dbConnection)
|
||||
await swapSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
throw err;
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb();
|
||||
await db.teardown();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("lists all swaps", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/swaps/", {
|
||||
@@ -100,18 +100,18 @@ describe("/admin/swaps", () => {
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data).toHaveProperty("count");
|
||||
expect(response.data.offset).toBe(0);
|
||||
expect(response.data.limit).toBe(50);
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toHaveProperty("count")
|
||||
expect(response.data.offset).toBe(0)
|
||||
expect(response.data.limit).toBe(50)
|
||||
expect(response.data.swaps).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: "test-swap",
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
const path = require("path")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
const productSeeder = require("../../helpers/product-seeder")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/products", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("GET /admin/product-variants", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("lists all product variants", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/variants/", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.variants).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining(
|
||||
{
|
||||
id: "test-variant",
|
||||
},
|
||||
{
|
||||
id: "test-variant_2",
|
||||
},
|
||||
{
|
||||
id: "test-variant_1",
|
||||
}
|
||||
),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("lists all product variants matching a specific sku", async () => {
|
||||
const api = useApi()
|
||||
const response = await api
|
||||
.get("/admin/variants?q=sku2", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.variants.length).toEqual(1)
|
||||
expect(response.data.variants).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
sku: "test-sku2",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("lists all product variants matching a specific variant title", async () => {
|
||||
const api = useApi()
|
||||
const response = await api
|
||||
.get("/admin/variants?q=rank (1)", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.variants.length).toEqual(1)
|
||||
expect(response.data.variants).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "test-variant_1",
|
||||
sku: "test-sku1",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("lists all product variants matching a specific product title", async () => {
|
||||
const api = useApi()
|
||||
const response = await api
|
||||
.get("/admin/variants?q=Test product1", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.variants.length).toEqual(2)
|
||||
expect(response.data.variants).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
product_id: "test-product1",
|
||||
id: "test-variant_3",
|
||||
sku: "test-sku3",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
product_id: "test-product1",
|
||||
id: "test-variant_4",
|
||||
sku: "test-sku4",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`/admin/discounts creates store session correctly 1`] = `
|
||||
Object {
|
||||
"billing_address_id": null,
|
||||
"created_at": Any<String>,
|
||||
"deleted_at": null,
|
||||
"email": "test@testesen.dk",
|
||||
"first_name": "test",
|
||||
"has_account": true,
|
||||
"id": Any<String>,
|
||||
"last_name": "testesen",
|
||||
"metadata": null,
|
||||
"orders": Array [],
|
||||
"phone": "12345678",
|
||||
"updated_at": Any<String>,
|
||||
}
|
||||
`;
|
||||
@@ -8,6 +8,14 @@ Object {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`/store/carts POST /store/carts/:id fails to complete swap cart with items inventory not/partially covered 1`] = `
|
||||
Object {
|
||||
"code": "insufficient_inventory",
|
||||
"message": "Variant with id: test-variant-2 does not have the required inventory",
|
||||
"type": "not_allowed",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`/store/carts POST /store/carts/:id returns early, if cart is already completed 1`] = `
|
||||
Object {
|
||||
"code": "cart_incompatible_state",
|
||||
|
||||
@@ -101,6 +101,7 @@ Object {
|
||||
],
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "draft",
|
||||
"subtitle": null,
|
||||
"tags": Array [
|
||||
Object {
|
||||
|
||||
@@ -58,6 +58,7 @@ Object {
|
||||
"mid_code": null,
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "draft",
|
||||
"subtitle": null,
|
||||
"thumbnail": null,
|
||||
"title": "test product",
|
||||
@@ -91,6 +92,7 @@ Object {
|
||||
"parent_order_id": "test-order",
|
||||
"swap_id": StringMatching /\\^swap_\\*/,
|
||||
},
|
||||
"payment_authorized_at": null,
|
||||
"payment_id": null,
|
||||
"region_id": "test-region",
|
||||
"shipping_address_id": "test-shipping-address",
|
||||
@@ -227,6 +229,7 @@ Object {
|
||||
"mid_code": null,
|
||||
"origin_country": null,
|
||||
"profile_id": StringMatching /\\^sp_\\*/,
|
||||
"status": "draft",
|
||||
"subtitle": null,
|
||||
"thumbnail": null,
|
||||
"title": "test product",
|
||||
@@ -260,6 +263,7 @@ Object {
|
||||
"parent_order_id": "test-order",
|
||||
"swap_id": StringMatching /\\^swap_\\*/,
|
||||
},
|
||||
"payment_authorized_at": null,
|
||||
"payment_id": null,
|
||||
"region_id": "test-region",
|
||||
"shipping_address_id": "test-shipping-address",
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
const path = require("path")
|
||||
const { Region, DiscountRule, Discount } = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
const { exportAllDeclaration } = require("@babel/types")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/admin/auth", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
it("creates store session correctly", async () => {
|
||||
const api = useApi()
|
||||
|
||||
await api
|
||||
.post("/store/customers", {
|
||||
email: "test@testesen.dk",
|
||||
password: "secret_password",
|
||||
first_name: "test",
|
||||
last_name: "testesen",
|
||||
phone: "12345678",
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const response = await api
|
||||
.post("/store/auth", {
|
||||
email: "test@testesen.dk",
|
||||
password: "secret_password",
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer.password_hash).toEqual(undefined)
|
||||
expect(response.data.customer).toMatchSnapshot({
|
||||
id: expect.any(String),
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
first_name: "test",
|
||||
last_name: "testesen",
|
||||
phone: "12345678",
|
||||
email: "test@testesen.dk",
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,155 +1,236 @@
|
||||
const path = require("path");
|
||||
const { Region, LineItem, GiftCard } = require("@medusajs/medusa");
|
||||
const path = require("path")
|
||||
const { Region, LineItem, GiftCard } = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server");
|
||||
const { useApi } = require("../../../helpers/use-api");
|
||||
const { initDb, useDb } = require("../../../helpers/use-db");
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const cartSeeder = require("../../helpers/cart-seeder");
|
||||
const cartSeeder = require("../../helpers/cart-seeder")
|
||||
const swapSeeder = require("../../helpers/swap-seeder")
|
||||
|
||||
jest.setTimeout(30000);
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/store/carts", () => {
|
||||
let medusaProcess;
|
||||
let dbConnection;
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
const doAfterEach = async () => {
|
||||
const db = useDb();
|
||||
return await db.teardown();
|
||||
};
|
||||
const db = useDb()
|
||||
return await db.teardown()
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."));
|
||||
dbConnection = await initDb({ cwd });
|
||||
medusaProcess = await setupServer({ cwd });
|
||||
});
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
try {
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb();
|
||||
await db.shutdown();
|
||||
medusaProcess.kill();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("POST /store/carts", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager;
|
||||
const manager = dbConnection.manager
|
||||
await manager.insert(Region, {
|
||||
id: "region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
});
|
||||
})
|
||||
await manager.query(
|
||||
`UPDATE "country" SET region_id='region' WHERE iso_2 = 'us'`
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await doAfterEach();
|
||||
});
|
||||
await doAfterEach()
|
||||
})
|
||||
|
||||
it("creates a cart", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post("/store/carts");
|
||||
expect(response.status).toEqual(200);
|
||||
const response = await api.post("/store/carts")
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const getRes = await api.post(`/store/carts/${response.data.cart.id}`);
|
||||
expect(getRes.status).toEqual(200);
|
||||
});
|
||||
const getRes = await api.post(`/store/carts/${response.data.cart.id}`)
|
||||
expect(getRes.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("creates a cart with country", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post("/store/carts", {
|
||||
country_code: "us",
|
||||
});
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.cart.shipping_address.country_code).toEqual("us");
|
||||
})
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.cart.shipping_address.country_code).toEqual("us")
|
||||
|
||||
const getRes = await api.post(`/store/carts/${response.data.cart.id}`);
|
||||
expect(getRes.status).toEqual(200);
|
||||
});
|
||||
const getRes = await api.post(`/store/carts/${response.data.cart.id}`)
|
||||
expect(getRes.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("creates a cart with context", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
const response = await api.post("/store/carts", {
|
||||
context: {
|
||||
test_id: "test",
|
||||
},
|
||||
});
|
||||
expect(response.status).toEqual(200);
|
||||
})
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
const getRes = await api.post(`/store/carts/${response.data.cart.id}`);
|
||||
expect(getRes.status).toEqual(200);
|
||||
const getRes = await api.post(`/store/carts/${response.data.cart.id}`)
|
||||
expect(getRes.status).toEqual(200)
|
||||
|
||||
const cart = getRes.data.cart;
|
||||
const cart = getRes.data.cart
|
||||
expect(cart.context).toEqual({
|
||||
ip: "::ffff:127.0.0.1",
|
||||
user_agent: "axios/0.21.1",
|
||||
test_id: "test",
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await cartSeeder(dbConnection);
|
||||
await cartSeeder(dbConnection)
|
||||
await swapSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await doAfterEach();
|
||||
});
|
||||
await doAfterEach()
|
||||
})
|
||||
|
||||
// We were experiencing some issues when having created a cart in a region
|
||||
// containing multiple countries. At this point, the cart does not have a shipping
|
||||
// address. Therefore, on subsequent requests to update the cart, the server
|
||||
// would throw a 500 due to missing shipping address id on insertion.
|
||||
it("updates a cart, that does not have a shipping address", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post("/store/carts", {
|
||||
region_id: "test-region-multiple",
|
||||
})
|
||||
|
||||
const getRes = await api.post(`/store/carts/${response.data.cart.id}`, {
|
||||
region_id: "test-region",
|
||||
})
|
||||
|
||||
expect(getRes.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("fails on apply discount if limit has been reached", async () => {
|
||||
const api = useApi();
|
||||
expect.assertions(2)
|
||||
const api = useApi()
|
||||
|
||||
try {
|
||||
await api.post("/store/carts/test-cart", {
|
||||
discounts: [{ code: "CREATED" }],
|
||||
});
|
||||
})
|
||||
} catch (error) {
|
||||
expect(error.response.status).toEqual(400);
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data.message).toEqual(
|
||||
"Discount has been used maximum allowed times"
|
||||
);
|
||||
)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
it("fails to apply expired discount", async () => {
|
||||
expect.assertions(2)
|
||||
const api = useApi()
|
||||
|
||||
try {
|
||||
await api.post("/store/carts/test-cart", {
|
||||
discounts: [{ code: "EXP_DISC" }],
|
||||
})
|
||||
} catch (error) {
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data.message).toEqual("Discount is expired")
|
||||
}
|
||||
})
|
||||
|
||||
it("fails on discount before start day", async () => {
|
||||
expect.assertions(2)
|
||||
const api = useApi()
|
||||
|
||||
try {
|
||||
await api.post("/store/carts/test-cart", {
|
||||
discounts: [{ code: "PREM_DISC" }],
|
||||
})
|
||||
} catch (error) {
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data.message).toEqual("Discount is not valid yet")
|
||||
}
|
||||
})
|
||||
|
||||
it("fails on apply invalid dynamic discount", async () => {
|
||||
const api = useApi()
|
||||
|
||||
try {
|
||||
await api.post("/store/carts/test-cart", {
|
||||
discounts: [{ code: "INV_DYN_DISC" }],
|
||||
})
|
||||
} catch (error) {
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data.message).toEqual("Discount is expired")
|
||||
}
|
||||
})
|
||||
|
||||
it("Applies dynamic discount to cart correctly", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const cart = await api.post(
|
||||
"/store/carts/test-cart",
|
||||
{
|
||||
discounts: [{ code: "DYN_DISC" }],
|
||||
},
|
||||
{ withCredentials: true }
|
||||
)
|
||||
|
||||
expect(cart.data.cart.shipping_total).toBe(1000)
|
||||
expect(cart.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("updates cart customer id", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post("/store/carts/test-cart", {
|
||||
customer_id: "test-customer-2",
|
||||
});
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
expect(response.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("updates address using string id", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post("/store/carts/test-cart", {
|
||||
billing_address: "test-general-address",
|
||||
shipping_address: "test-general-address",
|
||||
});
|
||||
})
|
||||
|
||||
expect(response.data.cart.shipping_address_id).toEqual(
|
||||
"test-general-address"
|
||||
);
|
||||
)
|
||||
expect(response.data.cart.billing_address_id).toEqual(
|
||||
"test-general-address"
|
||||
);
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
)
|
||||
expect(response.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("updates address", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post("/store/carts/test-cart", {
|
||||
shipping_address: {
|
||||
@@ -160,14 +241,14 @@ describe("/store/carts", () => {
|
||||
country_code: "us",
|
||||
postal_code: "something",
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
expect(response.data.cart.shipping_address.first_name).toEqual("clark");
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
expect(response.data.cart.shipping_address.first_name).toEqual("clark")
|
||||
expect(response.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("adds free shipping to cart then removes it again", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
let cart = await api.post(
|
||||
"/store/carts/test-cart",
|
||||
@@ -175,10 +256,10 @@ describe("/store/carts", () => {
|
||||
discounts: [{ code: "FREE_SHIPPING" }, { code: "CREATED" }],
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
)
|
||||
|
||||
expect(cart.data.cart.shipping_total).toBe(0);
|
||||
expect(cart.status).toEqual(200);
|
||||
expect(cart.data.cart.shipping_total).toBe(0)
|
||||
expect(cart.status).toEqual(200)
|
||||
|
||||
cart = await api.post(
|
||||
"/store/carts/test-cart",
|
||||
@@ -186,68 +267,68 @@ describe("/store/carts", () => {
|
||||
discounts: [{ code: "CREATED" }],
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
)
|
||||
|
||||
expect(cart.data.cart.shipping_total).toBe(1000);
|
||||
expect(cart.status).toEqual(200);
|
||||
});
|
||||
expect(cart.data.cart.shipping_total).toBe(1000)
|
||||
expect(cart.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("complete cart with giftcard total 0", async () => {
|
||||
const manager = dbConnection.manager;
|
||||
const manager = dbConnection.manager
|
||||
await manager.insert(GiftCard, {
|
||||
id: "gift_test",
|
||||
code: "GC_TEST",
|
||||
value: 20000,
|
||||
balance: 20000,
|
||||
region_id: "test-region",
|
||||
});
|
||||
})
|
||||
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
await api.post(`/store/carts/test-cart-3`, {
|
||||
gift_cards: [{ code: "GC_TEST" }],
|
||||
});
|
||||
})
|
||||
|
||||
const getRes = await api
|
||||
.post(`/store/carts/test-cart-3/complete`)
|
||||
.catch((err) => {
|
||||
console.log(err.response.data);
|
||||
});
|
||||
console.log(err.response.data)
|
||||
})
|
||||
|
||||
expect(getRes.status).toEqual(200);
|
||||
expect(getRes.data.type).toEqual("order");
|
||||
});
|
||||
expect(getRes.status).toEqual(200)
|
||||
expect(getRes.data.type).toEqual("order")
|
||||
})
|
||||
|
||||
it("complete cart with items inventory covered", async () => {
|
||||
const api = useApi();
|
||||
const getRes = await api.post(`/store/carts/test-cart-2/complete-cart`);
|
||||
const api = useApi()
|
||||
const getRes = await api.post(`/store/carts/test-cart-2/complete-cart`)
|
||||
|
||||
expect(getRes.status).toEqual(200);
|
||||
expect(getRes.status).toEqual(200)
|
||||
|
||||
const variantRes = await api.get("/store/variants/test-variant");
|
||||
expect(variantRes.data.variant.inventory_quantity).toEqual(0);
|
||||
});
|
||||
const variantRes = await api.get("/store/variants/test-variant")
|
||||
expect(variantRes.data.variant.inventory_quantity).toEqual(0)
|
||||
})
|
||||
|
||||
it("returns early, if cart is already completed", async () => {
|
||||
const manager = dbConnection.manager;
|
||||
const api = useApi();
|
||||
const manager = dbConnection.manager
|
||||
const api = useApi()
|
||||
await manager.query(
|
||||
`UPDATE "cart" SET completed_at=current_timestamp WHERE id = 'test-cart-2'`
|
||||
);
|
||||
)
|
||||
try {
|
||||
await api.post(`/store/carts/test-cart-2/complete-cart`);
|
||||
await api.post(`/store/carts/test-cart-2/complete-cart`)
|
||||
} catch (error) {
|
||||
expect(error.response.data).toMatchSnapshot({
|
||||
code: "not_allowed",
|
||||
message: "Cart has already been completed",
|
||||
code: "cart_incompatible_state",
|
||||
});
|
||||
expect(error.response.status).toEqual(409);
|
||||
})
|
||||
expect(error.response.status).toEqual(409)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
it("fails to complete cart with items inventory not/partially covered", async () => {
|
||||
const manager = dbConnection.manager;
|
||||
const manager = dbConnection.manager
|
||||
|
||||
const li = manager.create(LineItem, {
|
||||
id: "test-item",
|
||||
@@ -258,37 +339,110 @@ describe("/store/carts", () => {
|
||||
quantity: 99,
|
||||
variant_id: "test-variant-2",
|
||||
cart_id: "test-cart-2",
|
||||
});
|
||||
await manager.save(li);
|
||||
})
|
||||
await manager.save(li)
|
||||
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
try {
|
||||
await api.post(`/store/carts/test-cart-2/complete-cart`);
|
||||
await api.post(`/store/carts/test-cart-2/complete-cart`)
|
||||
} catch (e) {
|
||||
expect(e.response.data).toMatchSnapshot({
|
||||
code: "insufficient_inventory",
|
||||
});
|
||||
expect(e.response.status).toBe(409);
|
||||
})
|
||||
expect(e.response.status).toBe(409)
|
||||
}
|
||||
|
||||
//check to see if payment has been cancelled
|
||||
const res = await api.get(`/store/carts/test-cart-2`);
|
||||
expect(res.data.cart.payment.canceled_at).not.toBe(null);
|
||||
});
|
||||
});
|
||||
//check to see if payment has been cancelled and cart is not completed
|
||||
const res = await api.get(`/store/carts/test-cart-2`)
|
||||
expect(res.data.cart.payment.canceled_at).not.toBe(null)
|
||||
expect(res.data.cart.completed_at).toBe(null)
|
||||
})
|
||||
|
||||
it("fails to complete swap cart with items inventory not/partially covered", async () => {
|
||||
const manager = dbConnection.manager
|
||||
|
||||
const li = manager.create(LineItem, {
|
||||
id: "test-item",
|
||||
title: "Line Item",
|
||||
description: "Line Item Desc",
|
||||
thumbnail: "https://test.js/1234",
|
||||
unit_price: 8000,
|
||||
quantity: 99,
|
||||
variant_id: "test-variant-2",
|
||||
cart_id: "swap-cart",
|
||||
})
|
||||
await manager.save(li)
|
||||
|
||||
await manager.query(
|
||||
"UPDATE swap SET cart_id='swap-cart' where id='test-swap'"
|
||||
)
|
||||
|
||||
const api = useApi()
|
||||
|
||||
try {
|
||||
await api.post(`/store/carts/swap-cart/complete-cart`)
|
||||
} catch (e) {
|
||||
expect(e.response.data).toMatchSnapshot({
|
||||
code: "insufficient_inventory",
|
||||
})
|
||||
expect(e.response.status).toBe(409)
|
||||
}
|
||||
|
||||
//check to see if payment has been cancelled and cart is not completed
|
||||
const res = await api.get(`/store/carts/swap-cart`)
|
||||
expect(res.data.cart.payment_authorized_at).toBe(null)
|
||||
expect(res.data.cart.payment.canceled_at).not.toBe(null)
|
||||
})
|
||||
|
||||
it("successfully completes swap cart with items inventory not/partially covered due to backorder flag", async () => {
|
||||
const manager = dbConnection.manager
|
||||
|
||||
const li = manager.create(LineItem, {
|
||||
id: "test-item",
|
||||
title: "Line Item",
|
||||
description: "Line Item Desc",
|
||||
thumbnail: "https://test.js/1234",
|
||||
unit_price: 8000,
|
||||
quantity: 99,
|
||||
variant_id: "test-variant-2",
|
||||
cart_id: "swap-cart",
|
||||
})
|
||||
await manager.save(li)
|
||||
await manager.query(
|
||||
"UPDATE swap SET cart_id='swap-cart' where id='test-swap'"
|
||||
)
|
||||
await manager.query(
|
||||
"UPDATE swap SET allow_backorder=true where id='test-swap'"
|
||||
)
|
||||
await manager.query("DELETE FROM payment where swap_id='test-swap'")
|
||||
|
||||
const api = useApi()
|
||||
|
||||
try {
|
||||
await api.post(`/store/carts/swap-cart/complete-cart`)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
//check to see if payment is authorized and cart is completed
|
||||
const res = await api.get(`/store/carts/swap-cart`)
|
||||
expect(res.data.cart.payment_authorized_at).not.toBe(null)
|
||||
expect(res.data.cart.completed_at).not.toBe(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /store/carts/:id/shipping-methods", () => {
|
||||
beforeEach(async () => {
|
||||
await cartSeeder(dbConnection);
|
||||
});
|
||||
await cartSeeder(dbConnection)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await doAfterEach();
|
||||
});
|
||||
await doAfterEach()
|
||||
})
|
||||
|
||||
it("adds a shipping method to cart", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const cartWithShippingMethod = await api.post(
|
||||
"/store/carts/test-cart/shipping-methods",
|
||||
@@ -296,16 +450,16 @@ describe("/store/carts", () => {
|
||||
option_id: "test-option",
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
)
|
||||
|
||||
expect(cartWithShippingMethod.data.cart.shipping_methods).toContainEqual(
|
||||
expect.objectContaining({ shipping_option_id: "test-option" })
|
||||
);
|
||||
expect(cartWithShippingMethod.status).toEqual(200);
|
||||
});
|
||||
)
|
||||
expect(cartWithShippingMethod.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("adds a giftcard to cart, but ensures discount only applied to discountable items", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
// Add standard line item to cart
|
||||
await api.post(
|
||||
@@ -315,7 +469,7 @@ describe("/store/carts", () => {
|
||||
quantity: 1,
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
)
|
||||
|
||||
// Add gift card to cart
|
||||
await api.post(
|
||||
@@ -325,25 +479,27 @@ describe("/store/carts", () => {
|
||||
quantity: 1,
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
)
|
||||
|
||||
// Add a 10% discount to the cart
|
||||
const cartWithGiftcard = await api.post(
|
||||
"/store/carts/test-cart",
|
||||
{
|
||||
discounts: [{ code: "10PERCENT" }],
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
const cartWithGiftcard = await api
|
||||
.post(
|
||||
"/store/carts/test-cart",
|
||||
{
|
||||
discounts: [{ code: "10PERCENT" }],
|
||||
},
|
||||
{ withCredentials: true }
|
||||
)
|
||||
.catch((err) => console.log(err))
|
||||
|
||||
// Ensure that the discount is only applied to the standard item
|
||||
expect(cartWithGiftcard.data.cart.total).toBe(1900); // 1000 (giftcard) + 900 (standard item with 10% discount)
|
||||
expect(cartWithGiftcard.data.cart.discount_total).toBe(100);
|
||||
expect(cartWithGiftcard.status).toEqual(200);
|
||||
});
|
||||
expect(cartWithGiftcard.data.cart.total).toBe(1900) // 1000 (giftcard) + 900 (standard item with 10% discount)
|
||||
expect(cartWithGiftcard.data.cart.discount_total).toBe(100)
|
||||
expect(cartWithGiftcard.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("adds no more than 1 shipping method per shipping profile", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
const addShippingMethod = async (option_id) => {
|
||||
return await api.post(
|
||||
"/store/carts/test-cart/shipping-methods",
|
||||
@@ -351,17 +507,17 @@ describe("/store/carts", () => {
|
||||
option_id,
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
await addShippingMethod("test-option");
|
||||
await addShippingMethod("test-option")
|
||||
const cartWithAnotherShippingMethod = await addShippingMethod(
|
||||
"test-option-2"
|
||||
);
|
||||
)
|
||||
|
||||
expect(
|
||||
cartWithAnotherShippingMethod.data.cart.shipping_methods.length
|
||||
).toEqual(1);
|
||||
).toEqual(1)
|
||||
expect(
|
||||
cartWithAnotherShippingMethod.data.cart.shipping_methods
|
||||
).toContainEqual(
|
||||
@@ -369,30 +525,30 @@ describe("/store/carts", () => {
|
||||
shipping_option_id: "test-option-2",
|
||||
price: 500,
|
||||
})
|
||||
);
|
||||
expect(cartWithAnotherShippingMethod.status).toEqual(200);
|
||||
});
|
||||
});
|
||||
)
|
||||
expect(cartWithAnotherShippingMethod.status).toEqual(200)
|
||||
})
|
||||
})
|
||||
|
||||
describe("DELETE /store/carts/:id/discounts/:code", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await cartSeeder(dbConnection);
|
||||
await cartSeeder(dbConnection)
|
||||
await dbConnection.manager.query(
|
||||
`INSERT INTO "cart_discounts" (cart_id, discount_id) VALUES ('test-cart', 'free-shipping')`
|
||||
);
|
||||
)
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await doAfterEach();
|
||||
});
|
||||
await doAfterEach()
|
||||
})
|
||||
|
||||
it("removes free shipping and updates shipping total", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const cartWithFreeShipping = await api.post(
|
||||
"/store/carts/test-cart",
|
||||
@@ -400,36 +556,36 @@ describe("/store/carts", () => {
|
||||
discounts: [{ code: "FREE_SHIPPING" }],
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
)
|
||||
|
||||
expect(cartWithFreeShipping.data.cart.shipping_total).toBe(0);
|
||||
expect(cartWithFreeShipping.status).toEqual(200);
|
||||
expect(cartWithFreeShipping.data.cart.shipping_total).toBe(0)
|
||||
expect(cartWithFreeShipping.status).toEqual(200)
|
||||
|
||||
const response = await api.delete(
|
||||
"/store/carts/test-cart/discounts/FREE_SHIPPING"
|
||||
);
|
||||
)
|
||||
|
||||
expect(response.data.cart.shipping_total).toBe(1000);
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
});
|
||||
expect(response.data.cart.shipping_total).toBe(1000)
|
||||
expect(response.status).toEqual(200)
|
||||
})
|
||||
})
|
||||
|
||||
describe("get-cart with session customer", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await cartSeeder(dbConnection);
|
||||
await cartSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await doAfterEach();
|
||||
});
|
||||
await doAfterEach()
|
||||
})
|
||||
|
||||
it("updates empty cart.customer_id on cart retrieval", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
let customer = await api.post(
|
||||
"/store/customers",
|
||||
@@ -440,29 +596,25 @@ describe("/store/carts", () => {
|
||||
last_name: "oli",
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
)
|
||||
|
||||
const cookie = customer.headers["set-cookie"][0];
|
||||
const cookie = customer.headers["set-cookie"][0]
|
||||
|
||||
const cart = await api.post(
|
||||
"/store/carts",
|
||||
{},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
const cart = await api.post("/store/carts", {}, { withCredentials: true })
|
||||
|
||||
const response = await api.get(`/store/carts/${cart.data.cart.id}`, {
|
||||
headers: {
|
||||
cookie,
|
||||
},
|
||||
withCredentials: true,
|
||||
});
|
||||
})
|
||||
|
||||
expect(response.data.cart.customer_id).toEqual(customer.data.customer.id);
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
expect(response.data.cart.customer_id).toEqual(customer.data.customer.id)
|
||||
expect(response.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("updates cart.customer_id on cart retrieval if cart.customer_id differ from session customer", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
let customer = await api.post(
|
||||
"/store/customers",
|
||||
@@ -473,15 +625,15 @@ describe("/store/carts", () => {
|
||||
last_name: "oli",
|
||||
},
|
||||
{ withCredentials: true }
|
||||
);
|
||||
)
|
||||
|
||||
const cookie = customer.headers["set-cookie"][0];
|
||||
const cookie = customer.headers["set-cookie"][0]
|
||||
|
||||
const cart = await api.post("/store/carts");
|
||||
const cart = await api.post("/store/carts")
|
||||
|
||||
const updatedCart = await api.post(`/store/carts/${cart.data.cart.id}`, {
|
||||
customer_id: "test-customer",
|
||||
});
|
||||
})
|
||||
|
||||
const response = await api.get(
|
||||
`/store/carts/${updatedCart.data.cart.id}`,
|
||||
@@ -490,10 +642,10 @@ describe("/store/carts", () => {
|
||||
cookie,
|
||||
},
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
expect(response.data.cart.customer_id).toEqual(customer.data.customer.id);
|
||||
expect(response.status).toEqual(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
expect(response.data.cart.customer_id).toEqual(customer.data.customer.id)
|
||||
expect(response.status).toEqual(200)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,67 +1,67 @@
|
||||
const path = require("path");
|
||||
const { Address, Customer } = require("@medusajs/medusa");
|
||||
const path = require("path")
|
||||
const { Address, Customer } = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server");
|
||||
const { useApi } = require("../../../helpers/use-api");
|
||||
const { initDb, useDb } = require("../../../helpers/use-db");
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const customerSeeder = require("../../helpers/customer-seeder");
|
||||
const customerSeeder = require("../../helpers/customer-seeder")
|
||||
|
||||
jest.setTimeout(30000);
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/store/customers", () => {
|
||||
let medusaProcess;
|
||||
let dbConnection;
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
const doAfterEach = async () => {
|
||||
const db = useDb();
|
||||
await db.teardown();
|
||||
};
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."));
|
||||
dbConnection = await initDb({ cwd });
|
||||
medusaProcess = await setupServer({ cwd });
|
||||
});
|
||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||
dbConnection = await initDb({ cwd })
|
||||
medusaProcess = await setupServer({ cwd })
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
const db = useDb();
|
||||
await db.shutdown();
|
||||
medusaProcess.kill();
|
||||
});
|
||||
const db = useDb()
|
||||
await db.shutdown()
|
||||
medusaProcess.kill()
|
||||
})
|
||||
|
||||
describe("POST /store/customers", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager;
|
||||
const manager = dbConnection.manager
|
||||
await manager.insert(Customer, {
|
||||
id: "test_customer",
|
||||
first_name: "John",
|
||||
last_name: "Deere",
|
||||
email: "john@deere.com",
|
||||
has_account: true,
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await doAfterEach();
|
||||
});
|
||||
await doAfterEach()
|
||||
})
|
||||
|
||||
it("creates a customer", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.post("/store/customers", {
|
||||
first_name: "James",
|
||||
last_name: "Bond",
|
||||
email: "james@bond.com",
|
||||
password: "test",
|
||||
});
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash");
|
||||
});
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash")
|
||||
})
|
||||
|
||||
it("responds 409 on duplicate", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.post("/store/customers", {
|
||||
@@ -70,15 +70,15 @@ describe("/store/customers", () => {
|
||||
email: "john@deere.com",
|
||||
password: "test",
|
||||
})
|
||||
.catch((err) => err.response);
|
||||
.catch((err) => err.response)
|
||||
|
||||
expect(response.status).toEqual(402);
|
||||
});
|
||||
});
|
||||
expect(response.status).toEqual(402)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /store/customers/:id", () => {
|
||||
describe("POST /store/customers/me", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager;
|
||||
const manager = dbConnection.manager
|
||||
await manager.insert(Address, {
|
||||
id: "addr_test",
|
||||
first_name: "String",
|
||||
@@ -88,7 +88,7 @@ describe("/store/customers", () => {
|
||||
postal_code: "1236",
|
||||
province: "ca",
|
||||
country_code: "us",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "test_customer",
|
||||
@@ -98,26 +98,26 @@ describe("/store/customers", () => {
|
||||
password_hash:
|
||||
"c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test"
|
||||
has_account: true,
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await doAfterEach();
|
||||
});
|
||||
await doAfterEach()
|
||||
})
|
||||
|
||||
it("updates a customer", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const authResponse = await api.post("/store/auth", {
|
||||
email: "john@deere.com",
|
||||
password: "test",
|
||||
});
|
||||
})
|
||||
|
||||
const customerId = authResponse.data.customer.id;
|
||||
const [authCookie] = authResponse.headers["set-cookie"][0].split(";");
|
||||
const customerId = authResponse.data.customer.id
|
||||
const [authCookie] = authResponse.headers["set-cookie"][0].split(";")
|
||||
|
||||
const response = await api.post(
|
||||
`/store/customers/${customerId}`,
|
||||
`/store/customers/me`,
|
||||
{
|
||||
password: "test",
|
||||
metadata: { key: "value" },
|
||||
@@ -127,30 +127,30 @@ describe("/store/customers", () => {
|
||||
Cookie: authCookie,
|
||||
},
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash");
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash")
|
||||
expect(response.data.customer).toEqual(
|
||||
expect.objectContaining({
|
||||
metadata: { key: "value" },
|
||||
})
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("updates customer billing address", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const authResponse = await api.post("/store/auth", {
|
||||
email: "john@deere.com",
|
||||
password: "test",
|
||||
});
|
||||
})
|
||||
|
||||
const customerId = authResponse.data.customer.id;
|
||||
const [authCookie] = authResponse.headers["set-cookie"][0].split(";");
|
||||
const customerId = authResponse.data.customer.id
|
||||
const [authCookie] = authResponse.headers["set-cookie"][0].split(";")
|
||||
|
||||
const response = await api.post(
|
||||
`/store/customers/${customerId}`,
|
||||
`/store/customers/me`,
|
||||
{
|
||||
billing_address: {
|
||||
first_name: "test",
|
||||
@@ -167,10 +167,10 @@ describe("/store/customers", () => {
|
||||
Cookie: authCookie,
|
||||
},
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash");
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash")
|
||||
expect(response.data.customer.billing_address).toEqual(
|
||||
expect.objectContaining({
|
||||
first_name: "test",
|
||||
@@ -181,22 +181,22 @@ describe("/store/customers", () => {
|
||||
province: "ca",
|
||||
country_code: "us",
|
||||
})
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
|
||||
it("updates customer billing address with string", async () => {
|
||||
const api = useApi();
|
||||
const api = useApi()
|
||||
|
||||
const authResponse = await api.post("/store/auth", {
|
||||
email: "john@deere.com",
|
||||
password: "test",
|
||||
});
|
||||
})
|
||||
|
||||
const customerId = authResponse.data.customer.id;
|
||||
const [authCookie] = authResponse.headers["set-cookie"][0].split(";");
|
||||
const customerId = authResponse.data.customer.id
|
||||
const [authCookie] = authResponse.headers["set-cookie"][0].split(";")
|
||||
|
||||
const response = await api.post(
|
||||
`/store/customers/${customerId}`,
|
||||
`/store/customers/me`,
|
||||
{
|
||||
billing_address: "addr_test",
|
||||
},
|
||||
@@ -205,10 +205,10 @@ describe("/store/customers", () => {
|
||||
Cookie: authCookie,
|
||||
},
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash");
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.customer).not.toHaveProperty("password_hash")
|
||||
expect(response.data.customer.billing_address).toEqual(
|
||||
expect.objectContaining({
|
||||
first_name: "String",
|
||||
@@ -219,7 +219,7 @@ describe("/store/customers", () => {
|
||||
province: "ca",
|
||||
country_code: "us",
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,6 +5,7 @@ const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
const productSeeder = require("../../helpers/product-seeder")
|
||||
const adminSeeder = require("../../helpers/admin-seeder")
|
||||
jest.setTimeout(30000)
|
||||
describe("/store/products", () => {
|
||||
let medusaProcess
|
||||
@@ -26,6 +27,7 @@ describe("/store/products", () => {
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
await productSeeder(dbConnection)
|
||||
await adminSeeder(dbConnection)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
throw err
|
||||
@@ -261,5 +263,38 @@ describe("/store/products", () => {
|
||||
|
||||
expect(product.variants.some((variant) => variant.options)).toEqual(false)
|
||||
})
|
||||
|
||||
it("lists all published products", async () => {
|
||||
const api = useApi()
|
||||
|
||||
//update test-product status to published
|
||||
await api
|
||||
.post(
|
||||
"/admin/products/test-product",
|
||||
{
|
||||
status: "published",
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
const response = await api.get("/store/products")
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.products).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: "test-product",
|
||||
status: "published",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,16 +26,35 @@ describe("/store/return-reasons", () => {
|
||||
|
||||
describe("GET /store/return-reasons", () => {
|
||||
let rrId;
|
||||
let rrId_1;
|
||||
let rrId_2;
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
const created = dbConnection.manager.create(ReturnReason, {
|
||||
value: "too_big",
|
||||
label: "Too Big",
|
||||
value: "wrong_size",
|
||||
label: "Wrong size",
|
||||
});
|
||||
|
||||
const result = await dbConnection.manager.save(created);
|
||||
rrId = result.id;
|
||||
|
||||
const created_child = dbConnection.manager.create(ReturnReason, {
|
||||
value: "too_big",
|
||||
label: "Too Big",
|
||||
parent_return_reason_id: rrId
|
||||
});
|
||||
|
||||
const result_child = await dbConnection.manager.save(created_child);
|
||||
rrId_1 = result_child.id;
|
||||
|
||||
const created_2 = dbConnection.manager.create(ReturnReason, {
|
||||
value: "too_big_1",
|
||||
label: "Too Big 1",
|
||||
});
|
||||
|
||||
const result_2 = await dbConnection.manager.save(created_2);
|
||||
rrId_2 = result_2.id;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
throw err;
|
||||
@@ -59,7 +78,15 @@ describe("/store/return-reasons", () => {
|
||||
expect(response.data.return_reasons).toEqual([
|
||||
expect.objectContaining({
|
||||
id: rrId,
|
||||
value: "too_big",
|
||||
value: "wrong_size",
|
||||
return_reason_children:[expect.objectContaining({
|
||||
id: rrId_1,
|
||||
value: "too_big",
|
||||
}),]
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: rrId_2,
|
||||
value: "too_big_1",
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ const {
|
||||
Product,
|
||||
ProductVariant,
|
||||
ShippingOption,
|
||||
FulfillmentProvider,
|
||||
LineItem,
|
||||
Discount,
|
||||
DiscountRule,
|
||||
@@ -37,6 +38,8 @@ describe("/store/carts", () => {
|
||||
|
||||
describe("POST /store/returns", () => {
|
||||
let rrId;
|
||||
let rrId_child;
|
||||
let rrResult;
|
||||
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager;
|
||||
@@ -44,13 +47,17 @@ describe("/store/carts", () => {
|
||||
`ALTER SEQUENCE order_display_id_seq RESTART WITH 111`
|
||||
);
|
||||
|
||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||
type: "default",
|
||||
});
|
||||
|
||||
await manager.insert(Region, {
|
||||
id: "region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
});
|
||||
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "cus_1234",
|
||||
email: "test@email.com",
|
||||
@@ -98,10 +105,6 @@ describe("/store/carts", () => {
|
||||
|
||||
await manager.save(ord);
|
||||
|
||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||
type: "default",
|
||||
});
|
||||
|
||||
await manager.insert(Product, {
|
||||
id: "test-product",
|
||||
title: "test product",
|
||||
@@ -147,12 +150,23 @@ describe("/store/carts", () => {
|
||||
});
|
||||
|
||||
const created = dbConnection.manager.create(ReturnReason, {
|
||||
value: "too_big",
|
||||
label: "Too Big",
|
||||
value: "wrong_size",
|
||||
label: "Wrong Size",
|
||||
});
|
||||
const result = await dbConnection.manager.save(created);
|
||||
|
||||
rrResult = result
|
||||
rrId = result.id;
|
||||
|
||||
const created_1 = dbConnection.manager.create(ReturnReason, {
|
||||
value: "too_big",
|
||||
label: "Too Big",
|
||||
parent_return_reason_id: rrId,
|
||||
});
|
||||
|
||||
const result_1 = await dbConnection.manager.save(created_1);
|
||||
|
||||
rrId_child = result_1.id;
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -181,6 +195,59 @@ describe("/store/carts", () => {
|
||||
expect(response.data.return.refund_amount).toEqual(8000);
|
||||
});
|
||||
|
||||
it("failes to create a return with a reason category", async () => {
|
||||
const api = useApi();
|
||||
|
||||
const response = await api
|
||||
.post("/store/returns", {
|
||||
order_id: "order_test",
|
||||
items: [
|
||||
{
|
||||
reason_id: rrId,
|
||||
note: "TOO small",
|
||||
item_id: "test-item",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((err) => {
|
||||
return err.response;
|
||||
});
|
||||
|
||||
expect(response.status).toEqual(400);
|
||||
expect(response.data.message).toEqual('Cannot apply return reason category')
|
||||
|
||||
});
|
||||
|
||||
it("creates a return with reasons", async () => {
|
||||
const api = useApi();
|
||||
|
||||
const response = await api
|
||||
.post("/store/returns", {
|
||||
order_id: "order_test",
|
||||
items: [
|
||||
{
|
||||
reason_id: rrId_child,
|
||||
note: "TOO small",
|
||||
item_id: "test-item",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.response)
|
||||
return err.response;
|
||||
});
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
expect(response.data.return.items).toEqual([
|
||||
expect.objectContaining({
|
||||
reason_id: rrId_child,
|
||||
note: "TOO small",
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it("creates a return with discount and non-discountable item", async () => {
|
||||
const api = useApi();
|
||||
|
||||
@@ -234,32 +301,5 @@ describe("/store/carts", () => {
|
||||
expect(response.data.return.refund_amount).toEqual(7000);
|
||||
});
|
||||
|
||||
it("creates a return with reasons", async () => {
|
||||
const api = useApi();
|
||||
|
||||
const response = await api
|
||||
.post("/store/returns", {
|
||||
order_id: "order_test",
|
||||
items: [
|
||||
{
|
||||
reason_id: rrId,
|
||||
note: "TOO small",
|
||||
item_id: "test-item",
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((err) => {
|
||||
return err.response;
|
||||
});
|
||||
expect(response.status).toEqual(200);
|
||||
|
||||
expect(response.data.return.items).toEqual([
|
||||
expect.objectContaining({
|
||||
reason_id: rrId,
|
||||
note: "TOO small",
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const Scrypt = require("scrypt-kdf");
|
||||
const { User } = require("@medusajs/medusa");
|
||||
const Scrypt = require("scrypt-kdf")
|
||||
const { User } = require("@medusajs/medusa")
|
||||
|
||||
module.exports = async (connection, data = {}) => {
|
||||
const manager = connection.manager;
|
||||
const manager = connection.manager
|
||||
|
||||
const buf = await Scrypt.kdf("secret_password", { logN: 1, r: 1, p: 1 });
|
||||
const password_hash = buf.toString("base64");
|
||||
const buf = await Scrypt.kdf("secret_password", { logN: 1, r: 1, p: 1 })
|
||||
const password_hash = buf.toString("base64")
|
||||
|
||||
await manager.insert(User, {
|
||||
id: "admin_user",
|
||||
@@ -13,5 +13,5 @@ module.exports = async (connection, data = {}) => {
|
||||
api_token: "test_token",
|
||||
password_hash,
|
||||
...data,
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
@@ -14,31 +14,59 @@ const {
|
||||
LineItem,
|
||||
Payment,
|
||||
PaymentSession,
|
||||
} = require("@medusajs/medusa");
|
||||
} = require("@medusajs/medusa")
|
||||
|
||||
module.exports = async (connection, data = {}) => {
|
||||
const manager = connection.manager;
|
||||
const yesterday = ((today) => new Date(today.setDate(today.getDate() - 1)))(
|
||||
new Date()
|
||||
)
|
||||
const tomorrow = ((today) => new Date(today.setDate(today.getDate() + 1)))(
|
||||
new Date()
|
||||
)
|
||||
const tenDaysAgo = ((today) => new Date(today.setDate(today.getDate() - 10)))(
|
||||
new Date()
|
||||
)
|
||||
const tenDaysFromToday = ((today) =>
|
||||
new Date(today.setDate(today.getDate() + 10)))(new Date())
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||
type: "default",
|
||||
});
|
||||
})
|
||||
|
||||
const gcProfile = await manager.findOne(ShippingProfile, {
|
||||
type: "gift_card",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Address, {
|
||||
id: "test-general-address",
|
||||
first_name: "superman",
|
||||
country_code: "us",
|
||||
});
|
||||
})
|
||||
|
||||
const r = manager.create(Region, {
|
||||
id: "test-region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
});
|
||||
})
|
||||
|
||||
// Region with multiple countries
|
||||
const regionWithMultipleCoutries = manager.create(Region, {
|
||||
id: "test-region-multiple",
|
||||
name: "Test Region",
|
||||
currency_code: "eur",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
await manager.save(regionWithMultipleCoutries)
|
||||
await manager.query(
|
||||
`UPDATE "country" SET region_id='test-region-multiple' WHERE iso_2 = 'no'`
|
||||
)
|
||||
await manager.query(
|
||||
`UPDATE "country" SET region_id='test-region-multiple' WHERE iso_2 = 'dk'`
|
||||
)
|
||||
|
||||
const freeRule = manager.create(DiscountRule, {
|
||||
id: "free-shipping-rule",
|
||||
@@ -46,18 +74,18 @@ module.exports = async (connection, data = {}) => {
|
||||
type: "free_shipping",
|
||||
value: 100,
|
||||
allocation: "total",
|
||||
});
|
||||
})
|
||||
|
||||
const freeDisc = manager.create(Discount, {
|
||||
id: "free-shipping",
|
||||
code: "FREE_SHIPPING",
|
||||
is_dynamic: false,
|
||||
is_disabled: false,
|
||||
});
|
||||
})
|
||||
|
||||
freeDisc.regions = [r];
|
||||
freeDisc.rule = freeRule;
|
||||
await manager.save(freeDisc);
|
||||
freeDisc.regions = [r]
|
||||
freeDisc.rule = freeRule
|
||||
await manager.save(freeDisc)
|
||||
|
||||
const tenPercentRule = manager.create(DiscountRule, {
|
||||
id: "tenpercent-rule",
|
||||
@@ -65,25 +93,27 @@ module.exports = async (connection, data = {}) => {
|
||||
type: "percentage",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
});
|
||||
})
|
||||
|
||||
const tenPercent = manager.create(Discount, {
|
||||
id: "10Percent",
|
||||
code: "10PERCENT",
|
||||
is_dynamic: false,
|
||||
is_disabled: false,
|
||||
});
|
||||
starts_at: tenDaysAgo,
|
||||
ends_at: tenDaysFromToday,
|
||||
})
|
||||
|
||||
tenPercent.regions = [r];
|
||||
tenPercent.rule = tenPercentRule;
|
||||
await manager.save(tenPercent);
|
||||
tenPercent.regions = [r]
|
||||
tenPercent.rule = tenPercentRule
|
||||
await manager.save(tenPercent)
|
||||
|
||||
const d = await manager.create(Discount, {
|
||||
id: "test-discount",
|
||||
code: "CREATED",
|
||||
is_dynamic: false,
|
||||
is_disabled: false,
|
||||
});
|
||||
})
|
||||
|
||||
const dr = await manager.create(DiscountRule, {
|
||||
id: "test-discount-rule",
|
||||
@@ -91,31 +121,117 @@ module.exports = async (connection, data = {}) => {
|
||||
type: "fixed",
|
||||
value: 10000,
|
||||
allocation: "total",
|
||||
});
|
||||
})
|
||||
|
||||
d.rule = dr;
|
||||
d.regions = [r];
|
||||
d.rule = dr
|
||||
d.regions = [r]
|
||||
|
||||
await manager.save(d);
|
||||
await manager.save(d)
|
||||
|
||||
const expiredRule = manager.create(DiscountRule, {
|
||||
id: "expiredRule",
|
||||
description: "expired rule",
|
||||
type: "fixed",
|
||||
value: 100,
|
||||
allocation: "total",
|
||||
})
|
||||
|
||||
const expiredDisc = manager.create(Discount, {
|
||||
id: "expiredDisc",
|
||||
code: "EXP_DISC",
|
||||
is_dynamic: false,
|
||||
is_disabled: false,
|
||||
starts_at: tenDaysAgo,
|
||||
ends_at: yesterday,
|
||||
})
|
||||
|
||||
expiredDisc.regions = [r]
|
||||
expiredDisc.rule = expiredRule
|
||||
await manager.save(expiredDisc)
|
||||
|
||||
const prematureRule = manager.create(DiscountRule, {
|
||||
id: "prematureRule",
|
||||
description: "premature rule",
|
||||
type: "fixed",
|
||||
value: 100,
|
||||
allocation: "total",
|
||||
})
|
||||
|
||||
const prematureDiscount = manager.create(Discount, {
|
||||
id: "prematureDiscount",
|
||||
code: "PREM_DISC",
|
||||
is_dynamic: false,
|
||||
is_disabled: false,
|
||||
starts_at: tomorrow,
|
||||
ends_at: tenDaysFromToday,
|
||||
})
|
||||
|
||||
prematureDiscount.regions = [r]
|
||||
prematureDiscount.rule = prematureRule
|
||||
await manager.save(prematureDiscount)
|
||||
|
||||
const invalidDynamicRule = manager.create(DiscountRule, {
|
||||
id: "invalidDynamicRule",
|
||||
description: "invalidDynamic rule",
|
||||
type: "fixed",
|
||||
value: 100,
|
||||
allocation: "total",
|
||||
})
|
||||
|
||||
const invalidDynamicDiscount = manager.create(Discount, {
|
||||
id: "invalidDynamicDiscount",
|
||||
code: "INV_DYN_DISC",
|
||||
is_dynamic: true,
|
||||
is_disabled: false,
|
||||
starts_at: tenDaysAgo,
|
||||
ends_at: tenDaysFromToday,
|
||||
valid_duration: "P1D", // one day
|
||||
})
|
||||
|
||||
invalidDynamicDiscount.regions = [r]
|
||||
invalidDynamicDiscount.rule = invalidDynamicRule
|
||||
await manager.save(invalidDynamicDiscount)
|
||||
|
||||
const DynamicRule = manager.create(DiscountRule, {
|
||||
id: "DynamicRule",
|
||||
description: "Dynamic rule",
|
||||
type: "fixed",
|
||||
value: 10000,
|
||||
allocation: "total",
|
||||
})
|
||||
|
||||
const DynamicDiscount = manager.create(Discount, {
|
||||
id: "DynamicDiscount",
|
||||
code: "DYN_DISC",
|
||||
is_dynamic: true,
|
||||
is_disabled: false,
|
||||
starts_at: tenDaysAgo,
|
||||
ends_at: tenDaysFromToday,
|
||||
valid_duration: "P1M", //one month
|
||||
})
|
||||
|
||||
DynamicDiscount.regions = [r]
|
||||
DynamicDiscount.rule = DynamicRule
|
||||
await manager.save(DynamicDiscount)
|
||||
|
||||
await manager.query(
|
||||
`UPDATE "country" SET region_id='test-region' WHERE iso_2 = 'us'`
|
||||
);
|
||||
)
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "test-customer",
|
||||
email: "test@email.com",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "test-customer-2",
|
||||
email: "test-2@email.com",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "some-customer",
|
||||
email: "some-customer@email.com",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(ShippingOption, {
|
||||
id: "test-option",
|
||||
@@ -126,7 +242,7 @@ module.exports = async (connection, data = {}) => {
|
||||
price_type: "flat_rate",
|
||||
amount: 1000,
|
||||
data: {},
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(ShippingOption, {
|
||||
id: "gc-option",
|
||||
@@ -137,7 +253,7 @@ module.exports = async (connection, data = {}) => {
|
||||
price_type: "flat_rate",
|
||||
amount: 0,
|
||||
data: {},
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(ShippingOption, {
|
||||
id: "test-option-2",
|
||||
@@ -148,7 +264,7 @@ module.exports = async (connection, data = {}) => {
|
||||
price_type: "flat_rate",
|
||||
amount: 500,
|
||||
data: {},
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Product, {
|
||||
id: "giftcard-product",
|
||||
@@ -157,7 +273,7 @@ module.exports = async (connection, data = {}) => {
|
||||
discountable: false,
|
||||
profile_id: gcProfile.id,
|
||||
options: [{ id: "denom", title: "Denomination" }],
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(ProductVariant, {
|
||||
id: "giftcard-denom",
|
||||
@@ -170,14 +286,14 @@ module.exports = async (connection, data = {}) => {
|
||||
value: "1000",
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Product, {
|
||||
id: "test-product",
|
||||
title: "test product",
|
||||
profile_id: defaultProfile.id,
|
||||
options: [{ id: "test-option", title: "Size" }],
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(ProductVariant, {
|
||||
id: "test-variant",
|
||||
@@ -190,7 +306,7 @@ module.exports = async (connection, data = {}) => {
|
||||
value: "Size",
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(ProductVariant, {
|
||||
id: "test-variant-2",
|
||||
@@ -203,31 +319,31 @@ module.exports = async (connection, data = {}) => {
|
||||
value: "Size",
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
|
||||
const ma = manager.create(MoneyAmount, {
|
||||
variant_id: "test-variant",
|
||||
currency_code: "usd",
|
||||
amount: 1000,
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(ma);
|
||||
await manager.save(ma)
|
||||
|
||||
const ma2 = manager.create(MoneyAmount, {
|
||||
variant_id: "test-variant-2",
|
||||
currency_code: "usd",
|
||||
amount: 8000,
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(ma2);
|
||||
await manager.save(ma2)
|
||||
|
||||
const ma3 = manager.create(MoneyAmount, {
|
||||
variant_id: "giftcard-denom",
|
||||
currency_code: "usd",
|
||||
amount: 1000,
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(ma3);
|
||||
await manager.save(ma3)
|
||||
|
||||
const cart = manager.create(Cart, {
|
||||
id: "test-cart",
|
||||
@@ -241,9 +357,9 @@ module.exports = async (connection, data = {}) => {
|
||||
region_id: "test-region",
|
||||
currency_code: "usd",
|
||||
items: [],
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(cart);
|
||||
await manager.save(cart)
|
||||
|
||||
const cart2 = manager.create(Cart, {
|
||||
id: "test-cart-2",
|
||||
@@ -258,7 +374,26 @@ module.exports = async (connection, data = {}) => {
|
||||
currency_code: "usd",
|
||||
completed_at: null,
|
||||
items: [],
|
||||
});
|
||||
})
|
||||
|
||||
const swapCart = manager.create(Cart, {
|
||||
id: "swap-cart",
|
||||
type: "swap",
|
||||
customer_id: "some-customer",
|
||||
email: "some-customer@email.com",
|
||||
shipping_address: {
|
||||
id: "test-shipping-address",
|
||||
first_name: "lebron",
|
||||
country_code: "us",
|
||||
},
|
||||
region_id: "test-region",
|
||||
currency_code: "usd",
|
||||
completed_at: null,
|
||||
items: [],
|
||||
metadata: {
|
||||
swap_id: "test-swap",
|
||||
},
|
||||
})
|
||||
|
||||
const pay = manager.create(Payment, {
|
||||
id: "test-payment",
|
||||
@@ -267,13 +402,30 @@ module.exports = async (connection, data = {}) => {
|
||||
amount_refunded: 0,
|
||||
provider_id: "test-pay",
|
||||
data: {},
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(pay);
|
||||
await manager.save(pay)
|
||||
|
||||
cart2.payment = pay;
|
||||
cart2.payment = pay
|
||||
|
||||
await manager.save(cart2);
|
||||
await manager.save(cart2)
|
||||
const swapPay = manager.create(Payment, {
|
||||
id: "test-swap-payment",
|
||||
amount: 10000,
|
||||
currency_code: "usd",
|
||||
amount_refunded: 0,
|
||||
provider_id: "test-pay",
|
||||
data: {},
|
||||
})
|
||||
|
||||
await manager.save(pay)
|
||||
await manager.save(swapPay)
|
||||
|
||||
cart2.payment = pay
|
||||
swapCart.payment = swapPay
|
||||
|
||||
await manager.save(cart2)
|
||||
await manager.save(swapCart)
|
||||
|
||||
await manager.insert(PaymentSession, {
|
||||
id: "test-session",
|
||||
@@ -282,7 +434,16 @@ module.exports = async (connection, data = {}) => {
|
||||
is_selected: true,
|
||||
data: {},
|
||||
status: "authorized",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(PaymentSession, {
|
||||
id: "test-swap-session",
|
||||
cart_id: "swap-cart",
|
||||
provider_id: "test-pay",
|
||||
is_selected: true,
|
||||
data: {},
|
||||
status: "authorized",
|
||||
})
|
||||
|
||||
await manager.insert(ShippingMethod, {
|
||||
id: "test-method",
|
||||
@@ -290,7 +451,7 @@ module.exports = async (connection, data = {}) => {
|
||||
cart_id: "test-cart",
|
||||
price: 1000,
|
||||
data: {},
|
||||
});
|
||||
})
|
||||
|
||||
const li = manager.create(LineItem, {
|
||||
id: "test-item",
|
||||
@@ -301,8 +462,8 @@ module.exports = async (connection, data = {}) => {
|
||||
quantity: 1,
|
||||
variant_id: "test-variant",
|
||||
cart_id: "test-cart-2",
|
||||
});
|
||||
await manager.save(li);
|
||||
})
|
||||
await manager.save(li)
|
||||
|
||||
const cart3 = manager.create(Cart, {
|
||||
id: "test-cart-3",
|
||||
@@ -317,8 +478,8 @@ module.exports = async (connection, data = {}) => {
|
||||
currency_code: "usd",
|
||||
completed_at: null,
|
||||
items: [],
|
||||
});
|
||||
await manager.save(cart3);
|
||||
})
|
||||
await manager.save(cart3)
|
||||
|
||||
await manager.insert(ShippingMethod, {
|
||||
id: "test-method-2",
|
||||
@@ -326,7 +487,7 @@ module.exports = async (connection, data = {}) => {
|
||||
cart_id: "test-cart-3",
|
||||
price: 0,
|
||||
data: {},
|
||||
});
|
||||
})
|
||||
|
||||
const li2 = manager.create(LineItem, {
|
||||
id: "test-item-2",
|
||||
@@ -337,6 +498,6 @@ module.exports = async (connection, data = {}) => {
|
||||
quantity: 1,
|
||||
variant_id: "test-variant",
|
||||
cart_id: "test-cart-3",
|
||||
});
|
||||
await manager.save(li2);
|
||||
};
|
||||
})
|
||||
await manager.save(li2)
|
||||
}
|
||||
|
||||
@@ -1,27 +1,33 @@
|
||||
const { Customer, Address } = require("@medusajs/medusa");
|
||||
const { Customer, Address } = require("@medusajs/medusa")
|
||||
|
||||
module.exports = async (connection, data = {}) => {
|
||||
const manager = connection.manager;
|
||||
const manager = connection.manager
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "test-customer-1",
|
||||
email: "test1@email.com",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "test-customer-2",
|
||||
email: "test2@email.com",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "test-customer-3",
|
||||
email: "test3@email.com",
|
||||
});
|
||||
})
|
||||
|
||||
await manager.insert(Customer, {
|
||||
id: "test-customer-has_account",
|
||||
email: "test4@email.com",
|
||||
has_account: true,
|
||||
})
|
||||
|
||||
await manager.insert(Address, {
|
||||
id: "test-address",
|
||||
first_name: "Lebron",
|
||||
last_name: "James",
|
||||
customer_id: "test-customer-1",
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
const {
|
||||
Region,
|
||||
ShippingProfile,
|
||||
ShippingOption,
|
||||
ShippingOptionRequirement,
|
||||
} = require("@medusajs/medusa")
|
||||
|
||||
module.exports = async (connection, data = {}) => {
|
||||
const manager = connection.manager
|
||||
|
||||
await manager.insert(Region, {
|
||||
id: "region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
|
||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||
type: "default",
|
||||
})
|
||||
|
||||
await manager.insert(ShippingOption, {
|
||||
id: "test-out",
|
||||
name: "Test out",
|
||||
profile_id: defaultProfile.id,
|
||||
region_id: "region",
|
||||
provider_id: "test-ful",
|
||||
data: {},
|
||||
price_type: "flat_rate",
|
||||
amount: 2000,
|
||||
is_return: false,
|
||||
})
|
||||
|
||||
await manager.insert(ShippingOption, {
|
||||
id: "test-option-req",
|
||||
name: "With req",
|
||||
profile_id: defaultProfile.id,
|
||||
region_id: "region",
|
||||
provider_id: "test-ful",
|
||||
data: {},
|
||||
price_type: "flat_rate",
|
||||
amount: 2000,
|
||||
is_return: false,
|
||||
})
|
||||
|
||||
await manager.insert(ShippingOptionRequirement, {
|
||||
id: "option-req",
|
||||
shipping_option_id: "test-option-req",
|
||||
type: "min_subtotal",
|
||||
amount: 5,
|
||||
})
|
||||
|
||||
await manager.insert(ShippingOptionRequirement, {
|
||||
id: "option-req-2",
|
||||
shipping_option_id: "test-option-req",
|
||||
type: "max_subtotal",
|
||||
amount: 10,
|
||||
})
|
||||
}
|
||||
@@ -14,10 +14,10 @@ const {
|
||||
Swap,
|
||||
Cart,
|
||||
Return,
|
||||
} = require("@medusajs/medusa");
|
||||
} = require("@medusajs/medusa")
|
||||
|
||||
module.exports = async (connection, data = {}) => {
|
||||
const manager = connection.manager;
|
||||
const manager = connection.manager
|
||||
|
||||
let orderWithSwap = manager.create(Order, {
|
||||
id: "order-with-swap",
|
||||
@@ -50,12 +50,12 @@ module.exports = async (connection, data = {}) => {
|
||||
],
|
||||
items: [],
|
||||
...data,
|
||||
});
|
||||
})
|
||||
|
||||
orderWithSwap = await manager.save(orderWithSwap);
|
||||
orderWithSwap = await manager.save(orderWithSwap)
|
||||
|
||||
const cart = manager.create(Cart, {
|
||||
id: "test-cart",
|
||||
id: "test-cart-w-swap",
|
||||
customer_id: "test-customer",
|
||||
email: "test-customer@email.com",
|
||||
shipping_address_id: "test-shipping-address",
|
||||
@@ -66,16 +66,16 @@ module.exports = async (connection, data = {}) => {
|
||||
swap_id: "test-swap",
|
||||
parent_order_id: orderWithSwap.id,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(cart);
|
||||
await manager.save(cart)
|
||||
|
||||
const swap = manager.create(Swap, {
|
||||
id: "test-swap",
|
||||
order_id: "order-with-swap",
|
||||
payment_status: "captured",
|
||||
fulfillment_status: "fulfilled",
|
||||
cart_id: "test-cart",
|
||||
cart_id: "test-cart-w-swap",
|
||||
payment: {
|
||||
id: "test-payment-swap",
|
||||
amount: 10000,
|
||||
@@ -94,12 +94,12 @@ module.exports = async (connection, data = {}) => {
|
||||
unit_price: 9000,
|
||||
quantity: 1,
|
||||
variant_id: "test-variant-2",
|
||||
cart_id: "test-cart",
|
||||
cart_id: "test-cart-w-swap",
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(swap);
|
||||
await manager.save(swap)
|
||||
|
||||
const cartTemplate = async (cartId) => {
|
||||
const cart = manager.create(Cart, {
|
||||
@@ -176,9 +176,9 @@ module.exports = async (connection, data = {}) => {
|
||||
variant_id: "test-variant",
|
||||
order_id: orderWithSwap.id,
|
||||
cart_id: cart.id,
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(li);
|
||||
await manager.save(li)
|
||||
|
||||
const li2 = manager.create(LineItem, {
|
||||
id: "test-item-many",
|
||||
@@ -190,34 +190,33 @@ module.exports = async (connection, data = {}) => {
|
||||
quantity: 4,
|
||||
variant_id: "test-variant",
|
||||
order_id: orderWithSwap.id,
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(li2);
|
||||
await manager.save(li2)
|
||||
|
||||
const swapReturn = await manager.create(Return, {
|
||||
swap_id: swap.id,
|
||||
order_id: orderWithSwap.id,
|
||||
item_id: li.id,
|
||||
refund_amount: li.quantity * li.unit_price,
|
||||
// shipping_method_id: ,
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(swapReturn);
|
||||
await manager.save(swapReturn)
|
||||
|
||||
const return_item1 = manager.create(LineItem, {
|
||||
...li,
|
||||
unit_price: -1 * li.unit_price,
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(return_item1);
|
||||
await manager.save(return_item1)
|
||||
|
||||
await manager.insert(ShippingMethod, {
|
||||
id: "another-test-method",
|
||||
shipping_option_id: "test-option",
|
||||
cart_id: "test-cart",
|
||||
cart_id: "test-cart-w-swap",
|
||||
price: 1000,
|
||||
data: {},
|
||||
});
|
||||
})
|
||||
|
||||
const swapOnSwap = manager.create(Swap, {
|
||||
id: "swap-on-swap",
|
||||
@@ -255,9 +254,9 @@ module.exports = async (connection, data = {}) => {
|
||||
variant_id: "test-variant",
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
|
||||
await manager.save(swapOnSwap);
|
||||
await manager.save(swapOnSwap)
|
||||
|
||||
await manager.insert(ShippingMethod, {
|
||||
id: "test-method-swap-order",
|
||||
@@ -265,5 +264,5 @@ module.exports = async (connection, data = {}) => {
|
||||
order_id: "order-with-swap",
|
||||
price: 1000,
|
||||
data: {},
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,15 +8,15 @@
|
||||
"build": "babel src -d dist --extensions \".ts,.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@medusajs/medusa": "1.1.40-dev-1631178030541",
|
||||
"medusa-interfaces": "1.1.21",
|
||||
"@medusajs/medusa": "1.1.40-dev-1631630701835",
|
||||
"medusa-interfaces": "1.1.21-dev-1631630701835",
|
||||
"typeorm": "^0.2.31"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.12.10",
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/node": "^7.12.10",
|
||||
"babel-preset-medusa-package": "1.1.13",
|
||||
"babel-preset-medusa-package": "1.1.13-dev-1631630701835",
|
||||
"jest": "^26.6.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1223,10 +1223,10 @@
|
||||
"@types/yargs" "^15.0.0"
|
||||
chalk "^4.0.0"
|
||||
|
||||
"@medusajs/medusa-cli@^1.1.16":
|
||||
version "1.1.16"
|
||||
resolved "http://localhost:4873/@medusajs%2fmedusa-cli/-/medusa-cli-1.1.16.tgz#3ddcd5b16388a387c430116b962bb27a933ee85e"
|
||||
integrity sha512-QvE7IYkR3NFiy4seZklfX+Xs/dJannVLbKfxLQbxCV2Sso3ZtJbSJt1BpTUwDxYjOFWXyTxRRjO1kEnA1yqCBA==
|
||||
"@medusajs/medusa-cli@1.1.16-dev-1631630701835":
|
||||
version "1.1.16-dev-1631630701835"
|
||||
resolved "http://localhost:4873/@medusajs%2fmedusa-cli/-/medusa-cli-1.1.16-dev-1631630701835.tgz#7fcb95cb9a45e0367cc5becfff7f5d1533b46b5f"
|
||||
integrity sha512-UomtR8B1lBFDb3h1y060fOcWcZi812Jwt8Kgjxqtpn+aRj6Bu7+I3WJGHBVSx4VnUBINSYbtiQMpEwqVGTCKnw==
|
||||
dependencies:
|
||||
"@babel/polyfill" "^7.8.7"
|
||||
"@babel/runtime" "^7.9.6"
|
||||
@@ -1244,8 +1244,8 @@
|
||||
is-valid-path "^0.1.1"
|
||||
joi-objectid "^3.0.1"
|
||||
meant "^1.0.1"
|
||||
medusa-core-utils "^0.1.27"
|
||||
medusa-telemetry "^0.0.3"
|
||||
medusa-core-utils "1.1.20-dev-1631630701835"
|
||||
medusa-telemetry "0.0.3-dev-1631630701835"
|
||||
netrc-parser "^3.1.6"
|
||||
open "^8.0.6"
|
||||
ora "^5.4.1"
|
||||
@@ -1259,13 +1259,13 @@
|
||||
winston "^3.3.3"
|
||||
yargs "^15.3.1"
|
||||
|
||||
"@medusajs/medusa@1.1.40-dev-1631178030541":
|
||||
version "1.1.40-dev-1631178030541"
|
||||
resolved "http://localhost:4873/@medusajs%2fmedusa/-/medusa-1.1.40-dev-1631178030541.tgz#d693bdd9461e2281d387b26ad54b72c30e53218b"
|
||||
integrity sha512-hhh67dltQ9dZYXBzA8FB8NrCaQ8bdALEm48t7oZ0J+GueG0fa6kcjU7Ud0uyy1vdov2zN4NOZmxGpcAw3n4alg==
|
||||
"@medusajs/medusa@1.1.40-dev-1631630701835":
|
||||
version "1.1.40-dev-1631630701835"
|
||||
resolved "http://localhost:4873/@medusajs%2fmedusa/-/medusa-1.1.40-dev-1631630701835.tgz#fa67ceda5887fd31196b3bcfd3115a9e02d68448"
|
||||
integrity sha512-svPsKonuBrwRgtYod7U7ho9bN84K7N/QorMJG9+wklEO4jp6zXG+U5DQcfVAKQ00cHHe50OcnfX1ZS0kVNovYw==
|
||||
dependencies:
|
||||
"@hapi/joi" "^16.1.8"
|
||||
"@medusajs/medusa-cli" "^1.1.16"
|
||||
"@medusajs/medusa-cli" "1.1.16-dev-1631630701835"
|
||||
"@types/lodash" "^4.14.168"
|
||||
awilix "^4.2.3"
|
||||
body-parser "^1.19.0"
|
||||
@@ -1286,8 +1286,8 @@
|
||||
joi "^17.3.0"
|
||||
joi-objectid "^3.0.1"
|
||||
jsonwebtoken "^8.5.1"
|
||||
medusa-core-utils "^1.1.20"
|
||||
medusa-test-utils "^1.1.23"
|
||||
medusa-core-utils "1.1.20-dev-1631630701835"
|
||||
medusa-test-utils "1.1.23-dev-1631630701835"
|
||||
morgan "^1.9.1"
|
||||
multer "^1.4.2"
|
||||
passport "^0.4.0"
|
||||
@@ -1932,10 +1932,10 @@ babel-preset-jest@^26.6.2:
|
||||
babel-plugin-jest-hoist "^26.6.2"
|
||||
babel-preset-current-node-syntax "^1.0.0"
|
||||
|
||||
babel-preset-medusa-package@1.1.13:
|
||||
version "1.1.13"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.13.tgz#9dc4e64e08436fb7b3536cef0f363a535e126474"
|
||||
integrity sha512-Q9t06udxwMnfwyx7gyxoUKiZj/dtYSSXBtQ+K4ntY1hzMhOK2hBBInuiTgnLQS1cxc4j+FN2oYYPCpspX/acaw==
|
||||
babel-preset-medusa-package@1.1.13-dev-1631630701835:
|
||||
version "1.1.13-dev-1631630701835"
|
||||
resolved "http://localhost:4873/babel-preset-medusa-package/-/babel-preset-medusa-package-1.1.13-dev-1631630701835.tgz#5b66b3738e4904e31b2db30a6ea8e68eb0f8f641"
|
||||
integrity sha512-V7sXlktlvEON7FLhxe+Y3NVe8l8DQyB5oJTryG4Bhw8y1AaUFOiQ5Vat3XuoL3qRcUSVMGL4VHw0m0O78t0PuA==
|
||||
dependencies:
|
||||
"@babel/plugin-proposal-class-properties" "^7.12.1"
|
||||
"@babel/plugin-proposal-decorators" "^7.12.1"
|
||||
@@ -2867,6 +2867,11 @@ dir-glob@^3.0.1:
|
||||
dependencies:
|
||||
path-type "^4.0.0"
|
||||
|
||||
dom-walk@^0.1.0:
|
||||
version "0.1.2"
|
||||
resolved "http://localhost:4873/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
|
||||
integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==
|
||||
|
||||
domexception@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
|
||||
@@ -3588,6 +3593,14 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, gl
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
global@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "http://localhost:4873/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
|
||||
integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
|
||||
dependencies:
|
||||
min-document "^2.19.0"
|
||||
process "^0.11.10"
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||
@@ -5091,50 +5104,43 @@ media-typer@0.3.0:
|
||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
|
||||
|
||||
medusa-core-utils@^0.1.27:
|
||||
version "0.1.39"
|
||||
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-0.1.39.tgz#d57816c9bd43f9a92883650c1e66add1665291df"
|
||||
integrity sha512-R8+U1ile7if+nR6Cjh5exunx0ETV0OfkWUUBUpz1KmHSDv0V0CcvQqU9lcZesPFDEbu3Y2iEjsCqidVA4nG2nQ==
|
||||
dependencies:
|
||||
"@hapi/joi" "^16.1.8"
|
||||
joi-objectid "^3.0.1"
|
||||
|
||||
medusa-core-utils@^1.1.20:
|
||||
version "1.1.20"
|
||||
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.1.20.tgz#676c0dc863a206b80cc53299a984c532d07df65f"
|
||||
integrity sha512-gf+/L5eeqHea3xgjwD7YZEzfUGlxbjfvaeiiGWi3Wfu0dLa+G1B4S0TsX+upR+oVeWPmk66VMqWC80h3e4csqw==
|
||||
medusa-core-utils@1.1.20-dev-1631630701835:
|
||||
version "1.1.20-dev-1631630701835"
|
||||
resolved "http://localhost:4873/medusa-core-utils/-/medusa-core-utils-1.1.20-dev-1631630701835.tgz#1fa7ccd2551b7891127d4f07f708029c585f4ea8"
|
||||
integrity sha512-KKBo6W1QI47Ig3KMV4UXQnQN5JilMfjR6Cx7hDNj4frJoNiWa/YKDYqUr6SmY2+iJtKetnLkrKaPsDyyhZrxcw==
|
||||
dependencies:
|
||||
joi "^17.3.0"
|
||||
joi-objectid "^3.0.1"
|
||||
|
||||
medusa-interfaces@1.1.21:
|
||||
version "1.1.21"
|
||||
resolved "https://registry.yarnpkg.com/medusa-interfaces/-/medusa-interfaces-1.1.21.tgz#ca86808e939b7ecc21a6d316008a4e41f163619f"
|
||||
integrity sha512-mlHHoMIOFBc+Exs+uVIQsfeEP2C1Pi6IZHcpbm7O00tYBdQdqRjJre9+Z/I/Z37wt5IwA28/TIoVkYG71iQYxw==
|
||||
medusa-interfaces@1.1.21-dev-1631630701835:
|
||||
version "1.1.21-dev-1631630701835"
|
||||
resolved "http://localhost:4873/medusa-interfaces/-/medusa-interfaces-1.1.21-dev-1631630701835.tgz#af29b2ef0c987bded1b2d295ac6cf39880af551e"
|
||||
integrity sha512-rTASRjOdcS3J9fP95p9vJzCpatMpUhTum5ddfAA0s42pZx2gsPlf1f+rUSNz5QfeC5RdIEzRfOmAGfvMpAbYGw==
|
||||
dependencies:
|
||||
medusa-core-utils "^1.1.20"
|
||||
medusa-core-utils "1.1.20-dev-1631630701835"
|
||||
|
||||
medusa-telemetry@^0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "http://localhost:4873/medusa-telemetry/-/medusa-telemetry-0.0.3.tgz#c11e5e0f3cc969f3eaee41d1c24f78a5c0715362"
|
||||
integrity sha512-Qb/sgOwO8t2Sjjo4nKyBa6hKZ/SjniT4eEWenygEaJDqXZhfogVYGhWc5gn4tLlFFNEHXzDTlrqX2LvzfEJWIw==
|
||||
medusa-telemetry@0.0.3-dev-1631630701835:
|
||||
version "0.0.3-dev-1631630701835"
|
||||
resolved "http://localhost:4873/medusa-telemetry/-/medusa-telemetry-0.0.3-dev-1631630701835.tgz#d56c01d261fa30ccedc6d9976971b9744b9d8c0f"
|
||||
integrity sha512-FS1L1DOIOSdRZgeIQWaM5nhFG5NtbnC/Pntfac51vQxLkzFuHy7ZEtg11CXKE+x6NWlqT1rqqgxq0EabFzEZzw==
|
||||
dependencies:
|
||||
axios "^0.21.1"
|
||||
axios-retry "^3.1.9"
|
||||
boxen "^5.0.1"
|
||||
ci-info "^3.2.0"
|
||||
configstore "5.0.1"
|
||||
global "^4.4.0"
|
||||
is-docker "^2.2.1"
|
||||
remove-trailing-slash "^0.1.1"
|
||||
uuid "^8.3.2"
|
||||
|
||||
medusa-test-utils@^1.1.23:
|
||||
version "1.1.23"
|
||||
resolved "https://registry.yarnpkg.com/medusa-test-utils/-/medusa-test-utils-1.1.23.tgz#e8380df499979cd0b97a5bb87779662f4da9d722"
|
||||
integrity sha512-okyUgB4t7bqDieE0XO+HkbVVemn6hE1tTAtF9PXRi2igmKmcnyW/Ljk3lqrKYVhjei4z3Z/b+K2b0oNwhopbGQ==
|
||||
medusa-test-utils@1.1.23-dev-1631630701835:
|
||||
version "1.1.23-dev-1631630701835"
|
||||
resolved "http://localhost:4873/medusa-test-utils/-/medusa-test-utils-1.1.23-dev-1631630701835.tgz#8995d636caf2dea9ebb184f1e15b0c364c4d1b93"
|
||||
integrity sha512-A8xRL+sZS22qXZSHpVfdV8f/egZxXs4iExRO2xUkTP6I/OgMhFBSg6nEd/DXVdVfpsHZCDEv8PA3ewaeAkoYhQ==
|
||||
dependencies:
|
||||
"@babel/plugin-transform-classes" "^7.9.5"
|
||||
medusa-core-utils "^1.1.20"
|
||||
medusa-core-utils "1.1.20-dev-1631630701835"
|
||||
randomatic "^3.1.1"
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
@@ -5218,6 +5224,13 @@ mimic-fn@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
min-document@^2.19.0:
|
||||
version "2.19.0"
|
||||
resolved "http://localhost:4873/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
|
||||
integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=
|
||||
dependencies:
|
||||
dom-walk "^0.1.0"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
@@ -6060,6 +6073,11 @@ process-nextick-args@~2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
process@^0.11.10:
|
||||
version "0.11.10"
|
||||
resolved "http://localhost:4873/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
|
||||
promise.prototype.finally@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.2.tgz#b8af89160c9c673cefe3b4c4435b53cfd0287067"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
const path = require('path');
|
||||
const {dropDatabase} = require('pg-god');
|
||||
const path = require("path")
|
||||
const { dropDatabase } = require("pg-god")
|
||||
|
||||
require('dotenv').config({path: path.join(__dirname, '.env')});
|
||||
require("dotenv").config({ path: path.join(__dirname, ".env") })
|
||||
|
||||
const DB_USERNAME = process.env.DB_USERNAME || 'postgres';
|
||||
const DB_PASSWORD = process.env.DB_PASSWORD || '';
|
||||
const DB_USERNAME = process.env.DB_USERNAME || "postgres"
|
||||
const DB_PASSWORD = process.env.DB_PASSWORD || ""
|
||||
|
||||
const pgGodCredentials = {
|
||||
user: DB_USERNAME,
|
||||
password: DB_PASSWORD,
|
||||
};
|
||||
}
|
||||
|
||||
afterAll(() => {
|
||||
dropDatabase({databaseName: 'medusa-integration'}, pgGodCredentials);
|
||||
});
|
||||
dropDatabase({ databaseName: "medusa-integration" }, pgGodCredentials)
|
||||
})
|
||||
|
||||
@@ -2246,6 +2246,11 @@ doctrine@^3.0.0:
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
dom-walk@^0.1.0:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
|
||||
integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==
|
||||
|
||||
domexception@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
|
||||
@@ -2870,6 +2875,14 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
global@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
|
||||
integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
|
||||
dependencies:
|
||||
min-document "^2.19.0"
|
||||
process "^0.11.10"
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||
@@ -4091,16 +4104,17 @@ medusa-core-utils@^0.1.27:
|
||||
"@hapi/joi" "^16.1.8"
|
||||
joi-objectid "^3.0.1"
|
||||
|
||||
medusa-telemetry@^0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/medusa-telemetry/-/medusa-telemetry-0.0.3.tgz#c11e5e0f3cc969f3eaee41d1c24f78a5c0715362"
|
||||
integrity sha512-Qb/sgOwO8t2Sjjo4nKyBa6hKZ/SjniT4eEWenygEaJDqXZhfogVYGhWc5gn4tLlFFNEHXzDTlrqX2LvzfEJWIw==
|
||||
medusa-telemetry@^0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/medusa-telemetry/-/medusa-telemetry-0.0.5.tgz#d7d08fca5cbecc0e853b4e0406194a92c5206caa"
|
||||
integrity sha512-h7hP5Lc33OkFhMcvfrPcwINzMOuPoG8Vn8O6niKGFxF9RmmQnJgaAG1J43/Eq9ZWBrWi0n42XBttibKwCMViHw==
|
||||
dependencies:
|
||||
axios "^0.21.1"
|
||||
axios-retry "^3.1.9"
|
||||
boxen "^5.0.1"
|
||||
ci-info "^3.2.0"
|
||||
configstore "5.0.1"
|
||||
global "^4.4.0"
|
||||
is-docker "^2.2.1"
|
||||
remove-trailing-slash "^0.1.1"
|
||||
uuid "^8.3.2"
|
||||
@@ -4167,6 +4181,13 @@ mimic-fn@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
min-document@^2.19.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
|
||||
integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=
|
||||
dependencies:
|
||||
dom-walk "^0.1.0"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
@@ -4706,6 +4727,11 @@ process-nextick-args@~2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
process@^0.11.10:
|
||||
version "0.11.10"
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
|
||||
progress@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
@@ -5561,9 +5587,9 @@ tmp@^0.0.33:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
tmpl@1.0.x:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
|
||||
integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
|
||||
integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
||||
@@ -4938,9 +4938,9 @@ tmp@^0.0.33:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
tmpl@1.0.x:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
|
||||
integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
|
||||
integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-transform-instanceof",
|
||||
"@babel/plugin-transform-classes"
|
||||
],
|
||||
"presets": ["@babel/preset-env"],
|
||||
"env": {
|
||||
"test": {
|
||||
"plugins": ["@babel/plugin-transform-runtime"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"plugins": ["prettier"],
|
||||
"extends": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"semi": "error",
|
||||
"no-unused-expressions": "true"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/lib
|
||||
node_modules
|
||||
.DS_store
|
||||
.env*
|
||||
/*.js
|
||||
!index.js
|
||||
yarn.lock
|
||||
|
||||
/dist
|
||||
|
||||
/api
|
||||
/services
|
||||
/models
|
||||
/subscribers
|
||||
/__mocks__
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/lib
|
||||
node_modules
|
||||
.DS_store
|
||||
.env*
|
||||
/*.js
|
||||
!index.js
|
||||
yarn.lock
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# medusa-file-s3
|
||||
|
||||
Upload files to an AWS S3 bucket.
|
||||
|
||||
## Options
|
||||
|
||||
```
|
||||
s3_url: [url of your s3 bucket],
|
||||
access_key_id: [access-key],
|
||||
secret_access_key: [secret-access-key],
|
||||
bucket: [name of your bucket],
|
||||
region: [region of your bucket],
|
||||
```
|
||||
|
||||
Follow [this guide](https://docs.medusa-commerce.com/how-to/uploading-images-to-s3) to configure the plugin.
|
||||
@@ -0,0 +1 @@
|
||||
// noop
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "medusa-file-s3",
|
||||
"version": "1.0.0",
|
||||
"description": "AWS s3 file connector for Medusa",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/medusajs/medusa",
|
||||
"directory": "packages/medusa-file-s3"
|
||||
},
|
||||
"author": "Sebastian Mateos Nicolajsen",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.7.5",
|
||||
"@babel/core": "^7.7.5",
|
||||
"@babel/node": "^7.7.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.7.4",
|
||||
"@babel/plugin-transform-instanceof": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||
"@babel/preset-env": "^7.7.5",
|
||||
"@babel/register": "^7.7.4",
|
||||
"@babel/runtime": "^7.9.6",
|
||||
"client-sessions": "^0.8.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"eslint": "^6.8.0",
|
||||
"jest": "^25.5.2",
|
||||
"medusa-test-utils": "^0.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "babel src -d .",
|
||||
"prepare": "cross-env NODE_ENV=production npm run build",
|
||||
"watch": "babel -w src --out-dir . --ignore **/__tests__",
|
||||
"test": "jest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"medusa-interfaces": "1.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-classes": "^7.15.4",
|
||||
"aws-sdk": "^2.983.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"express": "^4.17.1",
|
||||
"medusa-core-utils": "^1.1.20",
|
||||
"medusa-test-utils": "^1.1.23"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import fs from "fs"
|
||||
import aws from "aws-sdk"
|
||||
import { FileService } from "medusa-interfaces"
|
||||
|
||||
class S3Service extends FileService {
|
||||
constructor({}, options) {
|
||||
super()
|
||||
|
||||
this.bucket_ = options.bucket
|
||||
this.s3Url_ = options.s3_url
|
||||
this.accessKeyId_ = options.access_key_id
|
||||
this.secretAccessKey_ = options.secret_access_key
|
||||
this.region_ = options.region
|
||||
this.endpoint_ = options.endpoint
|
||||
}
|
||||
|
||||
upload(file) {
|
||||
aws.config.setPromisesDependency()
|
||||
aws.config.update({
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
region: this.region_,
|
||||
endpoint: this.endpoint_,
|
||||
})
|
||||
|
||||
const s3 = new aws.S3()
|
||||
var params = {
|
||||
ACL: "public-read",
|
||||
Bucket: this.bucket_,
|
||||
Body: fs.createReadStream(file.path),
|
||||
Key: `${file.originalname}`,
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
s3.upload(params, (err, data) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
|
||||
resolve({ url: data.Location })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
delete(file) {
|
||||
aws.config.setPromisesDependency()
|
||||
aws.config.update({
|
||||
accessKeyId: this.accessKeyId_,
|
||||
secretAccessKey: this.secretAccessKey_,
|
||||
region: this.region_,
|
||||
endpoint: this.endpoint_,
|
||||
})
|
||||
|
||||
const s3 = new aws.S3()
|
||||
var params = {
|
||||
Bucket: this.bucket_,
|
||||
Key: `${file}`,
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
s3.deleteObject(params, (err, data) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
return
|
||||
}
|
||||
resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default S3Service
|
||||
@@ -0,0 +1,15 @@
|
||||
# medusa-file-spaces
|
||||
|
||||
Upload files to a DigitalOcean Space.
|
||||
|
||||
## Options
|
||||
|
||||
```
|
||||
spaces_url: [url of your DigitalOcean space],
|
||||
access_key_id: [access-key],
|
||||
secret_access_key: [secret-access-key],
|
||||
bucket: [name of your bucket],
|
||||
endpoint: [endpoint of you DigitalOcean space],
|
||||
```
|
||||
|
||||
Follow [this guide](https://docs.medusa-commerce.com/how-to/uploading-images-to-spaces) to configure the plugin.
|
||||
@@ -857,6 +857,18 @@
|
||||
exec-sh "^0.3.2"
|
||||
minimist "^1.2.0"
|
||||
|
||||
"@hapi/hoek@^9.0.0":
|
||||
version "9.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131"
|
||||
integrity sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==
|
||||
|
||||
"@hapi/topo@^5.0.0":
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
|
||||
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
|
||||
dependencies:
|
||||
"@hapi/hoek" "^9.0.0"
|
||||
|
||||
"@istanbuljs/load-nyc-config@^1.0.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
|
||||
@@ -1058,6 +1070,23 @@
|
||||
readdirp "^2.2.1"
|
||||
upath "^1.1.1"
|
||||
|
||||
"@sideway/address@^4.1.0":
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.2.tgz#811b84333a335739d3969cfc434736268170cad1"
|
||||
integrity sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==
|
||||
dependencies:
|
||||
"@hapi/hoek" "^9.0.0"
|
||||
|
||||
"@sideway/formula@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c"
|
||||
integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==
|
||||
|
||||
"@sideway/pinpoint@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
|
||||
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
|
||||
|
||||
"@sinonjs/commons@^1.7.0":
|
||||
version "1.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b"
|
||||
@@ -3167,6 +3196,22 @@ jest@^25.5.2:
|
||||
import-local "^3.0.2"
|
||||
jest-cli "^25.5.4"
|
||||
|
||||
joi-objectid@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/joi-objectid/-/joi-objectid-3.0.1.tgz#63ace7860f8e1a993a28d40c40ffd8eff01a3668"
|
||||
integrity sha512-V/3hbTlGpvJ03Me6DJbdBI08hBTasFOmipsauOsxOSnsF1blxV537WTl1zPwbfcKle4AK0Ma4OPnzMH4LlvTpQ==
|
||||
|
||||
joi@^17.3.0:
|
||||
version "17.4.2"
|
||||
resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.2.tgz#02f4eb5cf88e515e614830239379dcbbe28ce7f7"
|
||||
integrity sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==
|
||||
dependencies:
|
||||
"@hapi/hoek" "^9.0.0"
|
||||
"@hapi/topo" "^5.0.0"
|
||||
"@sideway/address" "^4.1.0"
|
||||
"@sideway/formula" "^3.0.0"
|
||||
"@sideway/pinpoint" "^2.0.0"
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
@@ -3379,6 +3424,14 @@ math-random@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
|
||||
integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
|
||||
|
||||
medusa-core-utils@^1.1.22:
|
||||
version "1.1.22"
|
||||
resolved "https://registry.yarnpkg.com/medusa-core-utils/-/medusa-core-utils-1.1.22.tgz#84ce0af0a7c672191d758ea462056e30a39d08b1"
|
||||
integrity sha512-kMuRkWOuNG4Bw6epg/AYu95UJuE+rjHTeTWRLbEPrYGjWREV82tLWVDI21/QcccmaHmMU98Rkw2z9JwyFZIiyw==
|
||||
dependencies:
|
||||
joi "^17.3.0"
|
||||
joi-objectid "^3.0.1"
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
@@ -4516,9 +4569,9 @@ tmp@^0.0.33:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
tmpl@1.0.x:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
|
||||
integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
|
||||
integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"glob": "^7.1.6",
|
||||
"ioredis": "^4.17.3",
|
||||
"ioredis-mock": "^5.6.0",
|
||||
"iso8601-duration": "^1.3.0",
|
||||
"joi": "^17.3.0",
|
||||
"joi-objectid": "^3.0.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
|
||||
@@ -12,6 +12,9 @@ import { Validator, MedusaError } from "medusa-core-utils"
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* email:
|
||||
* type: string
|
||||
* description: The Customer's email. Only providable if user not registered.
|
||||
* first_name:
|
||||
* type: string
|
||||
* description: The Customer's first name.
|
||||
@@ -37,6 +40,7 @@ export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
email: Validator.string().optional(),
|
||||
first_name: Validator.string().optional(),
|
||||
last_name: Validator.string().optional(),
|
||||
password: Validator.string().optional(),
|
||||
@@ -50,9 +54,19 @@ export default async (req, res) => {
|
||||
|
||||
try {
|
||||
const customerService = req.scope.resolve("customerService")
|
||||
|
||||
let customer = await customerService.retrieve(id)
|
||||
|
||||
if (value.email && customer.has_account) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"Email cannot be changed when the user has registered their account"
|
||||
)
|
||||
}
|
||||
|
||||
await customerService.update(id, value)
|
||||
|
||||
const customer = await customerService.retrieve(id, {
|
||||
customer = await customerService.retrieve(id, {
|
||||
relations: ["orders"],
|
||||
})
|
||||
res.status(200).json({ customer })
|
||||
|
||||
@@ -46,6 +46,7 @@ describe("POST /admin/discounts/:discount_id/regions/:region_id", () => {
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"metadata",
|
||||
"valid_duration",
|
||||
],
|
||||
relations: ["rule", "parent_discount", "regions", "rule.valid_for"],
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ describe("POST /admin/discounts/:discount_id/variants/:variant_id", () => {
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"metadata",
|
||||
"valid_duration",
|
||||
],
|
||||
relations: ["rule", "parent_discount", "regions", "rule.valid_for"],
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ describe("POST /admin/discounts", () => {
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: "02/02/2021 13:45",
|
||||
ends_at: "03/14/2021 04:30",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
@@ -39,12 +41,99 @@ describe("POST /admin/discounts", () => {
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: new Date("02/02/2021 13:45"),
|
||||
ends_at: new Date("03/14/2021 04:30"),
|
||||
is_disabled: false,
|
||||
is_dynamic: false,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("unsuccessful creation with dynamic discount using an invalid iso8601 duration", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request("POST", "/admin/discounts", {
|
||||
payload: {
|
||||
code: "TEST",
|
||||
rule: {
|
||||
description: "Test",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: "02/02/2021 13:45",
|
||||
is_dynamic: true,
|
||||
valid_duration: "PaMT2D",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 400", () => {
|
||||
expect(subject.status).toEqual(400)
|
||||
})
|
||||
|
||||
it("returns error", () => {
|
||||
expect(subject.body.message[0].message).toEqual(
|
||||
`"valid_duration" must be a valid ISO 8601 duration`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("successful creation with dynamic discount", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request("POST", "/admin/discounts", {
|
||||
payload: {
|
||||
code: "TEST",
|
||||
rule: {
|
||||
description: "Test",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: "02/02/2021 13:45",
|
||||
is_dynamic: true,
|
||||
valid_duration: "P1Y2M03DT04H05M",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service create", () => {
|
||||
expect(DiscountServiceMock.create).toHaveBeenCalledTimes(1)
|
||||
expect(DiscountServiceMock.create).toHaveBeenCalledWith({
|
||||
code: "TEST",
|
||||
rule: {
|
||||
description: "Test",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: new Date("02/02/2021 13:45"),
|
||||
is_disabled: false,
|
||||
is_dynamic: true,
|
||||
valid_duration: "P1Y2M03DT04H05M",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("fails on invalid data", () => {
|
||||
let subject
|
||||
|
||||
@@ -74,4 +163,84 @@ describe("POST /admin/discounts", () => {
|
||||
expect(subject.body.message[0].message).toEqual(`"rule.type" is required`)
|
||||
})
|
||||
})
|
||||
|
||||
describe("fails on invalid date intervals", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
subject = await request("POST", "/admin/discounts", {
|
||||
payload: {
|
||||
code: "TEST",
|
||||
rule: {
|
||||
description: "Test",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
ends_at: "02/02/2021",
|
||||
starts_at: "03/14/2021",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 400", () => {
|
||||
expect(subject.status).toEqual(400)
|
||||
})
|
||||
|
||||
it("returns error", () => {
|
||||
expect(subject.body.message[0].message).toEqual(
|
||||
`"ends_at" must be greater than "ref:starts_at"`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("succesfully creates a dynamic discount without setting valid duration", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request("POST", "/admin/discounts", {
|
||||
payload: {
|
||||
code: "TEST",
|
||||
is_dynamic: true,
|
||||
rule: {
|
||||
description: "Test",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: "03/14/2021 14:30",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("returns error", () => {
|
||||
expect(DiscountServiceMock.create).toHaveBeenCalledWith({
|
||||
code: "TEST",
|
||||
is_dynamic: true,
|
||||
is_disabled: false,
|
||||
rule: {
|
||||
description: "Test",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: new Date("03/14/2021 14:30"),
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -17,6 +17,7 @@ const defaultFields = [
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"metadata",
|
||||
"valid_duration",
|
||||
]
|
||||
|
||||
const defaultRelations = [
|
||||
|
||||
@@ -17,6 +17,7 @@ const defaultFields = [
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"metadata",
|
||||
"valid_duration",
|
||||
]
|
||||
|
||||
const defaultRelations = [
|
||||
|
||||
@@ -17,6 +17,7 @@ const defaultFields = [
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"metadata",
|
||||
"valid_duration",
|
||||
]
|
||||
|
||||
const defaultRelations = [
|
||||
|
||||
@@ -7,6 +7,7 @@ describe("POST /admin/discounts", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/discounts/${IdMap.getId("total10")}`,
|
||||
@@ -50,4 +51,139 @@ describe("POST /admin/discounts", () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("unsuccessful update with dynamic discount using an invalid iso8601 duration", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/discounts/${IdMap.getId("total10")}`,
|
||||
{
|
||||
payload: {
|
||||
code: "10TOTALOFF",
|
||||
rule: {
|
||||
id: "1234",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: "02/02/2021 13:45",
|
||||
is_dynamic: true,
|
||||
valid_duration: "PaMT2D",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 400", () => {
|
||||
expect(subject.status).toEqual(400)
|
||||
})
|
||||
|
||||
it("returns error", () => {
|
||||
expect(subject.body.message[0].message).toEqual(
|
||||
`"valid_duration" must be a valid ISO 8601 duration`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("successful update with dynamic discount", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/discounts/${IdMap.getId("total10")}`,
|
||||
{
|
||||
payload: {
|
||||
code: "10TOTALOFF",
|
||||
rule: {
|
||||
id: "1234",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: "02/02/2021 13:45",
|
||||
is_dynamic: true,
|
||||
valid_duration: "P1Y2M03DT04H05M",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 200", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("calls service update", () => {
|
||||
expect(DiscountServiceMock.update).toHaveBeenCalledTimes(1)
|
||||
expect(DiscountServiceMock.update).toHaveBeenCalledWith(
|
||||
IdMap.getId("total10"),
|
||||
{
|
||||
code: "10TOTALOFF",
|
||||
rule: {
|
||||
id: "1234",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
starts_at: new Date("02/02/2021 13:45"),
|
||||
is_dynamic: true,
|
||||
valid_duration: "P1Y2M03DT04H05M",
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("fails on invalid date intervals", () => {
|
||||
let subject
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/admin/discounts/${IdMap.getId("total10")}`,
|
||||
{
|
||||
payload: {
|
||||
code: "10TOTALOFF",
|
||||
rule: {
|
||||
id: "1234",
|
||||
type: "fixed",
|
||||
value: 10,
|
||||
allocation: "total",
|
||||
},
|
||||
ends_at: "02/02/2021",
|
||||
starts_at: "03/14/2021",
|
||||
},
|
||||
adminSession: {
|
||||
jwt: {
|
||||
userId: IdMap.getId("admin_user"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("returns 400", () => {
|
||||
expect(subject.status).toEqual(400)
|
||||
})
|
||||
|
||||
it("returns error", () => {
|
||||
expect(subject.body.message[0].message).toEqual(
|
||||
`"ends_at" must be greater than "ref:starts_at"`
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -71,7 +71,13 @@ export default async (req, res) => {
|
||||
.required(),
|
||||
is_disabled: Validator.boolean().default(false),
|
||||
starts_at: Validator.date().optional(),
|
||||
ends_at: Validator.date().optional(),
|
||||
ends_at: Validator.date()
|
||||
.greater(Validator.ref("starts_at"))
|
||||
.optional(),
|
||||
valid_duration: Validator.string()
|
||||
.isoDuration()
|
||||
.allow(null)
|
||||
.optional(),
|
||||
usage_limit: Validator.number()
|
||||
.positive()
|
||||
.optional(),
|
||||
|
||||
@@ -37,9 +37,9 @@ export default async (req, res) => {
|
||||
|
||||
try {
|
||||
const discountService = req.scope.resolve("discountService")
|
||||
await discountService.createDynamicCode(discount_id, value)
|
||||
const created = await discountService.createDynamicCode(discount_id, value)
|
||||
|
||||
const discount = await discountService.retrieve(discount_id, {
|
||||
const discount = await discountService.retrieve(created.id, {
|
||||
relations: ["rule", "rule.valid_for", "regions"],
|
||||
})
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ export const defaultFields = [
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
"metadata",
|
||||
"valid_duration",
|
||||
]
|
||||
|
||||
export const defaultRelations = [
|
||||
|
||||
@@ -68,7 +68,16 @@ export default async (req, res) => {
|
||||
.optional(),
|
||||
is_disabled: Validator.boolean().optional(),
|
||||
starts_at: Validator.date().optional(),
|
||||
ends_at: Validator.date().optional(),
|
||||
ends_at: Validator.when("starts_at", {
|
||||
not: undefined,
|
||||
then: Validator.date()
|
||||
.greater(Validator.ref("starts_at"))
|
||||
.optional(),
|
||||
otherwise: Validator.date().optional(),
|
||||
}),
|
||||
valid_duration: Validator.string()
|
||||
.isoDuration().allow(null)
|
||||
.optional(),
|
||||
usage_limit: Validator.number()
|
||||
.positive()
|
||||
.optional(),
|
||||
@@ -78,6 +87,7 @@ export default async (req, res) => {
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import variantRoutes from "./variants"
|
||||
import draftOrderRoutes from "./draft-orders"
|
||||
import collectionRoutes from "./collections"
|
||||
import notificationRoutes from "./notifications"
|
||||
import noteRoutes from "./notes"
|
||||
|
||||
const route = Router()
|
||||
|
||||
@@ -68,6 +69,7 @@ export default (app, container, config) => {
|
||||
collectionRoutes(route)
|
||||
notificationRoutes(route)
|
||||
returnReasonRoutes(route)
|
||||
noteRoutes(route)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
/**
|
||||
* @oas [post] /notes
|
||||
* operationId: "PostNotes"
|
||||
* summary: "Creates a Note"
|
||||
* description: "Creates a Note which can be associated with any resource as required."
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* resource_id:
|
||||
* type: string
|
||||
* description: The id of the resource which the Note relates to.
|
||||
* resource_type:
|
||||
* type: string
|
||||
* description: The type of resource which the Note relates to.
|
||||
* value:
|
||||
* type: string
|
||||
* description: The content of the Note to create.
|
||||
* tags:
|
||||
* - Note
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* note:
|
||||
* $ref: "#/components/schemas/note"
|
||||
*
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
resource_id: Validator.string(),
|
||||
resource_type: Validator.string(),
|
||||
value: Validator.string(),
|
||||
})
|
||||
|
||||
const userId = req.user.id || req.user.userId
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const noteService = req.scope.resolve("noteService")
|
||||
|
||||
const result = await noteService.create({
|
||||
resource_id: value.resource_id,
|
||||
resource_type: value.resource_type,
|
||||
value: value.value,
|
||||
author_id: userId,
|
||||
})
|
||||
|
||||
res.status(200).json({ note: result })
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @oas [delete] /notes/{id}
|
||||
* operationId: "DeleteNotesNote"
|
||||
* summary: "Deletes a Note"
|
||||
* description: "Deletes a Note."
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Note to delete.
|
||||
* tags:
|
||||
* - Note
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* id:
|
||||
* type: string
|
||||
* description: The id of the deleted Note.
|
||||
* deleted:
|
||||
* type: boolean
|
||||
* description: Whether or not the Note was deleted.
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
try {
|
||||
const noteService = req.scope.resolve("noteService")
|
||||
await noteService.delete(id)
|
||||
|
||||
res.status(200).json({ id, deleted: true })
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @oas [get] /notes/{id}
|
||||
* operationId: "GetNoteNote"
|
||||
* summary: "Get Note"
|
||||
* description: "Retrieves a single note using its id"
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the note to retrieve.
|
||||
* tags:
|
||||
* - Note
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* note:
|
||||
* $ref: "#/components/schemas/note"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
try {
|
||||
const noteService = req.scope.resolve("noteService")
|
||||
const note = await noteService.retrieve(id, { relations: ["author"] })
|
||||
|
||||
res.status(200).json({ note })
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Router } from "express"
|
||||
import middlewares from "../../../middlewares"
|
||||
|
||||
const route = Router()
|
||||
|
||||
export default app => {
|
||||
app.use("/notes", route)
|
||||
|
||||
route.get("/:id", middlewares.wrap(require("./get-note").default))
|
||||
|
||||
route.get("/", middlewares.wrap(require("./list-notes").default))
|
||||
|
||||
route.post("/", middlewares.wrap(require("./create-note").default))
|
||||
|
||||
route.post("/:id", middlewares.wrap(require("./update-note").default))
|
||||
|
||||
route.delete("/:id", middlewares.wrap(require("./delete-note").default))
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @oas [get] /notes
|
||||
* operationId: "GetNotes"
|
||||
* summary: "List Notes"
|
||||
* description: "Retrieves a list of notes"
|
||||
* tags:
|
||||
* - Note
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* notes:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: "#/components/schemas/note"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
try {
|
||||
const limit = parseInt(req.query.limit) || 50
|
||||
const offset = parseInt(req.query.offset) || 0
|
||||
|
||||
const selector = {}
|
||||
|
||||
if ("resource_id" in req.query) {
|
||||
selector.resource_id = req.query.resource_id
|
||||
}
|
||||
|
||||
const noteService = req.scope.resolve("noteService")
|
||||
const notes = await noteService.list(selector, {
|
||||
take: limit,
|
||||
skip: offset,
|
||||
relations: ["author"],
|
||||
})
|
||||
|
||||
res.status(200).json({ notes })
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
/**
|
||||
* @oas [post] /notes/{id}
|
||||
* operationId: "PostNotesNote"
|
||||
* summary: "Updates a Note"
|
||||
* description: "Updates a Note associated with some resource"
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Note to update
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* value:
|
||||
* type: string
|
||||
* description: The updated description of the Note.
|
||||
* tags:
|
||||
* - Note
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* note:
|
||||
* $ref: "#/components/schemas/note"
|
||||
*
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
value: Validator.string(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
if (error) {
|
||||
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
|
||||
}
|
||||
|
||||
try {
|
||||
const noteService = req.scope.resolve("noteService")
|
||||
const result = await noteService.update(id, value.value)
|
||||
|
||||
res.status(200).json({ note: result })
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,9 @@ import { defaultFields, defaultRelations } from "./"
|
||||
* no_notification:
|
||||
* description: If set to true no notification will be send related to this Swap.
|
||||
* type: boolean
|
||||
* allow_backorder:
|
||||
* description: If true, swaps can be completed with items out of stock
|
||||
* type: boolean
|
||||
* tags:
|
||||
* - Order
|
||||
* responses:
|
||||
@@ -83,6 +86,7 @@ export default async (req, res) => {
|
||||
quantity: Validator.number().required(),
|
||||
}),
|
||||
no_notification: Validator.boolean().optional(),
|
||||
allow_backorder: Validator.boolean().default(true),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
@@ -141,6 +145,7 @@ export default async (req, res) => {
|
||||
{
|
||||
idempotency_key: idempotencyKey.idempotency_key,
|
||||
no_notification: value.no_notification,
|
||||
allow_backorder: value.allow_backorder,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ describe("POST /admin/products", () => {
|
||||
description: "Test Description",
|
||||
tags: [{ id: "test", value: "test" }],
|
||||
handle: "test-product",
|
||||
status: "draft",
|
||||
is_giftcard: false,
|
||||
options: [{ title: "Denominations" }],
|
||||
profile_id: IdMap.getId("default_shipping_profile"),
|
||||
@@ -170,6 +171,7 @@ describe("POST /admin/products", () => {
|
||||
options: [{ title: "Denominations" }],
|
||||
handle: "test-gift-card",
|
||||
is_giftcard: true,
|
||||
status: "draft",
|
||||
profile_id: IdMap.getId("giftCardProfile"),
|
||||
})
|
||||
})
|
||||
|
||||
@@ -193,6 +193,9 @@ export default async (req, res) => {
|
||||
.optional(),
|
||||
thumbnail: Validator.string().optional(),
|
||||
handle: Validator.string().optional(),
|
||||
status: Validator.string()
|
||||
.valid("proposed", "draft", "published", "rejected")
|
||||
.default("draft"),
|
||||
type: Validator.object()
|
||||
.keys({
|
||||
id: Validator.string().optional(),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import _ from "lodash"
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import { defaultFields, defaultRelations } from "./"
|
||||
|
||||
/**
|
||||
@@ -56,6 +57,20 @@ export default async (req, res) => {
|
||||
selector.is_giftcard = req.query.is_giftcard === "true"
|
||||
}
|
||||
|
||||
if ("status" in req.query) {
|
||||
const schema = Validator.array()
|
||||
.items(
|
||||
Validator.string().valid("proposed", "draft", "published", "rejected")
|
||||
)
|
||||
.single()
|
||||
|
||||
const { value, error } = schema.validate(req.query.status)
|
||||
|
||||
if (value && !error) {
|
||||
selector.status = value
|
||||
}
|
||||
}
|
||||
|
||||
const listConfig = {
|
||||
select: includeFields.length ? includeFields : defaultFields,
|
||||
relations: expandFields.length ? expandFields : defaultRelations,
|
||||
|
||||
@@ -193,6 +193,12 @@ export default async (req, res) => {
|
||||
.allow(null, ""),
|
||||
description: Validator.string().optional(),
|
||||
discountable: Validator.boolean().optional(),
|
||||
status: Validator.string().valid(
|
||||
"proposed",
|
||||
"draft",
|
||||
"published",
|
||||
"rejected"
|
||||
),
|
||||
type: Validator.object()
|
||||
.keys({
|
||||
id: Validator.string().optional(),
|
||||
|
||||
@@ -39,6 +39,7 @@ export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
value: Validator.string().required(),
|
||||
label: Validator.string().required(),
|
||||
parent_return_reason_id: Validator.string().optional(),
|
||||
description: Validator.string()
|
||||
.optional()
|
||||
.allow(""),
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @oas [delete] /return-reason/{id}
|
||||
* operationId: "DeleteReturnReason"
|
||||
* summary: "Delete a return reason"
|
||||
* description: "Deletes a return reason."
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the return reason
|
||||
* tags:
|
||||
* - Return Reason
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* properties:
|
||||
* id:
|
||||
* type: string
|
||||
* description: The id of the deleted return reason
|
||||
* object:
|
||||
* type: string
|
||||
* description: The type of the object that was deleted.
|
||||
* deleted:
|
||||
* type: boolean
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
|
||||
try {
|
||||
const returnReasonService = req.scope.resolve("returnReasonService")
|
||||
await returnReasonService.delete(id)
|
||||
|
||||
res.json({
|
||||
id: id,
|
||||
object: "return_reason",
|
||||
deleted: true,
|
||||
})
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,11 @@ export default app => {
|
||||
*/
|
||||
route.post("/:id", middlewares.wrap(require("./update-reason").default))
|
||||
|
||||
/**
|
||||
* Delete a reason
|
||||
*/
|
||||
route.delete("/:id", middlewares.wrap(require("./delete-reason").default))
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -33,10 +38,14 @@ export const defaultFields = [
|
||||
"id",
|
||||
"value",
|
||||
"label",
|
||||
"parent_return_reason_id",
|
||||
"description",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
]
|
||||
|
||||
export const defaultRelations = []
|
||||
export const defaultRelations = [
|
||||
"parent_return_reason",
|
||||
"return_reason_children",
|
||||
]
|
||||
|
||||
@@ -24,7 +24,7 @@ export default async (req, res) => {
|
||||
try {
|
||||
const returnReasonService = req.scope.resolve("returnReasonService")
|
||||
|
||||
const query = {}
|
||||
const query = { parent_return_reason_id: null }
|
||||
const data = await returnReasonService.list(query, {
|
||||
select: defaultFields,
|
||||
relations: defaultRelations,
|
||||
|
||||
@@ -42,6 +42,7 @@ export default async (req, res) => {
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
label: Validator.string().optional(),
|
||||
parent_return_reason_id: Validator.string().optional(),
|
||||
description: Validator.string()
|
||||
.optional()
|
||||
.allow(""),
|
||||
|
||||
@@ -138,18 +138,36 @@ export default async (req, res) => {
|
||||
// If cart is part of swap, we register swap as complete
|
||||
switch (cart.type) {
|
||||
case "swap": {
|
||||
const swapId = cart.metadata?.swap_id
|
||||
let swap = await swapService
|
||||
.withTransaction(manager)
|
||||
.registerCartCompletion(swapId)
|
||||
try {
|
||||
const swapId = cart.metadata?.swap_id
|
||||
let swap = await swapService
|
||||
.withTransaction(manager)
|
||||
.registerCartCompletion(swapId)
|
||||
|
||||
swap = await swapService
|
||||
.withTransaction(manager)
|
||||
.retrieve(swap.id, { relations: ["shipping_address"] })
|
||||
swap = await swapService
|
||||
.withTransaction(manager)
|
||||
.retrieve(swap.id, { relations: ["shipping_address"] })
|
||||
|
||||
return {
|
||||
response_code: 200,
|
||||
response_body: { data: swap, type: "swap" },
|
||||
return {
|
||||
response_code: 200,
|
||||
response_body: { data: swap, type: "swap" },
|
||||
}
|
||||
} catch (error) {
|
||||
if (
|
||||
error &&
|
||||
error.code === MedusaError.Codes.INSUFFICIENT_INVENTORY
|
||||
) {
|
||||
return {
|
||||
response_code: 409,
|
||||
response_body: {
|
||||
message: error.message,
|
||||
type: error.type,
|
||||
code: error.code,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
// case "payment_link":
|
||||
|
||||
@@ -7,21 +7,18 @@ describe("POST /store/customers/:id", () => {
|
||||
describe("successfully updates a customer", () => {
|
||||
let subject
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/store/customers/${IdMap.getId("lebron")}`,
|
||||
{
|
||||
payload: {
|
||||
first_name: "LeBron",
|
||||
last_name: "James",
|
||||
subject = await request("POST", `/store/customers/me`, {
|
||||
payload: {
|
||||
first_name: "LeBron",
|
||||
last_name: "James",
|
||||
email: "test@email.com",
|
||||
},
|
||||
clientSession: {
|
||||
jwt: {
|
||||
customer_id: IdMap.getId("lebron"),
|
||||
},
|
||||
clientSession: {
|
||||
jwt: {
|
||||
customer_id: IdMap.getId("lebron"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
@@ -35,6 +32,7 @@ describe("POST /store/customers/:id", () => {
|
||||
{
|
||||
first_name: "LeBron",
|
||||
last_name: "James",
|
||||
email: "test@email.com",
|
||||
}
|
||||
)
|
||||
})
|
||||
@@ -59,20 +57,16 @@ describe("POST /store/customers/:id", () => {
|
||||
describe("successfully updates a customer with billing address id", () => {
|
||||
let subject
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/store/customers/${IdMap.getId("lebron")}`,
|
||||
{
|
||||
payload: {
|
||||
billing_address: "test",
|
||||
subject = await request("POST", `/store/customers/me`, {
|
||||
payload: {
|
||||
billing_address: "test",
|
||||
},
|
||||
clientSession: {
|
||||
jwt: {
|
||||
customer_id: IdMap.getId("lebron"),
|
||||
},
|
||||
clientSession: {
|
||||
jwt: {
|
||||
customer_id: IdMap.getId("lebron"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
@@ -97,28 +91,24 @@ describe("POST /store/customers/:id", () => {
|
||||
describe("successfully updates a customer with billing address object", () => {
|
||||
let subject
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/store/customers/${IdMap.getId("lebron")}`,
|
||||
{
|
||||
payload: {
|
||||
billing_address: {
|
||||
first_name: "Olli",
|
||||
last_name: "Juhl",
|
||||
address_1: "Laksegade",
|
||||
city: "Copenhagen",
|
||||
country_code: "dk",
|
||||
postal_code: "2100",
|
||||
phone: "+1 (222) 333 4444",
|
||||
},
|
||||
subject = await request("POST", `/store/customers/me`, {
|
||||
payload: {
|
||||
billing_address: {
|
||||
first_name: "Olli",
|
||||
last_name: "Juhl",
|
||||
address_1: "Laksegade",
|
||||
city: "Copenhagen",
|
||||
country_code: "dk",
|
||||
postal_code: "2100",
|
||||
phone: "+1 (222) 333 4444",
|
||||
},
|
||||
clientSession: {
|
||||
jwt: {
|
||||
customer_id: IdMap.getId("lebron"),
|
||||
},
|
||||
},
|
||||
clientSession: {
|
||||
jwt: {
|
||||
customer_id: IdMap.getId("lebron"),
|
||||
},
|
||||
}
|
||||
)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
@@ -147,33 +137,4 @@ describe("POST /store/customers/:id", () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
})
|
||||
})
|
||||
|
||||
describe("fails if not authenticated", () => {
|
||||
let subject
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"POST",
|
||||
`/store/customers/${IdMap.getId("customer1")}`,
|
||||
{
|
||||
payload: {
|
||||
first_name: "LeBron",
|
||||
last_name: "James",
|
||||
},
|
||||
clientSession: {
|
||||
jwt: {
|
||||
customer_id: IdMap.getId("lebron"),
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("status code 400", () => {
|
||||
expect(subject.status).toEqual(400)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res, next, id) => {
|
||||
if (!(req.user && req.user.customer_id === id)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_ALLOWED,
|
||||
"You must be logged in to update"
|
||||
)
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import { defaultRelations, defaultFields } from "./"
|
||||
* $ref: "#/components/schemas/customer"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
const id = req.user.customer_id
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
address: Validator.address().required(),
|
||||
|
||||
@@ -21,7 +21,8 @@ import { defaultRelations, defaultFields } from "./"
|
||||
* $ref: "#/components/schemas/customer"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id, address_id } = req.params
|
||||
const id = req.user.customer_id
|
||||
const { address_id } = req.params
|
||||
|
||||
const customerService = req.scope.resolve("customerService")
|
||||
try {
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { defaultRelations, defaultFields } from "./"
|
||||
|
||||
/**
|
||||
* @oas [get] /customers/{id}
|
||||
* @oas [get] /customers/me
|
||||
* operationId: GetCustomersCustomer
|
||||
* summary: Retrieves a Customer
|
||||
* description: "Retrieves a Customer - the Customer must be logged in to retrieve their details."
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Customer.
|
||||
* tags:
|
||||
* - Customer
|
||||
* responses:
|
||||
@@ -20,7 +18,7 @@ import { defaultRelations, defaultFields } from "./"
|
||||
* $ref: "#/components/schemas/customer"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
const id = req.user.customer_id
|
||||
try {
|
||||
const customerService = req.scope.resolve("customerService")
|
||||
const customer = await customerService.retrieve(id, {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @oas [get] /customers/{id}/payment-methods
|
||||
* @oas [get] /customers/me/payment-methods
|
||||
* operationId: GetCustomersCustomerPaymentMethods
|
||||
* summary: Retrieve saved payment methods
|
||||
* description: "Retrieves a list of a Customer's saved payment methods. Payment methods are saved with Payment Providers and it is their responsibility to fetch saved methods."
|
||||
@@ -26,7 +26,7 @@
|
||||
* description: The data needed for the Payment Provider to use the saved payment method.
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
const id = req.user.customer_id
|
||||
try {
|
||||
const storeService = req.scope.resolve("storeService")
|
||||
const paymentProviderService = req.scope.resolve("paymentProviderService")
|
||||
@@ -37,11 +37,11 @@ export default async (req, res) => {
|
||||
const store = await storeService.retrieve(["payment_providers"])
|
||||
|
||||
const methods = await Promise.all(
|
||||
store.payment_providers.map(async next => {
|
||||
store.payment_providers.map(async (next) => {
|
||||
const provider = paymentProviderService.retrieveProvider(next)
|
||||
|
||||
const pMethods = await provider.retrieveSavedMethods(customer)
|
||||
return pMethods.map(m => ({
|
||||
return pMethods.map((m) => ({
|
||||
provider_id: next,
|
||||
data: m,
|
||||
}))
|
||||
|
||||
@@ -7,7 +7,6 @@ export default (app, container) => {
|
||||
const middlewareService = container.resolve("middlewareService")
|
||||
|
||||
app.use("/customers", route)
|
||||
route.param("id", middlewares.wrap(require("./authorize-customer").default))
|
||||
|
||||
// Inject plugin routes
|
||||
const routers = middlewareService.getRouters("store/customers")
|
||||
@@ -30,28 +29,28 @@ export default (app, container) => {
|
||||
// Authenticated endpoints
|
||||
route.use(middlewares.authenticate())
|
||||
|
||||
route.get("/:id", middlewares.wrap(require("./get-customer").default))
|
||||
route.post("/:id", middlewares.wrap(require("./update-customer").default))
|
||||
route.get("/me", middlewares.wrap(require("./get-customer").default))
|
||||
route.post("/me", middlewares.wrap(require("./update-customer").default))
|
||||
|
||||
route.get("/:id/orders", middlewares.wrap(require("./list-orders").default))
|
||||
route.get("/me/orders", middlewares.wrap(require("./list-orders").default))
|
||||
|
||||
route.post(
|
||||
"/:id/addresses",
|
||||
"/me/addresses",
|
||||
middlewares.wrap(require("./create-address").default)
|
||||
)
|
||||
|
||||
route.post(
|
||||
"/:id/addresses/:address_id",
|
||||
"/me/addresses/:address_id",
|
||||
middlewares.wrap(require("./update-address").default)
|
||||
)
|
||||
|
||||
route.delete(
|
||||
"/:id/addresses/:address_id",
|
||||
"/me/addresses/:address_id",
|
||||
middlewares.wrap(require("./delete-address").default)
|
||||
)
|
||||
|
||||
route.get(
|
||||
"/:id/payment-methods",
|
||||
"/me/payment-methods",
|
||||
middlewares.wrap(require("./get-payment-methods").default)
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from "../orders"
|
||||
|
||||
/**
|
||||
* @oas [get] /customers/{id}/orders
|
||||
* @oas [get] /customers/me/orders
|
||||
* operationId: GetCustomersCustomerOrders
|
||||
* summary: Retrieve Customer Orders
|
||||
* description: "Retrieves a list of a Customer's Orders."
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
* $ref: "#/components/schemas/order"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
const id = req.user.customer_id
|
||||
try {
|
||||
const orderService = req.scope.resolve("orderService")
|
||||
|
||||
@@ -42,13 +42,13 @@ export default async (req, res) => {
|
||||
let includeFields = []
|
||||
if ("fields" in req.query) {
|
||||
includeFields = req.query.fields.split(",")
|
||||
includeFields = includeFields.filter(f => allowedFields.includes(f))
|
||||
includeFields = includeFields.filter((f) => allowedFields.includes(f))
|
||||
}
|
||||
|
||||
let expandFields = []
|
||||
if ("expand" in req.query) {
|
||||
expandFields = req.query.expand.split(",")
|
||||
expandFields = expandFields.filter(f => allowedRelations.includes(f))
|
||||
expandFields = expandFields.filter((f) => allowedRelations.includes(f))
|
||||
}
|
||||
|
||||
const listConfig = {
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
|
||||
/**
|
||||
* @oas [post] /customers/{id}/password-token
|
||||
* @oas [post] /customers/password-token
|
||||
* operationId: PostCustomersCustomerPasswordToken
|
||||
* summary: Creates a reset password token
|
||||
* description: "Creates a reset password token to be used in a subsequent /reset-password request. The password token should be sent out of band e.g. via email and will not be returned."
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Customer.
|
||||
* tags:
|
||||
* - Customer
|
||||
* responses:
|
||||
@@ -15,9 +13,7 @@ import { MedusaError, Validator } from "medusa-core-utils"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
email: Validator.string()
|
||||
.email()
|
||||
.required(),
|
||||
email: Validator.string().email().required(),
|
||||
})
|
||||
|
||||
const { value, error } = schema.validate(req.body)
|
||||
|
||||
@@ -2,12 +2,11 @@ import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import jwt from "jsonwebtoken"
|
||||
|
||||
/**
|
||||
* @oas [post] /customers/{id}/reset-password
|
||||
* operationId: PostCustomersCustomerResetPassword
|
||||
* @oas [post] /customers/reset-password
|
||||
* operationId: PostCustomersResetPassword
|
||||
* summary: Resets Customer password
|
||||
* description: "Resets a Customer's password using a password token created by a previous /password-token request."
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Customer.
|
||||
* - (body) email=* {string} The Customer's email.
|
||||
* - (body) token=* {string} The password token created by a /password-token request.
|
||||
* - (body) password=* {string} The new password to set for the Customer.
|
||||
@@ -25,9 +24,7 @@ import jwt from "jsonwebtoken"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const schema = Validator.object().keys({
|
||||
email: Validator.string()
|
||||
.email()
|
||||
.required(),
|
||||
email: Validator.string().email().required(),
|
||||
token: Validator.string().required(),
|
||||
password: Validator.string().required(),
|
||||
})
|
||||
|
||||
@@ -2,12 +2,11 @@ import { Validator, MedusaError } from "medusa-core-utils"
|
||||
import { defaultRelations, defaultFields } from "./"
|
||||
|
||||
/**
|
||||
* @oas [post] /customers/{id}/addresses/{address_id}
|
||||
* @oas [post] /customers/me/addresses/{address_id}
|
||||
* operationId: PostCustomersCustomerAddressesAddress
|
||||
* summary: "Update a Shipping Address"
|
||||
* description: "Updates a Customer's saved Shipping Address."
|
||||
* parameters:
|
||||
* - (path) id=* {String} The Customer id.
|
||||
* - (path) address_id=* {String} The id of the Address to update.
|
||||
* requestBody:
|
||||
* content:
|
||||
@@ -31,7 +30,8 @@ import { defaultRelations, defaultFields } from "./"
|
||||
* $ref: "#/components/schemas/customer"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id, address_id } = req.params
|
||||
const id = req.user.customer_id
|
||||
const { address_id } = req.params
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
address: Validator.address().required(),
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { optional } from "joi"
|
||||
import { Validator, MedusaError } from "medusa-core-utils"
|
||||
import { defaultRelations, defaultFields } from "./"
|
||||
|
||||
/**
|
||||
* @oas [post] /customers/{id}
|
||||
* @oas [post] /customers/me
|
||||
* operationId: PostCustomersCustomer
|
||||
* summary: Update Customer details
|
||||
* description: "Updates a Customer's saved details."
|
||||
* parameters:
|
||||
* - (path) id=* {string} The id of the Customer.
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
@@ -29,6 +28,9 @@ import { defaultRelations, defaultFields } from "./"
|
||||
* phone:
|
||||
* description: "The Customer's phone number."
|
||||
* type: string
|
||||
* email:
|
||||
* description: "The email of the customer."
|
||||
* type: string
|
||||
* metadata:
|
||||
* description: "Metadata about the customer."
|
||||
* type: object
|
||||
@@ -45,7 +47,7 @@ import { defaultRelations, defaultFields } from "./"
|
||||
* $ref: "#/components/schemas/customer"
|
||||
*/
|
||||
export default async (req, res) => {
|
||||
const { id } = req.params
|
||||
const id = req.user.customer_id
|
||||
|
||||
const schema = Validator.object().keys({
|
||||
billing_address: Validator.address().optional(),
|
||||
@@ -53,6 +55,7 @@ export default async (req, res) => {
|
||||
last_name: Validator.string().optional(),
|
||||
password: Validator.string().optional(),
|
||||
phone: Validator.string().optional(),
|
||||
email: Validator.string().optional(),
|
||||
metadata: Validator.object().optional(),
|
||||
})
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ describe("GET /store/products", () => {
|
||||
it("calls get product from productSerice", () => {
|
||||
expect(ProductServiceMock.list).toHaveBeenCalledTimes(1)
|
||||
expect(ProductServiceMock.list).toHaveBeenCalledWith(
|
||||
{},
|
||||
{ status: ["published"] },
|
||||
{ relations: defaultRelations, skip: 0, take: 100 }
|
||||
)
|
||||
})
|
||||
@@ -43,7 +43,7 @@ describe("GET /store/products", () => {
|
||||
it("calls list from productSerice", () => {
|
||||
expect(ProductServiceMock.list).toHaveBeenCalledTimes(1)
|
||||
expect(ProductServiceMock.list).toHaveBeenCalledWith(
|
||||
{ is_giftcard: true },
|
||||
{ is_giftcard: true, status: ["published"] },
|
||||
{ relations: defaultRelations, skip: 0, take: 100 }
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { MedusaError, Validator } from "medusa-core-utils"
|
||||
import { defaultRelations } from "."
|
||||
|
||||
/**
|
||||
@@ -41,6 +42,8 @@ export default async (req, res) => {
|
||||
selector.is_giftcard = req.query.is_giftcard === "true"
|
||||
}
|
||||
|
||||
selector.status = ["published"]
|
||||
|
||||
const listConfig = {
|
||||
relations: defaultRelations,
|
||||
skip: offset,
|
||||
|
||||
@@ -23,10 +23,14 @@ export const defaultFields = [
|
||||
"id",
|
||||
"value",
|
||||
"label",
|
||||
"parent_return_reason_id",
|
||||
"description",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"deleted_at",
|
||||
]
|
||||
|
||||
export const defaultRelations = []
|
||||
export const defaultRelations = [
|
||||
"parent_return_reason",
|
||||
"return_reason_children",
|
||||
]
|
||||
|
||||
@@ -24,7 +24,7 @@ export default async (req, res) => {
|
||||
try {
|
||||
const returnReasonService = req.scope.resolve("returnReasonService")
|
||||
|
||||
const query = {}
|
||||
const query = { parent_return_reason_id: null}
|
||||
const data = await returnReasonService.list(query, {
|
||||
select: defaultFields,
|
||||
relations: defaultRelations,
|
||||
|
||||
@@ -28,10 +28,7 @@ describe("Get variant by id", () => {
|
||||
describe("get variant with prices", () => {
|
||||
let subject
|
||||
beforeAll(async () => {
|
||||
subject = await request(
|
||||
"GET",
|
||||
`/store/variants/${IdMap.getId("variantWithPrices")}`
|
||||
)
|
||||
subject = await request("GET", `/store/variants/variant_with_prices`)
|
||||
})
|
||||
it("successfully retrieves variants with prices", async () => {
|
||||
expect(subject.status).toEqual(200)
|
||||
|
||||
@@ -114,6 +114,9 @@ const t = async function({ directory, migrate, seedFile }) {
|
||||
const variants = p.variants
|
||||
delete p.variants
|
||||
|
||||
// default to the products being visible
|
||||
p.status = p.status || "published"
|
||||
|
||||
p.profile_id = defaultProfile.id
|
||||
if (p.is_giftcard) {
|
||||
p.profile_id = gcProfile.id
|
||||
|
||||
@@ -45,3 +45,4 @@ export { Swap } from "./models/swap"
|
||||
export { User } from "./models/user"
|
||||
export { DraftOrder } from "./models/draft-order"
|
||||
export { ReturnReason } from "./models/return-reason"
|
||||
export { Note } from "./models/note"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class allowBackorderSwaps1630505790603 implements MigrationInterface {
|
||||
name = 'allowBackorderSwaps1630505790603'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "swap" ADD "allow_backorder" boolean NOT NULL DEFAULT false`);
|
||||
await queryRunner.query(`ALTER TABLE "cart" ADD "payment_authorized_at" TIMESTAMP WITH TIME ZONE`);
|
||||
await queryRunner.query(`ALTER TYPE "swap_payment_status_enum" RENAME TO "swap_payment_status_enum_old"`);
|
||||
await queryRunner.query(`CREATE TYPE "swap_payment_status_enum" AS ENUM('not_paid', 'awaiting', 'captured', 'confirmed', 'canceled', 'difference_refunded', 'partially_refunded', 'refunded', 'requires_action')`);
|
||||
await queryRunner.query(`ALTER TABLE "swap" ALTER COLUMN "payment_status" TYPE "swap_payment_status_enum" USING "payment_status"::"text"::"swap_payment_status_enum"`);
|
||||
await queryRunner.query(`DROP TYPE "swap_payment_status_enum_old"`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TYPE "swap_payment_status_enum_old" AS ENUM('not_paid', 'awaiting', 'captured', 'canceled', 'difference_refunded', 'partially_refunded', 'refunded', 'requires_action')`);
|
||||
await queryRunner.query(`ALTER TABLE "swap" ALTER COLUMN "payment_status" TYPE "swap_payment_status_enum_old" USING "payment_status"::"text"::"swap_payment_status_enum_old"`);
|
||||
await queryRunner.query(`DROP TYPE "swap_payment_status_enum"`);
|
||||
await queryRunner.query(`ALTER TYPE "swap_payment_status_enum_old" RENAME TO "swap_payment_status_enum"`);
|
||||
await queryRunner.query(`ALTER TABLE "cart" DROP COLUMN "payment_authorized_at"`);
|
||||
await queryRunner.query(`ALTER TABLE "swap" DROP COLUMN "allow_backorder"`);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user