diff --git a/.changeset/tasty-glasses-cheat.md b/.changeset/tasty-glasses-cheat.md new file mode 100644 index 0000000000..578e690302 --- /dev/null +++ b/.changeset/tasty-glasses-cheat.md @@ -0,0 +1,5 @@ +--- +"medusa-test-utils": patch +--- + +Chore/integration tests modules utils diff --git a/integration-tests/.env.test b/integration-tests/.env.test index d6f87184c3..79690313e4 100644 --- a/integration-tests/.env.test +++ b/integration-tests/.env.test @@ -2,3 +2,4 @@ DB_HOST=localhost DB_USERNAME=postgres DB_PASSWORD='' +LOG_LEVEL=error \ No newline at end of file diff --git a/integration-tests/modules/__tests__/api-key/admin/api-key.spec.ts b/integration-tests/modules/__tests__/api-key/admin/api-key.spec.ts index 8d3bdc5d32..0b2559d44b 100644 --- a/integration-tests/modules/__tests__/api-key/admin/api-key.spec.ts +++ b/integration-tests/modules/__tests__/api-key/admin/api-key.spec.ts @@ -1,13 +1,8 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ApiKeyType } from "@medusajs/utils" -import { IApiKeyModuleService, IRegionModuleService } from "@medusajs/types" +import { IRegionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,182 +11,171 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("API Keys - Admin", () => { - let dbConnection - let appContainer - let shutdownServer - let service: IApiKeyModuleService - let regionService: IRegionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("API Keys - Admin", () => { + let regionService: IRegionModuleService + let container - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - service = appContainer.resolve(ModuleRegistrationName.API_KEY) - regionService = appContainer.resolve(ModuleRegistrationName.REGION) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - // TODO: Once teardown doesn't skip constraint checks and cascades, we can remove this - const existingRegions = await regionService.list({}) - await regionService.delete(existingRegions.map((r) => r.id)) - await db.teardown() - }) - - it("should correctly implement the entire lifecycle of an api key", async () => { - const api = useApi() as any - const created = await api.post( - `/admin/api-keys`, - { - title: "Test Secret Key", - type: ApiKeyType.SECRET, - }, - adminHeaders - ) - - expect(created.status).toEqual(200) - expect(created.data.apiKey).toEqual( - expect.objectContaining({ - id: created.data.apiKey.id, - title: "Test Secret Key", - created_by: "admin_user", + beforeAll(async () => { + container = getContainer() + regionService = container.resolve( + ModuleRegistrationName.REGION + ) as IRegionModuleService }) - ) - // On create we get the token in raw form so we can store it. - expect(created.data.apiKey.token).toContain("sk_") - const updated = await api.post( - `/admin/api-keys/${created.data.apiKey.id}`, - { - title: "Updated Secret Key", - }, - adminHeaders - ) - - expect(updated.status).toEqual(200) - expect(updated.data.apiKey).toEqual( - expect.objectContaining({ - id: created.data.apiKey.id, - title: "Updated Secret Key", + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, container) }) - ) - const revoked = await api.post( - `/admin/api-keys/${created.data.apiKey.id}/revoke`, - {}, - adminHeaders - ) - - expect(revoked.status).toEqual(200) - expect(revoked.data.apiKey).toEqual( - expect.objectContaining({ - id: created.data.apiKey.id, - revoked_by: "admin_user", + afterEach(async () => { + // TODO: Once teardown doesn't skip constraint checks and cascades, we can remove this + const existingRegions = await regionService.list({}) + await regionService.delete(existingRegions.map((r) => r.id)) }) - ) - expect(revoked.data.apiKey.revoked_at).toBeTruthy() - const deleted = await api.delete( - `/admin/api-keys/${created.data.apiKey.id}`, - adminHeaders - ) - const listedApiKeys = await api.get(`/admin/api-keys`, adminHeaders) - - expect(deleted.status).toEqual(200) - expect(listedApiKeys.data.apiKeys).toHaveLength(0) - }) - - it("can use a secret api key for authentication", async () => { - const api = useApi() as any - const created = await api.post( - `/admin/api-keys`, - { - title: "Test Secret Key", - type: ApiKeyType.SECRET, - }, - adminHeaders - ) - - const createdRegion = await api.post( - `/admin/regions`, - { - name: "Test Region", - currency_code: "usd", - countries: ["us", "ca"], - }, - { - auth: { - username: created.data.apiKey.token, - }, - } - ) - - expect(createdRegion.status).toEqual(200) - expect(createdRegion.data.region.name).toEqual("Test Region") - }) - - it("falls back to other mode of authentication when an api key is not valid", async () => { - const api = useApi() as any - const created = await api.post( - `/admin/api-keys`, - { - title: "Test Secret Key", - type: ApiKeyType.SECRET, - }, - adminHeaders - ) - - await api.post( - `/admin/api-keys/${created.data.apiKey.id}/revoke`, - {}, - adminHeaders - ) - - const err = await api - .post( - `/admin/regions`, - { - name: "Test Region", - currency_code: "usd", - countries: ["us", "ca"], - }, - { - auth: { - username: created.data.apiKey.token, + it("should correctly implement the entire lifecycle of an api key", async () => { + const created = await api.post( + `/admin/api-keys`, + { + title: "Test Secret Key", + type: ApiKeyType.SECRET, }, - } - ) - .catch((e) => e.message) + adminHeaders + ) - const createdRegion = await api.post( - `/admin/regions`, - { - name: "Test Region", - currency_code: "usd", - countries: ["us", "ca"], - }, - { - auth: { - username: created.data.apiKey.token, - }, - ...adminHeaders, - } - ) + expect(created.status).toEqual(200) + expect(created.data.apiKey).toEqual( + expect.objectContaining({ + id: created.data.apiKey.id, + title: "Test Secret Key", + created_by: "admin_user", + }) + ) + // On create we get the token in raw form so we can store it. + expect(created.data.apiKey.token).toContain("sk_") - expect(err).toEqual("Request failed with status code 401") - expect(createdRegion.status).toEqual(200) - expect(createdRegion.data.region.name).toEqual("Test Region") - }) + const updated = await api.post( + `/admin/api-keys/${created.data.apiKey.id}`, + { + title: "Updated Secret Key", + }, + adminHeaders + ) + + expect(updated.status).toEqual(200) + expect(updated.data.apiKey).toEqual( + expect.objectContaining({ + id: created.data.apiKey.id, + title: "Updated Secret Key", + }) + ) + + const revoked = await api.post( + `/admin/api-keys/${created.data.apiKey.id}/revoke`, + {}, + adminHeaders + ) + + expect(revoked.status).toEqual(200) + expect(revoked.data.apiKey).toEqual( + expect.objectContaining({ + id: created.data.apiKey.id, + revoked_by: "admin_user", + }) + ) + expect(revoked.data.apiKey.revoked_at).toBeTruthy() + + const deleted = await api.delete( + `/admin/api-keys/${created.data.apiKey.id}`, + adminHeaders + ) + const listedApiKeys = await api.get(`/admin/api-keys`, adminHeaders) + + expect(deleted.status).toEqual(200) + expect(listedApiKeys.data.apiKeys).toHaveLength(0) + }) + + it("can use a secret api key for authentication", async () => { + const created = await api.post( + `/admin/api-keys`, + { + title: "Test Secret Key", + type: ApiKeyType.SECRET, + }, + adminHeaders + ) + + const createdRegion = await api.post( + `/admin/regions`, + { + name: "Test Region", + currency_code: "usd", + countries: ["us", "ca"], + }, + { + auth: { + username: created.data.apiKey.token, + }, + } + ) + + expect(createdRegion.status).toEqual(200) + expect(createdRegion.data.region.name).toEqual("Test Region") + }) + + it("falls back to other mode of authentication when an api key is not valid", async () => { + const created = await api.post( + `/admin/api-keys`, + { + title: "Test Secret Key", + type: ApiKeyType.SECRET, + }, + adminHeaders + ) + + await api.post( + `/admin/api-keys/${created.data.apiKey.id}/revoke`, + {}, + adminHeaders + ) + + const err = await api + .post( + `/admin/regions`, + { + name: "Test Region", + currency_code: "usd", + countries: ["us", "ca"], + }, + { + auth: { + username: created.data.apiKey.token, + }, + } + ) + .catch((e) => e.message) + + const createdRegion = await api.post( + `/admin/regions`, + { + name: "Test Region", + currency_code: "usd", + countries: ["us", "ca"], + }, + { + auth: { + username: created.data.apiKey.token, + }, + ...adminHeaders, + } + ) + + expect(err).toEqual("Request failed with status code 401") + expect(createdRegion.status).toEqual(200) + expect(createdRegion.data.region.name).toEqual("Test Region") + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/auth/admin/email-password-provider.spec.ts b/integration-tests/modules/__tests__/auth/admin/email-password-provider.spec.ts index e0518d1e0e..4624459ca9 100644 --- a/integration-tests/modules/__tests__/auth/admin/email-password-provider.spec.ts +++ b/integration-tests/modules/__tests__/auth/admin/email-password-provider.spec.ts @@ -1,135 +1,117 @@ import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IAuthModuleService, ICustomerModuleService } from "@medusajs/types" -import path from "path" import Scrypt from "scrypt-kdf" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import adminSeeder from "../../../../helpers/admin-seeder" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("POST /auth/emailpass", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /auth/emailpass", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await adminSeeder(dbConnection) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - const password = "supersecret" - const email = "test@test.com" - - it("should return a token on successful login", async () => { - const passwordHash = ( - await Scrypt.kdf(password, { logN: 15, r: 8, p: 1 }) - ).toString("base64") - const authService: IAuthModuleService = appContainer.resolve( - ModuleRegistrationName.AUTH - ) - - await authService.create({ - provider: "emailpass", - entity_id: email, - scope: "admin", - provider_metadata: { - password: passwordHash, - }, - }) - - const api = useApi() as any - const response = await api - .post(`/auth/admin/emailpass`, { - email: email, - password: password, + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - .catch((e) => e) - expect(response.status).toEqual(200) - expect(response.data).toEqual( - expect.objectContaining({ - token: expect.any(String), + beforeEach(async () => { + await adminSeeder(dbConnection) }) - ) - }) - it("should throw an error upon incorrect password", async () => { - const passwordHash = ( - await Scrypt.kdf(password, { logN: 15, r: 8, p: 1 }) - ).toString("base64") - const authService: IAuthModuleService = appContainer.resolve( - ModuleRegistrationName.AUTH - ) + const password = "supersecret" + const email = "test@test.com" - await authService.create({ - provider: "emailpass", - entity_id: email, - scope: "admin", - provider_metadata: { - password: passwordHash, - }, - }) + it("should return a token on successful login", async () => { + const passwordHash = ( + await Scrypt.kdf(password, { logN: 15, r: 8, p: 1 }) + ).toString("base64") + const authService: IAuthModuleService = appContainer.resolve( + ModuleRegistrationName.AUTH + ) - const api = useApi() as any - const error = await api - .post(`/auth/admin/emailpass`, { - email: email, - password: "incorrect-password", + await authService.create({ + provider: "emailpass", + entity_id: email, + scope: "admin", + provider_metadata: { + password: passwordHash, + }, + }) + + const response = await api + .post(`/auth/admin/emailpass`, { + email: email, + password: password, + }) + .catch((e) => e) + + expect(response.status).toEqual(200) + expect(response.data).toEqual( + expect.objectContaining({ + token: expect.any(String), + }) + ) }) - .catch((e) => e) - expect(error.response.status).toEqual(401) - expect(error.response.data).toEqual({ - type: "unauthorized", - message: "Invalid email or password", - }) - }) + it("should throw an error upon incorrect password", async () => { + const passwordHash = ( + await Scrypt.kdf(password, { logN: 15, r: 8, p: 1 }) + ).toString("base64") + const authService: IAuthModuleService = appContainer.resolve( + ModuleRegistrationName.AUTH + ) - it.skip("should throw an error upon logging in with a non existing auth user", async () => { - const passwordHash = ( - await Scrypt.kdf(password, { logN: 15, r: 8, p: 1 }) - ).toString("base64") + await authService.create({ + provider: "emailpass", + entity_id: email, + scope: "admin", + provider_metadata: { + password: passwordHash, + }, + }) - const api = useApi() as any - const error = await api - .post(`/auth/admin/emailpass`, { - email: "should-not-exist", - password: "should-not-exist", + const error = await api + .post(`/auth/admin/emailpass`, { + email: email, + password: "incorrect-password", + }) + .catch((e) => e) + + expect(error.response.status).toEqual(401) + expect(error.response.data).toEqual({ + type: "unauthorized", + message: "Invalid email or password", + }) }) - .catch((e) => e) - // TODO: This is creating a user with a scope of admin. The client consuming the auth service - // should reject this if its not being created by an admin user - expect(error.response.status).toEqual(401) - expect(error.response.data).toEqual({ - type: "unauthorized", - message: "Invalid email or password", + it.skip("should throw an error upon logging in with a non existing auth user", async () => { + const passwordHash = ( + await Scrypt.kdf(password, { logN: 15, r: 8, p: 1 }) + ).toString("base64") + + const error = await api + .post(`/auth/admin/emailpass`, { + email: "should-not-exist", + password: "should-not-exist", + }) + .catch((e) => e) + + // TODO: This is creating a user with a scope of admin. The client consuming the auth service + // should reject this if its not being created by an admin user + expect(error.response.status).toEqual(401) + expect(error.response.data).toEqual({ + type: "unauthorized", + message: "Invalid email or password", + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/cart/store/add-promotions-to-cart.spec.ts b/integration-tests/modules/__tests__/cart/store/add-promotions-to-cart.spec.ts index 22229b272d..dc8ddb215f 100644 --- a/integration-tests/modules/__tests__/cart/store/add-promotions-to-cart.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/add-promotions-to-cart.spec.ts @@ -6,319 +6,296 @@ import { } from "@medusajs/modules-sdk" import { ICartModuleService, IPromotionModuleService } from "@medusajs/types" import { PromotionType } from "@medusajs/utils" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import adminSeeder from "../../../../helpers/admin-seeder" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Store Carts API: Add promotions to cart", () => { - let dbConnection - let appContainer - let shutdownServer - let cartModuleService: ICartModuleService - let promotionModuleService: IPromotionModuleService - let remoteLinkService: RemoteLink +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Store Carts API: Add promotions to cart", () => { + let appContainer + let cartModuleService: ICartModuleService + let promotionModuleService: IPromotionModuleService + let remoteLinkService: RemoteLink - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - remoteLinkService = appContainer.resolve(LinkModuleUtils.REMOTE_LINK) - }) + beforeAll(async () => { + appContainer = getContainer() + cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) + remoteLinkService = appContainer.resolve(LinkModuleUtils.REMOTE_LINK) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) + }) - beforeEach(async () => { - await adminSeeder(dbConnection) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - describe("POST /store/carts/:id/promotions", () => { - it("should add line item adjustments to a cart based on promotions", async () => { - const appliedPromotion = await promotionModuleService.create({ - code: "PROMOTION_APPLIED", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "items", - allocation: "each", - value: "300", - apply_to_quantity: 1, - max_quantity: 1, - target_rules: [ - { - attribute: "product_id", - operator: "eq", - values: "prod_tshirt", + describe("POST /store/carts/:id/promotions", () => { + it("should add line item adjustments to a cart based on promotions", async () => { + const appliedPromotion = await promotionModuleService.create({ + code: "PROMOTION_APPLIED", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "items", + allocation: "each", + value: "300", + apply_to_quantity: 1, + max_quantity: 1, + target_rules: [ + { + attribute: "product_id", + operator: "eq", + values: "prod_tshirt", + }, + ], }, - ], - }, - }) + }) - const createdPromotion = await promotionModuleService.create({ - code: "PROMOTION_TEST", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "items", - allocation: "across", - value: "1000", - apply_to_quantity: 1, - target_rules: [ - { - attribute: "product_id", - operator: "eq", - values: "prod_mat", + const createdPromotion = await promotionModuleService.create({ + code: "PROMOTION_TEST", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "items", + allocation: "across", + value: "1000", + apply_to_quantity: 1, + target_rules: [ + { + attribute: "product_id", + operator: "eq", + values: "prod_mat", + }, + ], }, - ], - }, - }) + }) - const cart = await cartModuleService.create({ - currency_code: "usd", - items: [ - // Adjustment to add - { - id: "item-1", - unit_price: 2000, - quantity: 1, - title: "Test item", - product_id: "prod_mat", - } as any, - // This adjustment will be removed and recreated - { - id: "item-2", - unit_price: 1000, - quantity: 1, - title: "Test item", - product_id: "prod_tshirt", - } as any, - ], - }) - - // Adjustment to keep - const [lineItemAdjustment] = - await cartModuleService.addLineItemAdjustments([ - { - code: appliedPromotion.code!, - amount: 300, - item_id: "item-2", - promotion_id: appliedPromotion.id, - }, - ]) - - await remoteLinkService.create({ - [Modules.CART]: { cart_id: cart.id }, - [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, - }) - - const api = useApi() as any - - const created = await api.post(`/store/carts/${cart.id}/promotions`, { - promo_codes: [createdPromotion.code], - }) - - expect(created.status).toEqual(200) - expect(created.data.cart).toEqual( - expect.objectContaining({ - id: expect.any(String), - items: expect.arrayContaining([ - expect.objectContaining({ - id: "item-1", - adjustments: expect.arrayContaining([ - expect.objectContaining({ - code: createdPromotion.code, - amount: 1000, - }), - ]), - }), - expect.objectContaining({ - adjustments: expect.arrayContaining([ - expect.objectContaining({ - id: expect.not.stringContaining(lineItemAdjustment.id), - code: appliedPromotion.code, - amount: 300, - }), - ]), - }), - ]), - }) - ) - }) - - it("should add shipping method adjustments to a cart based on promotions", async () => { - const [appliedPromotion] = await promotionModuleService.create([ - { - code: "PROMOTION_APPLIED", - type: PromotionType.STANDARD, - rules: [ - { - attribute: "customer_id", - operator: "in", - values: ["cus_test"], - }, - { - attribute: "currency_code", - operator: "in", - values: ["eur"], - }, - ], - application_method: { - type: "fixed", - target_type: "shipping_methods", - allocation: "each", - value: "100", - max_quantity: 1, - target_rules: [ + const cart = await cartModuleService.create({ + currency_code: "usd", + items: [ + // Adjustment to add { - attribute: "name", - operator: "in", - values: ["express"], - }, - ], - }, - }, - ]) - - const [newPromotion] = await promotionModuleService.create([ - { - code: "PROMOTION_NEW", - type: PromotionType.STANDARD, - rules: [ - { - attribute: "customer_id", - operator: "in", - values: ["cus_test"], - }, - { - attribute: "currency_code", - operator: "in", - values: ["eur"], - }, - ], - application_method: { - type: "fixed", - target_type: "shipping_methods", - allocation: "each", - value: "200", - max_quantity: 1, - target_rules: [ + id: "item-1", + unit_price: 2000, + quantity: 1, + title: "Test item", + product_id: "prod_mat", + } as any, + // This adjustment will be removed and recreated { - attribute: "name", - operator: "in", - values: ["express", "standard"], - }, + id: "item-2", + unit_price: 1000, + quantity: 1, + title: "Test item", + product_id: "prod_tshirt", + } as any, ], - }, - }, - ]) + }) - const cart = await cartModuleService.create({ - currency_code: "eur", - customer_id: "cus_test", - items: [ - { - unit_price: 2000, - quantity: 1, - title: "Test item", - product_id: "prod_mat", - } as any, - ], - }) + // Adjustment to keep + const [lineItemAdjustment] = + await cartModuleService.addLineItemAdjustments([ + { + code: appliedPromotion.code!, + amount: 300, + item_id: "item-2", + promotion_id: appliedPromotion.id, + }, + ]) - const [express, standard] = await cartModuleService.addShippingMethods( - cart.id, - [ - { - amount: 500, - name: "express", - }, - { - amount: 500, - name: "standard", - }, - ] - ) + await remoteLinkService.create({ + [Modules.CART]: { cart_id: cart.id }, + [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, + }) - await remoteLinkService.create({ - [Modules.CART]: { cart_id: cart.id }, - [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, - }) + const created = await api.post(`/store/carts/${cart.id}/promotions`, { + promo_codes: [createdPromotion.code], + }) - const [adjustment] = await cartModuleService.addShippingMethodAdjustments( - cart.id, - [ - { - shipping_method_id: express.id, - amount: 100, - code: appliedPromotion.code!, - }, - ] - ) - - const api = useApi() as any - - const created = await api.post(`/store/carts/${cart.id}/promotions`, { - promo_codes: [newPromotion.code], - }) - - expect(created.status).toEqual(200) - expect(created.data.cart).toEqual( - expect.objectContaining({ - id: expect.any(String), - items: expect.arrayContaining([ + expect(created.status).toEqual(200) + expect(created.data.cart).toEqual( expect.objectContaining({ id: expect.any(String), - }), - ]), - shipping_methods: expect.arrayContaining([ - expect.objectContaining({ - id: express.id, - adjustments: expect.arrayContaining([ + items: expect.arrayContaining([ expect.objectContaining({ - id: expect.any(String), - amount: 200, - code: newPromotion.code, + id: "item-1", + adjustments: expect.arrayContaining([ + expect.objectContaining({ + code: createdPromotion.code, + amount: 1000, + }), + ]), }), expect.objectContaining({ - id: expect.not.stringContaining(adjustment.id), - amount: 100, - code: appliedPromotion.code, + adjustments: expect.arrayContaining([ + expect.objectContaining({ + id: expect.not.stringContaining(lineItemAdjustment.id), + code: appliedPromotion.code, + amount: 300, + }), + ]), }), ]), - }), + }) + ) + }) + + it("should add shipping method adjustments to a cart based on promotions", async () => { + const [appliedPromotion] = await promotionModuleService.create([ + { + code: "PROMOTION_APPLIED", + type: PromotionType.STANDARD, + rules: [ + { + attribute: "customer_id", + operator: "in", + values: ["cus_test"], + }, + { + attribute: "currency_code", + operator: "in", + values: ["eur"], + }, + ], + application_method: { + type: "fixed", + target_type: "shipping_methods", + allocation: "each", + value: "100", + max_quantity: 1, + target_rules: [ + { + attribute: "name", + operator: "in", + values: ["express"], + }, + ], + }, + }, + ]) + + const [newPromotion] = await promotionModuleService.create([ + { + code: "PROMOTION_NEW", + type: PromotionType.STANDARD, + rules: [ + { + attribute: "customer_id", + operator: "in", + values: ["cus_test"], + }, + { + attribute: "currency_code", + operator: "in", + values: ["eur"], + }, + ], + application_method: { + type: "fixed", + target_type: "shipping_methods", + allocation: "each", + value: "200", + max_quantity: 1, + target_rules: [ + { + attribute: "name", + operator: "in", + values: ["express", "standard"], + }, + ], + }, + }, + ]) + + const cart = await cartModuleService.create({ + currency_code: "eur", + customer_id: "cus_test", + items: [ + { + unit_price: 2000, + quantity: 1, + title: "Test item", + product_id: "prod_mat", + } as any, + ], + }) + + const [express, standard] = + await cartModuleService.addShippingMethods(cart.id, [ + { + amount: 500, + name: "express", + }, + { + amount: 500, + name: "standard", + }, + ]) + + await remoteLinkService.create({ + [Modules.CART]: { cart_id: cart.id }, + [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, + }) + + const [adjustment] = + await cartModuleService.addShippingMethodAdjustments(cart.id, [ + { + shipping_method_id: express.id, + amount: 100, + code: appliedPromotion.code!, + }, + ]) + + const created = await api.post(`/store/carts/${cart.id}/promotions`, { + promo_codes: [newPromotion.code], + }) + + expect(created.status).toEqual(200) + expect(created.data.cart).toEqual( expect.objectContaining({ - id: standard.id, - adjustments: [ + id: expect.any(String), + items: expect.arrayContaining([ expect.objectContaining({ id: expect.any(String), - amount: 200, - code: newPromotion.code, }), - ], - }), - ]), + ]), + shipping_methods: expect.arrayContaining([ + expect.objectContaining({ + id: express.id, + adjustments: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + amount: 200, + code: newPromotion.code, + }), + expect.objectContaining({ + id: expect.not.stringContaining(adjustment.id), + amount: 100, + code: appliedPromotion.code, + }), + ]), + }), + expect.objectContaining({ + id: standard.id, + adjustments: [ + expect.objectContaining({ + id: expect.any(String), + amount: 200, + code: newPromotion.code, + }), + ], + }), + ]), + }) + ) }) - ) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts b/integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts index 411db50078..6f54b999d1 100644 --- a/integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts @@ -19,797 +19,795 @@ import { IRegionModuleService, ISalesChannelModuleService, } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import adminSeeder from "../../../../helpers/admin-seeder" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Carts workflows", () => { - let dbConnection - let appContainer - let shutdownServer - let cartModuleService: ICartModuleService - let regionModuleService: IRegionModuleService - let scModuleService: ISalesChannelModuleService - let customerModule: ICustomerModuleService - let productModule: IProductModuleService - let pricingModule: IPricingModuleService - let paymentModule: IPaymentModuleService - let remoteLink, remoteQuery +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Carts workflows", () => { + let appContainer + let cartModuleService: ICartModuleService + let regionModuleService: IRegionModuleService + let scModuleService: ISalesChannelModuleService + let customerModule: ICustomerModuleService + let productModule: IProductModuleService + let pricingModule: IPricingModuleService + let paymentModule: IPaymentModuleService + let remoteLink, remoteQuery - let defaultRegion + let defaultRegion - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) - regionModuleService = appContainer.resolve(ModuleRegistrationName.REGION) - scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL) - customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER) - productModule = appContainer.resolve(ModuleRegistrationName.PRODUCT) - pricingModule = appContainer.resolve(ModuleRegistrationName.PRICING) - paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT) - remoteLink = appContainer.resolve("remoteLink") - remoteQuery = appContainer.resolve("remoteQuery") - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await adminSeeder(dbConnection) - - // Here, so we don't have to create a region for each test - defaultRegion = await regionModuleService.create({ - name: "Default Region", - currency_code: "dkk", - }) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - describe("CreateCartWorkflow", () => { - it("should create a cart", async () => { - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", + beforeAll(async () => { + appContainer = getContainer() + cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) + regionModuleService = appContainer.resolve( + ModuleRegistrationName.REGION + ) + scModuleService = appContainer.resolve( + ModuleRegistrationName.SALES_CHANNEL + ) + customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER) + productModule = appContainer.resolve(ModuleRegistrationName.PRODUCT) + pricingModule = appContainer.resolve(ModuleRegistrationName.PRICING) + paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT) + remoteLink = appContainer.resolve("remoteLink") + remoteQuery = appContainer.resolve("remoteQuery") }) - const salesChannel = await scModuleService.create({ - name: "Webshop", + beforeEach(async () => { + await adminSeeder(dbConnection) + + // Here, so we don't have to create a region for each test + defaultRegion = await regionModuleService.create({ + name: "Default Region", + currency_code: "dkk", + }) }) - const [product] = await productModule.create([ - { - title: "Test product", - variants: [ - { - title: "Test variant", - }, - ], - }, - ]) - - const priceSet = await pricingModule.create({ - prices: [ - { - amount: 3000, + describe("CreateCartWorkflow", () => { + it("should create a cart", async () => { + const region = await regionModuleService.create({ + name: "US", currency_code: "usd", - }, - ], - }) + }) - await remoteLink.create([ - { - productService: { - variant_id: product.variants[0].id, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }, - ]) + const salesChannel = await scModuleService.create({ + name: "Webshop", + }) - const { result } = await createCartWorkflow(appContainer).run({ - input: { - email: "tony@stark.com", - currency_code: "usd", - region_id: region.id, - sales_channel_id: salesChannel.id, - items: [ + const [product] = await productModule.create([ { - variant_id: product.variants[0].id, - quantity: 1, + title: "Test product", + variants: [ + { + title: "Test variant", + }, + ], }, - ], - }, - }) + ]) - const cart = await cartModuleService.retrieve(result.id, { - relations: ["items"], - }) - - expect(cart).toEqual( - expect.objectContaining({ - currency_code: "usd", - email: "tony@stark.com", - region_id: region.id, - sales_channel_id: salesChannel.id, - customer_id: expect.any(String), - items: expect.arrayContaining([ - expect.objectContaining({ - quantity: 1, - unit_price: 3000, - }), - ]), - }) - ) - }) - - it("should throw when no regions exist", async () => { - await regionModuleService.delete(defaultRegion.id) - - const { errors } = await createCartWorkflow(appContainer).run({ - input: { - email: "tony@stark.com", - currency_code: "usd", - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "find-one-or-any-region", - handlerType: "invoke", - error: new Error("No regions found"), - }, - ]) - }) - - it("should throw if sales channel is disabled", async () => { - const api = useApi() as any - - const salesChannel = await scModuleService.create({ - name: "Webshop", - is_disabled: true, - }) - - const { errors } = await createCartWorkflow(appContainer).run({ - input: { - sales_channel_id: salesChannel.id, - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "find-sales-channel", - handlerType: "invoke", - error: new Error( - `Unable to assign cart to disabled Sales Channel: Webshop` - ), - }, - ]) - }) - - describe("compensation", () => { - it("should delete created customer if cart-creation fails", async () => { - expect.assertions(2) - const workflow = createCartWorkflow(appContainer) - - workflow.appendAction("throw", findOrCreateCustomerStepId, { - invoke: async function failStep() { - throw new Error(`Failed to create cart`) - }, - }) - - const { errors } = await workflow.run({ - input: { - currency_code: "usd", - email: "tony@stark-industries.com", - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "throw", - handlerType: "invoke", - error: new Error(`Failed to create cart`), - }, - ]) - - const customers = await customerModule.list({ - email: "tony@stark-industries.com", - }) - - expect(customers).toHaveLength(0) - }) - - it("should not delete existing customer if cart-creation fails", async () => { - expect.assertions(2) - const workflow = createCartWorkflow(appContainer) - - workflow.appendAction("throw", findOrCreateCustomerStepId, { - invoke: async function failStep() { - throw new Error(`Failed to create cart`) - }, - }) - - const customer = await customerModule.create({ - email: "tony@stark-industries.com", - }) - - const { errors } = await workflow.run({ - input: { - currency_code: "usd", - customer_id: customer.id, - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "throw", - handlerType: "invoke", - error: new Error(`Failed to create cart`), - }, - ]) - - const customers = await customerModule.list({ - email: "tony@stark-industries.com", - }) - - expect(customers).toHaveLength(1) - }) - }) - }) - - describe("AddToCartWorkflow", () => { - it("should add item to cart", async () => { - let cart = await cartModuleService.create({ - currency_code: "usd", - }) - - const [product] = await productModule.create([ - { - title: "Test product", - variants: [ - { - title: "Test variant", - }, - ], - }, - ]) - - const priceSet = await pricingModule.create({ - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - }) - - await remoteLink.create([ - { - productService: { - variant_id: product.variants[0].id, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }, - ]) - - cart = await cartModuleService.retrieve(cart.id, { - select: ["id", "region_id", "currency_code"], - }) - - await addToCartWorkflow(appContainer).run({ - input: { - items: [ - { - variant_id: product.variants[0].id, - quantity: 1, - }, - ], - cart, - }, - }) - - cart = await cartModuleService.retrieve(cart.id, { - relations: ["items"], - }) - - expect(cart).toEqual( - expect.objectContaining({ - id: cart.id, - currency_code: "usd", - items: expect.arrayContaining([ - expect.objectContaining({ - unit_price: 3000, - quantity: 1, - title: "Test variant", - }), - ]), - }) - ) - }) - - it("should throw if no price sets for variant exist", async () => { - const cart = await cartModuleService.create({ - currency_code: "usd", - }) - - const [product] = await productModule.create([ - { - title: "Test product", - variants: [ - { - title: "Test variant", - }, - ], - }, - ]) - - const { errors } = await addToCartWorkflow(appContainer).run({ - input: { - items: [ - { - variant_id: product.variants[0].id, - quantity: 1, - }, - ], - cart, - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "get-variant-price-sets", - handlerType: "invoke", - error: new Error( - `Variants with IDs ${product.variants[0].id} do not have a price` - ), - }, - ]) - }) - - it("should throw if variant does not exist", async () => { - const cart = await cartModuleService.create({ - currency_code: "usd", - }) - - const { errors } = await addToCartWorkflow(appContainer).run({ - input: { - items: [ - { - variant_id: "prva_foo", - quantity: 1, - }, - ], - cart, - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "validate-variants-exist", - handlerType: "invoke", - error: new Error(`Variants with IDs prva_foo do not exist`), - }, - ]) - }) - }) - - describe("updateLineItemInCartWorkflow", () => { - it("should update item in cart", async () => { - const [product] = await productModule.create([ - { - title: "Test product", - variants: [ - { - title: "Test variant", - }, - ], - }, - ]) - - const priceSet = await pricingModule.create({ - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - }) - - await remoteLink.create([ - { - productService: { - variant_id: product.variants[0].id, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }, - ]) - - let cart = await cartModuleService.create({ - currency_code: "usd", - items: [ - { - variant_id: product.variants[0].id, - quantity: 1, - unit_price: 5000, - title: "Test item", - }, - ], - }) - - cart = await cartModuleService.retrieve(cart.id, { - select: ["id", "region_id", "currency_code"], - relations: ["items", "items.variant_id", "items.metadata"], - }) - - const item = cart.items?.[0]! - - await updateLineItemInCartWorkflow(appContainer).run({ - input: { - cart, - item, - update: { - metadata: { - foo: "bar", - }, - quantity: 2, - }, - }, - throwOnError: false, - }) - - const updatedItem = await cartModuleService.retrieveLineItem(item.id) - - expect(updatedItem).toEqual( - expect.objectContaining({ - id: item.id, - unit_price: 3000, - quantity: 2, - title: "Test item", - }) - ) - }) - - describe("compensation", () => { - it("should revert line item update to original state", async () => { - expect.assertions(2) - const workflow = updateLineItemInCartWorkflow(appContainer) - - workflow.appendAction("throw", updateLineItemsStepId, { - invoke: async function failStep() { - throw new Error(`Failed to update something after line items`) - }, - }) - - const [product] = await productModule.create([ - { - title: "Test product", - variants: [ + const priceSet = await pricingModule.create({ + prices: [ { - title: "Test variant", + amount: 3000, + currency_code: "usd", }, ], - }, - ]) + }) - let cart = await cartModuleService.create({ - currency_code: "usd", - items: [ + await remoteLink.create([ { - variant_id: product.variants[0].id, - quantity: 1, - unit_price: 3000, - title: "Test item", + productService: { + variant_id: product.variants[0].id, + }, + pricingService: { + price_set_id: priceSet.id, + }, }, - ], + ]) + + const { result } = await createCartWorkflow(appContainer).run({ + input: { + email: "tony@stark.com", + currency_code: "usd", + region_id: region.id, + sales_channel_id: salesChannel.id, + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + }, + ], + }, + }) + + const cart = await cartModuleService.retrieve(result.id, { + relations: ["items"], + }) + + expect(cart).toEqual( + expect.objectContaining({ + currency_code: "usd", + email: "tony@stark.com", + region_id: region.id, + sales_channel_id: salesChannel.id, + customer_id: expect.any(String), + items: expect.arrayContaining([ + expect.objectContaining({ + quantity: 1, + unit_price: 3000, + }), + ]), + }) + ) }) - const priceSet = await pricingModule.create({ - prices: [ - { - amount: 5000, + it("should throw when no regions exist", async () => { + await regionModuleService.delete(defaultRegion.id) + + const { errors } = await createCartWorkflow(appContainer).run({ + input: { + email: "tony@stark.com", currency_code: "usd", }, - ], - }) - - await remoteLink.create([ - { - productService: { - variant_id: product.variants[0].id, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }, - ]) - - cart = await cartModuleService.retrieve(cart.id, { - select: ["id", "region_id", "currency_code"], - relations: ["items", "items.variant_id", "items.metadata"], - }) - - const item = cart.items?.[0]! - - const { errors } = await workflow.run({ - input: { - cart, - item, - update: { - metadata: { - foo: "bar", - }, - title: "Test item updated", - quantity: 2, - }, - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "throw", - handlerType: "invoke", - error: new Error(`Failed to update something after line items`), - }, - ]) - - const updatedItem = await cartModuleService.retrieveLineItem(item.id) - - expect(updatedItem).toEqual( - expect.objectContaining({ - id: item.id, - unit_price: 3000, - quantity: 1, - title: "Test item", + throwOnError: false, }) - ) - }) - }) - }) - describe("deleteLineItems", () => { - it("should delete items in cart", async () => { - const cart = await cartModuleService.create({ - currency_code: "usd", - items: [ - { - quantity: 1, - unit_price: 5000, - title: "Test item", - }, - ], - }) - - const items = await cartModuleService.listLineItems({ cart_id: cart.id }) - - await deleteLineItemsWorkflow(appContainer).run({ - input: { - ids: items.map((i) => i.id), - }, - throwOnError: false, - }) - - const [deletedItem] = await cartModuleService.listLineItems({ - id: items.map((i) => i.id), - }) - - expect(deletedItem).toBeUndefined() - }) - - describe("compensation", () => { - it("should restore line item if delete fails", async () => { - const workflow = deleteLineItemsWorkflow(appContainer) - - workflow.appendAction("throw", deleteLineItemsStepId, { - invoke: async function failStep() { - throw new Error(`Failed to do something after deleting line items`) - }, - }) - - const cart = await cartModuleService.create({ - currency_code: "usd", - items: [ + expect(errors).toEqual([ { - quantity: 1, - unit_price: 3000, - title: "Test item", + action: "find-one-or-any-region", + handlerType: "invoke", + error: new Error("No regions found"), }, - ], + ]) }) - const items = await cartModuleService.listLineItems({ - cart_id: cart.id, - }) + it("should throw if sales channel is disabled", async () => { + const salesChannel = await scModuleService.create({ + name: "Webshop", + is_disabled: true, + }) - const { errors } = await workflow.run({ - input: { - ids: items.map((i) => i.id), - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "throw", - handlerType: "invoke", - error: new Error( - `Failed to do something after deleting line items` - ), - }, - ]) - - const updatedItem = await cartModuleService.retrieveLineItem( - items[0].id - ) - - expect(updatedItem).not.toBeUndefined() - }) - }) - }) - - describe("createPaymentCollectionForCart", () => { - it("should create a payment collection and link it to cart", async () => { - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", - }) - - const cart = await cartModuleService.create({ - currency_code: "usd", - region_id: region.id, - items: [ - { - quantity: 1, - unit_price: 5000, - title: "Test item", - }, - ], - }) - - await createPaymentCollectionForCartWorkflow(appContainer).run({ - input: { - cart_id: cart.id, - region_id: region.id, - currency_code: "usd", - amount: 5000, - }, - throwOnError: false, - }) - - const result = await remoteQuery( - { - cart: { - fields: ["id"], - payment_collection: { - fields: ["id", "amount", "currency_code"], + const { errors } = await createCartWorkflow(appContainer).run({ + input: { + sales_channel_id: salesChannel.id, }, - }, - }, - { - cart: { - id: cart.id, - }, - } - ) + throwOnError: false, + }) - expect(result).toEqual([ - expect.objectContaining({ - id: cart.id, - payment_collection: expect.objectContaining({ - amount: 5000, - currency_code: "usd", - }), - }), - ]) - }) - - describe("compensation", () => { - it("should dismiss cart <> payment collection link and delete created payment collection", async () => { - const workflow = createPaymentCollectionForCartWorkflow(appContainer) - - workflow.appendAction("throw", linkCartAndPaymentCollectionsStepId, { - invoke: async function failStep() { - throw new Error( - `Failed to do something after linking cart and payment collection` - ) - }, - }) - - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", - }) - - const cart = await cartModuleService.create({ - currency_code: "usd", - region_id: region.id, - items: [ + expect(errors).toEqual([ { - quantity: 1, - unit_price: 5000, - title: "Test item", + action: "find-sales-channel", + handlerType: "invoke", + error: new Error( + `Unable to assign cart to disabled Sales Channel: Webshop` + ), }, - ], + ]) }) - const { errors } = await workflow.run({ - input: { - cart_id: cart.id, - region_id: region.id, + describe("compensation", () => { + it("should delete created customer if cart-creation fails", async () => { + expect.assertions(2) + const workflow = createCartWorkflow(appContainer) + + workflow.appendAction("throw", findOrCreateCustomerStepId, { + invoke: async function failStep() { + throw new Error(`Failed to create cart`) + }, + }) + + const { errors } = await workflow.run({ + input: { + currency_code: "usd", + email: "tony@stark-industries.com", + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "throw", + handlerType: "invoke", + error: new Error(`Failed to create cart`), + }, + ]) + + const customers = await customerModule.list({ + email: "tony@stark-industries.com", + }) + + expect(customers).toHaveLength(0) + }) + + it("should not delete existing customer if cart-creation fails", async () => { + expect.assertions(2) + const workflow = createCartWorkflow(appContainer) + + workflow.appendAction("throw", findOrCreateCustomerStepId, { + invoke: async function failStep() { + throw new Error(`Failed to create cart`) + }, + }) + + const customer = await customerModule.create({ + email: "tony@stark-industries.com", + }) + + const { errors } = await workflow.run({ + input: { + currency_code: "usd", + customer_id: customer.id, + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "throw", + handlerType: "invoke", + error: new Error(`Failed to create cart`), + }, + ]) + + const customers = await customerModule.list({ + email: "tony@stark-industries.com", + }) + + expect(customers).toHaveLength(1) + }) + }) + }) + + describe("AddToCartWorkflow", () => { + it("should add item to cart", async () => { + let cart = await cartModuleService.create({ currency_code: "usd", - amount: 5000, - }, - throwOnError: false, - }) + }) - expect(errors).toEqual([ - { - action: "throw", - handlerType: "invoke", - error: new Error( - `Failed to do something after linking cart and payment collection` - ), - }, - ]) + const [product] = await productModule.create([ + { + title: "Test product", + variants: [ + { + title: "Test variant", + }, + ], + }, + ]) - const carts = await remoteQuery( - { - cart: { - fields: ["id"], - payment_collection: { - fields: ["id", "amount", "currency_code"], + const priceSet = await pricingModule.create({ + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + await remoteLink.create([ + { + productService: { + variant_id: product.variants[0].id, + }, + pricingService: { + price_set_id: priceSet.id, }, }, - }, - { - cart: { - id: cart.id, - }, - } - ) + ]) - const payCols = await remoteQuery({ - payment_collection: { - fields: ["id"], - }, + cart = await cartModuleService.retrieve(cart.id, { + select: ["id", "region_id", "currency_code"], + }) + + await addToCartWorkflow(appContainer).run({ + input: { + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + }, + ], + cart, + }, + }) + + cart = await cartModuleService.retrieve(cart.id, { + relations: ["items"], + }) + + expect(cart).toEqual( + expect.objectContaining({ + id: cart.id, + currency_code: "usd", + items: expect.arrayContaining([ + expect.objectContaining({ + unit_price: 3000, + quantity: 1, + title: "Test variant", + }), + ]), + }) + ) }) - expect(carts).toEqual([ - expect.objectContaining({ - id: cart.id, - payment_collection: undefined, - }), - ]) - expect(payCols.length).toEqual(0) + it("should throw if no price sets for variant exist", async () => { + const cart = await cartModuleService.create({ + currency_code: "usd", + }) + + const [product] = await productModule.create([ + { + title: "Test product", + variants: [ + { + title: "Test variant", + }, + ], + }, + ]) + + const { errors } = await addToCartWorkflow(appContainer).run({ + input: { + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + }, + ], + cart, + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "get-variant-price-sets", + handlerType: "invoke", + error: new Error( + `Variants with IDs ${product.variants[0].id} do not have a price` + ), + }, + ]) + }) + + it("should throw if variant does not exist", async () => { + const cart = await cartModuleService.create({ + currency_code: "usd", + }) + + const { errors } = await addToCartWorkflow(appContainer).run({ + input: { + items: [ + { + variant_id: "prva_foo", + quantity: 1, + }, + ], + cart, + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "validate-variants-exist", + handlerType: "invoke", + error: new Error(`Variants with IDs prva_foo do not exist`), + }, + ]) + }) + }) + + describe("updateLineItemInCartWorkflow", () => { + it("should update item in cart", async () => { + const [product] = await productModule.create([ + { + title: "Test product", + variants: [ + { + title: "Test variant", + }, + ], + }, + ]) + + const priceSet = await pricingModule.create({ + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + await remoteLink.create([ + { + productService: { + variant_id: product.variants[0].id, + }, + pricingService: { + price_set_id: priceSet.id, + }, + }, + ]) + + let cart = await cartModuleService.create({ + currency_code: "usd", + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + unit_price: 5000, + title: "Test item", + }, + ], + }) + + cart = await cartModuleService.retrieve(cart.id, { + select: ["id", "region_id", "currency_code"], + relations: ["items", "items.variant_id", "items.metadata"], + }) + + const item = cart.items?.[0]! + + await updateLineItemInCartWorkflow(appContainer).run({ + input: { + cart, + item, + update: { + metadata: { + foo: "bar", + }, + quantity: 2, + }, + }, + throwOnError: false, + }) + + const updatedItem = await cartModuleService.retrieveLineItem(item.id) + + expect(updatedItem).toEqual( + expect.objectContaining({ + id: item.id, + unit_price: 3000, + quantity: 2, + title: "Test item", + }) + ) + }) + + describe("compensation", () => { + it("should revert line item update to original state", async () => { + expect.assertions(2) + const workflow = updateLineItemInCartWorkflow(appContainer) + + workflow.appendAction("throw", updateLineItemsStepId, { + invoke: async function failStep() { + throw new Error(`Failed to update something after line items`) + }, + }) + + const [product] = await productModule.create([ + { + title: "Test product", + variants: [ + { + title: "Test variant", + }, + ], + }, + ]) + + let cart = await cartModuleService.create({ + currency_code: "usd", + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + unit_price: 3000, + title: "Test item", + }, + ], + }) + + const priceSet = await pricingModule.create({ + prices: [ + { + amount: 5000, + currency_code: "usd", + }, + ], + }) + + await remoteLink.create([ + { + productService: { + variant_id: product.variants[0].id, + }, + pricingService: { + price_set_id: priceSet.id, + }, + }, + ]) + + cart = await cartModuleService.retrieve(cart.id, { + select: ["id", "region_id", "currency_code"], + relations: ["items", "items.variant_id", "items.metadata"], + }) + + const item = cart.items?.[0]! + + const { errors } = await workflow.run({ + input: { + cart, + item, + update: { + metadata: { + foo: "bar", + }, + title: "Test item updated", + quantity: 2, + }, + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "throw", + handlerType: "invoke", + error: new Error(`Failed to update something after line items`), + }, + ]) + + const updatedItem = await cartModuleService.retrieveLineItem( + item.id + ) + + expect(updatedItem).toEqual( + expect.objectContaining({ + id: item.id, + unit_price: 3000, + quantity: 1, + title: "Test item", + }) + ) + }) + }) + }) + + describe("deleteLineItems", () => { + it("should delete items in cart", async () => { + const cart = await cartModuleService.create({ + currency_code: "usd", + items: [ + { + quantity: 1, + unit_price: 5000, + title: "Test item", + }, + ], + }) + + const items = await cartModuleService.listLineItems({ + cart_id: cart.id, + }) + + await deleteLineItemsWorkflow(appContainer).run({ + input: { + ids: items.map((i) => i.id), + }, + throwOnError: false, + }) + + const [deletedItem] = await cartModuleService.listLineItems({ + id: items.map((i) => i.id), + }) + + expect(deletedItem).toBeUndefined() + }) + + describe("compensation", () => { + it("should restore line item if delete fails", async () => { + const workflow = deleteLineItemsWorkflow(appContainer) + + workflow.appendAction("throw", deleteLineItemsStepId, { + invoke: async function failStep() { + throw new Error( + `Failed to do something after deleting line items` + ) + }, + }) + + const cart = await cartModuleService.create({ + currency_code: "usd", + items: [ + { + quantity: 1, + unit_price: 3000, + title: "Test item", + }, + ], + }) + + const items = await cartModuleService.listLineItems({ + cart_id: cart.id, + }) + + const { errors } = await workflow.run({ + input: { + ids: items.map((i) => i.id), + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "throw", + handlerType: "invoke", + error: new Error( + `Failed to do something after deleting line items` + ), + }, + ]) + + const updatedItem = await cartModuleService.retrieveLineItem( + items[0].id + ) + + expect(updatedItem).not.toBeUndefined() + }) + }) + }) + + describe("createPaymentCollectionForCart", () => { + it("should create a payment collection and link it to cart", async () => { + const region = await regionModuleService.create({ + name: "US", + currency_code: "usd", + }) + + const cart = await cartModuleService.create({ + currency_code: "usd", + region_id: region.id, + items: [ + { + quantity: 1, + unit_price: 5000, + title: "Test item", + }, + ], + }) + + await createPaymentCollectionForCartWorkflow(appContainer).run({ + input: { + cart_id: cart.id, + region_id: region.id, + currency_code: "usd", + amount: 5000, + }, + throwOnError: false, + }) + + const result = await remoteQuery( + { + cart: { + fields: ["id"], + payment_collection: { + fields: ["id", "amount", "currency_code"], + }, + }, + }, + { + cart: { + id: cart.id, + }, + } + ) + + expect(result).toEqual([ + expect.objectContaining({ + id: cart.id, + payment_collection: expect.objectContaining({ + amount: 5000, + currency_code: "usd", + }), + }), + ]) + }) + + describe("compensation", () => { + it("should dismiss cart <> payment collection link and delete created payment collection", async () => { + const workflow = + createPaymentCollectionForCartWorkflow(appContainer) + + workflow.appendAction( + "throw", + linkCartAndPaymentCollectionsStepId, + { + invoke: async function failStep() { + throw new Error( + `Failed to do something after linking cart and payment collection` + ) + }, + } + ) + + const region = await regionModuleService.create({ + name: "US", + currency_code: "usd", + }) + + const cart = await cartModuleService.create({ + currency_code: "usd", + region_id: region.id, + items: [ + { + quantity: 1, + unit_price: 5000, + title: "Test item", + }, + ], + }) + + const { errors } = await workflow.run({ + input: { + cart_id: cart.id, + region_id: region.id, + currency_code: "usd", + amount: 5000, + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "throw", + handlerType: "invoke", + error: new Error( + `Failed to do something after linking cart and payment collection` + ), + }, + ]) + + const carts = await remoteQuery( + { + cart: { + fields: ["id"], + payment_collection: { + fields: ["id", "amount", "currency_code"], + }, + }, + }, + { + cart: { + id: cart.id, + }, + } + ) + + const payCols = await remoteQuery({ + payment_collection: { + fields: ["id"], + }, + }) + + expect(carts).toEqual([ + expect.objectContaining({ + id: cart.id, + payment_collection: undefined, + }), + ]) + expect(payCols.length).toEqual(0) + }) + }) }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/cart/store/carts.spec.ts b/integration-tests/modules/__tests__/cart/store/carts.spec.ts index ac8acc091d..ec4228ee3f 100644 --- a/integration-tests/modules/__tests__/cart/store/carts.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/carts.spec.ts @@ -14,705 +14,684 @@ import { ISalesChannelModuleService, } from "@medusajs/types" import { PromotionRuleOperator, PromotionType } from "@medusajs/utils" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import adminSeeder from "../../../../helpers/admin-seeder" import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Store Carts API", () => { - let dbConnection - let appContainer - let shutdownServer - let cartModuleService: ICartModuleService - let regionModuleService: IRegionModuleService - let scModuleService: ISalesChannelModuleService - let customerModule: ICustomerModuleService - let productModule: IProductModuleService - let pricingModule: IPricingModuleService - let remoteLink: RemoteLink - let promotionModule: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Store Carts API", () => { + let appContainer + let cartModuleService: ICartModuleService + let regionModuleService: IRegionModuleService + let scModuleService: ISalesChannelModuleService + let customerModule: ICustomerModuleService + let productModule: IProductModuleService + let pricingModule: IPricingModuleService + let remoteLink: RemoteLink + let promotionModule: IPromotionModuleService - let defaultRegion + let defaultRegion - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) - regionModuleService = appContainer.resolve(ModuleRegistrationName.REGION) - scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL) - customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER) - productModule = appContainer.resolve(ModuleRegistrationName.PRODUCT) - pricingModule = appContainer.resolve(ModuleRegistrationName.PRICING) - remoteLink = appContainer.resolve(LinkModuleUtils.REMOTE_LINK) - promotionModule = appContainer.resolve(ModuleRegistrationName.PROMOTION) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await adminSeeder(dbConnection) - - // Here, so we don't have to create a region for each test - defaultRegion = await regionModuleService.create({ - name: "Default Region", - currency_code: "dkk", - }) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - describe("POST /store/carts", () => { - it("should create a cart", async () => { - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", + beforeAll(async () => { + appContainer = getContainer() + cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) + regionModuleService = appContainer.resolve( + ModuleRegistrationName.REGION + ) + scModuleService = appContainer.resolve( + ModuleRegistrationName.SALES_CHANNEL + ) + customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER) + productModule = appContainer.resolve(ModuleRegistrationName.PRODUCT) + pricingModule = appContainer.resolve(ModuleRegistrationName.PRICING) + remoteLink = appContainer.resolve(LinkModuleUtils.REMOTE_LINK) + promotionModule = appContainer.resolve(ModuleRegistrationName.PROMOTION) }) - const salesChannel = await scModuleService.create({ - name: "Webshop", - }) + beforeEach(async () => { + await adminSeeder(dbConnection) - const [product] = await productModule.create([ - { - title: "Test product", - variants: [ - { - title: "Test variant", - }, - { - title: "Test variant 2", - }, - ], - }, - ]) - - const [priceSet, priceSetTwo] = await pricingModule.create([ - { - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - }, - { - prices: [ - { - amount: 4000, - currency_code: "usd", - }, - ], - }, - ]) - - await remoteLink.create([ - { - productService: { - variant_id: product.variants[0].id, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }, - { - productService: { - variant_id: product.variants[1].id, - }, - pricingService: { - price_set_id: priceSetTwo.id, - }, - }, - ]) - - const api = useApi() as any - - const created = await api.post(`/store/carts`, { - email: "tony@stark.com", - currency_code: "usd", - region_id: region.id, - sales_channel_id: salesChannel.id, - items: [ - { - variant_id: product.variants[0].id, - quantity: 1, - }, - { - variant_id: product.variants[1].id, - quantity: 2, - }, - ], - }) - - expect(created.status).toEqual(200) - expect(created.data.cart).toEqual( - expect.objectContaining({ - id: created.data.cart.id, - currency_code: "usd", - email: "tony@stark.com", - region: expect.objectContaining({ - id: region.id, - currency_code: "usd", - }), - sales_channel_id: salesChannel.id, - customer: expect.objectContaining({ - email: "tony@stark.com", - }), - items: expect.arrayContaining([ - expect.objectContaining({ - quantity: 1, - unit_price: 3000, - }), - expect.objectContaining({ - quantity: 2, - unit_price: 4000, - }), - ]), - }) - ) - }) - - it("should create cart with customer from email", async () => { - const api = useApi() as any - - const created = await api.post(`/store/carts`, { - currency_code: "usd", - email: "tony@stark-industries.com", - }) - - expect(created.status).toEqual(200) - expect(created.data.cart).toEqual( - expect.objectContaining({ - id: created.data.cart.id, - currency_code: "usd", - email: "tony@stark-industries.com", - customer: expect.objectContaining({ - id: expect.any(String), - email: "tony@stark-industries.com", - }), - }) - ) - }) - - it("should create cart with any region", async () => { - await regionModuleService.create({ - name: "US", - currency_code: "usd", - }) - - const api = useApi() as any - const response = await api.post(`/store/carts`, { - email: "tony@stark.com", - currency_code: "usd", - }) - - expect(response.status).toEqual(200) - expect(response.data.cart).toEqual( - expect.objectContaining({ - id: response.data.cart.id, - currency_code: "usd", - email: "tony@stark.com", - region: expect.objectContaining({ - id: expect.any(String), - }), - }) - ) - }) - - it("should create cart with region currency code", async () => { - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", - }) - - const api = useApi() as any - const response = await api.post(`/store/carts`, { - email: "tony@stark.com", - region_id: region.id, - }) - - expect(response.status).toEqual(200) - expect(response.data.cart).toEqual( - expect.objectContaining({ - id: response.data.cart.id, - currency_code: "usd", - email: "tony@stark.com", - region: expect.objectContaining({ - id: region.id, - }), - }) - ) - }) - - it("should create cart with logged-in customer", async () => { - const { customer, jwt } = await createAuthenticatedCustomer(appContainer) - - const api = useApi() as any - const response = await api.post( - `/store/carts`, - {}, - { - headers: { authorization: `Bearer ${jwt}` }, - } - ) - - expect(response.status).toEqual(200) - expect(response.data.cart).toEqual( - expect.objectContaining({ - id: response.data.cart.id, + // Here, so we don't have to create a region for each test + defaultRegion = await regionModuleService.create({ + name: "Default Region", currency_code: "dkk", - email: customer.email, - customer: expect.objectContaining({ - id: customer.id, - email: customer.email, - }), }) - ) - }) - - it("should respond 400 bad request on unknown props", async () => { - const api = useApi() as any - - await expect( - api.post(`/store/carts`, { - foo: "bar", - }) - ).rejects.toThrow() - }) - }) - - describe("POST /store/carts/:id", () => { - it("should update a cart with promo codes with a replace action", async () => { - const targetRules = [ - { - attribute: "product_id", - operator: PromotionRuleOperator.IN, - values: ["prod_tshirt"], - }, - ] - - const appliedPromotion = await promotionModule.create({ - code: "PROMOTION_APPLIED", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "items", - allocation: "each", - value: "300", - apply_to_quantity: 1, - max_quantity: 1, - target_rules: targetRules, - }, }) - const createdPromotion = await promotionModule.create({ - code: "PROMOTION_TEST", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "items", - allocation: "across", - value: "1000", - apply_to_quantity: 1, - target_rules: targetRules, - }, - }) - - const cart = await cartModuleService.create({ - currency_code: "usd", - email: "tony@stark.com", - items: [ - { - id: "item-1", - unit_price: 2000, - quantity: 1, - title: "Test item", - product_id: "prod_tshirt", - } as any, - ], - }) - - const [adjustment] = await cartModuleService.addLineItemAdjustments([ - { - code: appliedPromotion.code!, - amount: 300, - item_id: "item-1", - promotion_id: appliedPromotion.id, - }, - ]) - - await remoteLink.create({ - [Modules.CART]: { cart_id: cart.id }, - [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, - }) - - const api = useApi() as any - - // Should remove earlier adjustments from other promocodes - let updated = await api.post(`/store/carts/${cart.id}`, { - promo_codes: [createdPromotion.code], - }) - - expect(updated.status).toEqual(200) - expect(updated.data.cart).toEqual( - expect.objectContaining({ - id: cart.id, - items: [ - expect.objectContaining({ - id: "item-1", - adjustments: [ - expect.objectContaining({ - id: expect.not.stringContaining(adjustment.id), - code: createdPromotion.code, - }), - ], - }), - ], - }) - ) - - // Should remove all adjustments from other promo codes - updated = await api.post(`/store/carts/${cart.id}`, { - promo_codes: [], - }) - - expect(updated.status).toEqual(200) - expect(updated.data.cart).toEqual( - expect.objectContaining({ - id: cart.id, - items: [ - expect.objectContaining({ - id: "item-1", - adjustments: [], - }), - ], - }) - ) - }) - - it("should update a cart's region, sales channel and customer data", async () => { - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", - }) - - const salesChannel = await scModuleService.create({ - name: "Webshop", - }) - - const cart = await cartModuleService.create({ - currency_code: "eur", - }) - - const api = useApi() as any - - let updated = await api.post(`/store/carts/${cart.id}`, { - region_id: region.id, - email: "tony@stark.com", - sales_channel_id: salesChannel.id, - }) - - expect(updated.status).toEqual(200) - expect(updated.data.cart).toEqual( - expect.objectContaining({ - id: cart.id, - currency_code: "usd", - region: expect.objectContaining({ - id: region.id, + describe("POST /store/carts", () => { + it("should create a cart", async () => { + const region = await regionModuleService.create({ + name: "US", currency_code: "usd", - }), - email: "tony@stark.com", - customer: expect.objectContaining({ - email: "tony@stark.com", - }), - sales_channel_id: salesChannel.id, - }) - ) + }) - updated = await api.post(`/store/carts/${cart.id}`, { - email: null, - sales_channel_id: null, - }) + const salesChannel = await scModuleService.create({ + name: "Webshop", + }) - expect(updated.status).toEqual(200) - expect(updated.data.cart).toEqual( - expect.objectContaining({ - id: cart.id, - currency_code: "usd", - email: null, - customer_id: null, - region: expect.objectContaining({ - id: region.id, - currency_code: "usd", - }), - sales_channel_id: null, - }) - ) - }) - }) - - describe("GET /store/carts/:id", () => { - it("should create and update a cart", async () => { - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", - }) - - const salesChannel = await scModuleService.create({ - name: "Webshop", - }) - - const api = useApi() as any - - const created = await api.post(`/store/carts`, { - email: "tony@stark.com", - currency_code: "usd", - region_id: region.id, - sales_channel_id: salesChannel.id, - }) - - expect(created.status).toEqual(200) - expect(created.data.cart).toEqual( - expect.objectContaining({ - id: created.data.cart.id, - currency_code: "usd", - email: "tony@stark.com", - region: expect.objectContaining({ - id: region.id, - currency_code: "usd", - }), - sales_channel_id: salesChannel.id, - }) - ) - - const updated = await api.post(`/store/carts/${created.data.cart.id}`, { - email: "tony@stark-industries.com", - }) - - expect(updated.status).toEqual(200) - expect(updated.data.cart).toEqual( - expect.objectContaining({ - id: updated.data.cart.id, - currency_code: "usd", - email: "tony@stark-industries.com", - }) - ) - }) - }) - - describe("GET /store/carts", () => { - it("should get cart", async () => { - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", - }) - - const salesChannel = await scModuleService.create({ - name: "Webshop", - }) - - const cart = await cartModuleService.create({ - currency_code: "usd", - items: [ - { - unit_price: 1000, - quantity: 1, - title: "Test item", - }, - ], - region_id: region.id, - sales_channel_id: salesChannel.id, - }) - - const api = useApi() as any - const response = await api.get(`/store/carts/${cart.id}`) - - expect(response.status).toEqual(200) - expect(response.data.cart).toEqual( - expect.objectContaining({ - id: cart.id, - currency_code: "usd", - items: expect.arrayContaining([ - expect.objectContaining({ - unit_price: 1000, - quantity: 1, - title: "Test item", - }), - ]), - region: expect.objectContaining({ - id: region.id, - currency_code: "usd", - }), - sales_channel_id: salesChannel.id, - }) - ) - }) - }) - - describe("POST /store/carts/:id/line-items", () => { - it("should add item to cart", async () => { - const [product] = await productModule.create([ - { - title: "Test product", - variants: [ + const [product] = await productModule.create([ { - title: "Test variant", + title: "Test product", + variants: [ + { + title: "Test variant", + }, + { + title: "Test variant 2", + }, + ], }, - ], - }, - ]) + ]) - const cart = await cartModuleService.create({ - currency_code: "usd", - items: [ - { - id: "item-1", - unit_price: 2000, - quantity: 1, - title: "Test item", - product_id: "prod_mat", - } as any, - ], + const [priceSet, priceSetTwo] = await pricingModule.create([ + { + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }, + { + prices: [ + { + amount: 4000, + currency_code: "usd", + }, + ], + }, + ]) + + await remoteLink.create([ + { + productService: { + variant_id: product.variants[0].id, + }, + pricingService: { + price_set_id: priceSet.id, + }, + }, + { + productService: { + variant_id: product.variants[1].id, + }, + pricingService: { + price_set_id: priceSetTwo.id, + }, + }, + ]) + + const created = await api.post(`/store/carts`, { + email: "tony@stark.com", + currency_code: "usd", + region_id: region.id, + sales_channel_id: salesChannel.id, + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + }, + { + variant_id: product.variants[1].id, + quantity: 2, + }, + ], + }) + + expect(created.status).toEqual(200) + expect(created.data.cart).toEqual( + expect.objectContaining({ + id: created.data.cart.id, + currency_code: "usd", + email: "tony@stark.com", + region: expect.objectContaining({ + id: region.id, + currency_code: "usd", + }), + sales_channel_id: salesChannel.id, + customer: expect.objectContaining({ + email: "tony@stark.com", + }), + items: expect.arrayContaining([ + expect.objectContaining({ + quantity: 1, + unit_price: 3000, + }), + expect.objectContaining({ + quantity: 2, + unit_price: 4000, + }), + ]), + }) + ) + }) + + it("should create cart with customer from email", async () => { + const created = await api.post(`/store/carts`, { + currency_code: "usd", + email: "tony@stark-industries.com", + }) + + expect(created.status).toEqual(200) + expect(created.data.cart).toEqual( + expect.objectContaining({ + id: created.data.cart.id, + currency_code: "usd", + email: "tony@stark-industries.com", + customer: expect.objectContaining({ + id: expect.any(String), + email: "tony@stark-industries.com", + }), + }) + ) + }) + + it("should create cart with any region", async () => { + await regionModuleService.create({ + name: "US", + currency_code: "usd", + }) + + const response = await api.post(`/store/carts`, { + email: "tony@stark.com", + currency_code: "usd", + }) + + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( + expect.objectContaining({ + id: response.data.cart.id, + currency_code: "usd", + email: "tony@stark.com", + region: expect.objectContaining({ + id: expect.any(String), + }), + }) + ) + }) + + it("should create cart with region currency code", async () => { + const region = await regionModuleService.create({ + name: "US", + currency_code: "usd", + }) + + const response = await api.post(`/store/carts`, { + email: "tony@stark.com", + region_id: region.id, + }) + + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( + expect.objectContaining({ + id: response.data.cart.id, + currency_code: "usd", + email: "tony@stark.com", + region: expect.objectContaining({ + id: region.id, + }), + }) + ) + }) + + it("should create cart with logged-in customer", async () => { + const { customer, jwt } = await createAuthenticatedCustomer( + appContainer + ) + + const response = await api.post( + `/store/carts`, + {}, + { + headers: { authorization: `Bearer ${jwt}` }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( + expect.objectContaining({ + id: response.data.cart.id, + currency_code: "dkk", + email: customer.email, + customer: expect.objectContaining({ + id: customer.id, + email: customer.email, + }), + }) + ) + }) + + it("should respond 400 bad request on unknown props", async () => { + await expect( + api.post(`/store/carts`, { + foo: "bar", + }) + ).rejects.toThrow() + }) }) - const appliedPromotion = await promotionModule.create({ - code: "PROMOTION_APPLIED", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "items", - allocation: "across", - value: "300", - apply_to_quantity: 2, - target_rules: [ + describe("POST /store/carts/:id", () => { + it("should update a cart with promo codes with a replace action", async () => { + const targetRules = [ { attribute: "product_id", - operator: "in", - values: ["prod_mat", product.id], + operator: PromotionRuleOperator.IN, + values: ["prod_tshirt"], }, - ], - }, - }) + ] - const [lineItemAdjustment] = - await cartModuleService.addLineItemAdjustments([ - { - code: appliedPromotion.code!, - amount: 300, - item_id: "item-1", - promotion_id: appliedPromotion.id, - }, - ]) + const appliedPromotion = await promotionModule.create({ + code: "PROMOTION_APPLIED", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "items", + allocation: "each", + value: "300", + apply_to_quantity: 1, + max_quantity: 1, + target_rules: targetRules, + }, + }) - const priceSet = await pricingModule.create({ - prices: [ - { - amount: 3000, + const createdPromotion = await promotionModule.create({ + code: "PROMOTION_TEST", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "items", + allocation: "across", + value: "1000", + apply_to_quantity: 1, + target_rules: targetRules, + }, + }) + + const cart = await cartModuleService.create({ currency_code: "usd", - }, - ], - }) + email: "tony@stark.com", + items: [ + { + id: "item-1", + unit_price: 2000, + quantity: 1, + title: "Test item", + product_id: "prod_tshirt", + } as any, + ], + }) - await remoteLink.create([ - { - productService: { - variant_id: product.variants[0].id, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }, - ]) + const [adjustment] = await cartModuleService.addLineItemAdjustments([ + { + code: appliedPromotion.code!, + amount: 300, + item_id: "item-1", + promotion_id: appliedPromotion.id, + }, + ]) - await remoteLink.create({ - [Modules.CART]: { cart_id: cart.id }, - [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, - }) + await remoteLink.create({ + [Modules.CART]: { cart_id: cart.id }, + [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, + }) - const api = useApi() as any - const response = await api.post(`/store/carts/${cart.id}/line-items`, { - variant_id: product.variants[0].id, - quantity: 1, - }) + // Should remove earlier adjustments from other promocodes + let updated = await api.post(`/store/carts/${cart.id}`, { + promo_codes: [createdPromotion.code], + }) - expect(response.status).toEqual(200) - expect(response.data.cart).toEqual( - expect.objectContaining({ - id: cart.id, - currency_code: "usd", - items: expect.arrayContaining([ + expect(updated.status).toEqual(200) + expect(updated.data.cart).toEqual( expect.objectContaining({ - unit_price: 3000, - quantity: 1, - title: "Test variant", - adjustments: [ + id: cart.id, + items: [ expect.objectContaining({ - code: "PROMOTION_APPLIED", - amount: 180, + id: "item-1", + adjustments: [ + expect.objectContaining({ + id: expect.not.stringContaining(adjustment.id), + code: createdPromotion.code, + }), + ], }), ], - }), + }) + ) + + // Should remove all adjustments from other promo codes + updated = await api.post(`/store/carts/${cart.id}`, { + promo_codes: [], + }) + + expect(updated.status).toEqual(200) + expect(updated.data.cart).toEqual( expect.objectContaining({ - unit_price: 2000, - quantity: 1, - title: "Test item", - adjustments: [ + id: cart.id, + items: [ expect.objectContaining({ - id: expect.not.stringContaining(lineItemAdjustment.id), - code: "PROMOTION_APPLIED", - amount: 120, + id: "item-1", + adjustments: [], }), ], - }), - ]), + }) + ) }) - ) - }) - }) - describe("POST /store/carts/:id/payment-collections", () => { - it("should create a payment collection for the cart", async () => { - const region = await regionModuleService.create({ - name: "US", - currency_code: "usd", + it("should update a cart's region, sales channel and customer data", async () => { + const region = await regionModuleService.create({ + name: "US", + currency_code: "usd", + }) + + const salesChannel = await scModuleService.create({ + name: "Webshop", + }) + + const cart = await cartModuleService.create({ + currency_code: "eur", + }) + + let updated = await api.post(`/store/carts/${cart.id}`, { + region_id: region.id, + email: "tony@stark.com", + sales_channel_id: salesChannel.id, + }) + + expect(updated.status).toEqual(200) + expect(updated.data.cart).toEqual( + expect.objectContaining({ + id: cart.id, + currency_code: "usd", + region: expect.objectContaining({ + id: region.id, + currency_code: "usd", + }), + email: "tony@stark.com", + customer: expect.objectContaining({ + email: "tony@stark.com", + }), + sales_channel_id: salesChannel.id, + }) + ) + + updated = await api.post(`/store/carts/${cart.id}`, { + email: null, + sales_channel_id: null, + }) + + expect(updated.status).toEqual(200) + expect(updated.data.cart).toEqual( + expect.objectContaining({ + id: cart.id, + currency_code: "usd", + email: null, + customer_id: null, + region: expect.objectContaining({ + id: region.id, + currency_code: "usd", + }), + sales_channel_id: null, + }) + ) + }) }) - const cart = await cartModuleService.create({ - currency_code: "usd", - region_id: region.id, + describe("GET /store/carts/:id", () => { + it("should create and update a cart", async () => { + const region = await regionModuleService.create({ + name: "US", + currency_code: "usd", + }) + + const salesChannel = await scModuleService.create({ + name: "Webshop", + }) + + const created = await api.post(`/store/carts`, { + email: "tony@stark.com", + currency_code: "usd", + region_id: region.id, + sales_channel_id: salesChannel.id, + }) + + expect(created.status).toEqual(200) + expect(created.data.cart).toEqual( + expect.objectContaining({ + id: created.data.cart.id, + currency_code: "usd", + email: "tony@stark.com", + region: expect.objectContaining({ + id: region.id, + currency_code: "usd", + }), + sales_channel_id: salesChannel.id, + }) + ) + + const updated = await api.post( + `/store/carts/${created.data.cart.id}`, + { + email: "tony@stark-industries.com", + } + ) + + expect(updated.status).toEqual(200) + expect(updated.data.cart).toEqual( + expect.objectContaining({ + id: updated.data.cart.id, + currency_code: "usd", + email: "tony@stark-industries.com", + }) + ) + }) }) - const api = useApi() as any - const response = await api.post( - `/store/carts/${cart.id}/payment-collections` - ) + describe("GET /store/carts", () => { + it("should get cart", async () => { + const region = await regionModuleService.create({ + name: "US", + currency_code: "usd", + }) - expect(response.status).toEqual(200) - expect(response.data.cart).toEqual( - expect.objectContaining({ - id: cart.id, - currency_code: "usd", - payment_collection: expect.objectContaining({ - id: expect.any(String), - amount: 0, - }), + const salesChannel = await scModuleService.create({ + name: "Webshop", + }) + + const cart = await cartModuleService.create({ + currency_code: "usd", + items: [ + { + unit_price: 1000, + quantity: 1, + title: "Test item", + }, + ], + region_id: region.id, + sales_channel_id: salesChannel.id, + }) + + const response = await api.get(`/store/carts/${cart.id}`) + + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( + expect.objectContaining({ + id: cart.id, + currency_code: "usd", + items: expect.arrayContaining([ + expect.objectContaining({ + unit_price: 1000, + quantity: 1, + title: "Test item", + }), + ]), + region: expect.objectContaining({ + id: region.id, + currency_code: "usd", + }), + sales_channel_id: salesChannel.id, + }) + ) }) - ) + }) + + describe("POST /store/carts/:id/line-items", () => { + it("should add item to cart", async () => { + const [product] = await productModule.create([ + { + title: "Test product", + variants: [ + { + title: "Test variant", + }, + ], + }, + ]) + + const cart = await cartModuleService.create({ + currency_code: "usd", + items: [ + { + id: "item-1", + unit_price: 2000, + quantity: 1, + title: "Test item", + product_id: "prod_mat", + } as any, + ], + }) + + const appliedPromotion = await promotionModule.create({ + code: "PROMOTION_APPLIED", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "items", + allocation: "across", + value: "300", + apply_to_quantity: 2, + target_rules: [ + { + attribute: "product_id", + operator: "in", + values: ["prod_mat", product.id], + }, + ], + }, + }) + + const [lineItemAdjustment] = + await cartModuleService.addLineItemAdjustments([ + { + code: appliedPromotion.code!, + amount: 300, + item_id: "item-1", + promotion_id: appliedPromotion.id, + }, + ]) + + const priceSet = await pricingModule.create({ + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + await remoteLink.create([ + { + productService: { + variant_id: product.variants[0].id, + }, + pricingService: { + price_set_id: priceSet.id, + }, + }, + ]) + + await remoteLink.create({ + [Modules.CART]: { cart_id: cart.id }, + [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, + }) + + const response = await api.post( + `/store/carts/${cart.id}/line-items`, + { + variant_id: product.variants[0].id, + quantity: 1, + } + ) + + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( + expect.objectContaining({ + id: cart.id, + currency_code: "usd", + items: expect.arrayContaining([ + expect.objectContaining({ + unit_price: 3000, + quantity: 1, + title: "Test variant", + adjustments: [ + expect.objectContaining({ + code: "PROMOTION_APPLIED", + amount: 180, + }), + ], + }), + expect.objectContaining({ + unit_price: 2000, + quantity: 1, + title: "Test item", + adjustments: [ + expect.objectContaining({ + id: expect.not.stringContaining(lineItemAdjustment.id), + code: "PROMOTION_APPLIED", + amount: 120, + }), + ], + }), + ]), + }) + ) + }) + }) + + describe("POST /store/carts/:id/payment-collections", () => { + it("should create a payment collection for the cart", async () => { + const region = await regionModuleService.create({ + name: "US", + currency_code: "usd", + }) + + const cart = await cartModuleService.create({ + currency_code: "usd", + region_id: region.id, + }) + + const response = await api.post( + `/store/carts/${cart.id}/payment-collections` + ) + + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( + expect.objectContaining({ + id: cart.id, + currency_code: "usd", + payment_collection: expect.objectContaining({ + id: expect.any(String), + amount: 0, + }), + }) + ) + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/cart/store/remove-promotions-from-cart.spec.ts b/integration-tests/modules/__tests__/cart/store/remove-promotions-from-cart.spec.ts index fc7dedf925..212eaa7522 100644 --- a/integration-tests/modules/__tests__/cart/store/remove-promotions-from-cart.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/remove-promotions-from-cart.spec.ts @@ -6,324 +6,313 @@ import { } from "@medusajs/modules-sdk" import { ICartModuleService, IPromotionModuleService } from "@medusajs/types" import { PromotionType } from "@medusajs/utils" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import adminSeeder from "../../../../helpers/admin-seeder" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Store Carts API: Remove promotions from cart", () => { - let dbConnection - let appContainer - let shutdownServer - let cartModuleService: ICartModuleService - let promotionModuleService: IPromotionModuleService - let remoteLinkService: RemoteLink +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Store Carts API: Remove promotions from cart", () => { + let appContainer + let cartModuleService: ICartModuleService + let promotionModuleService: IPromotionModuleService + let remoteLinkService: RemoteLink - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) - remoteLinkService = appContainer.resolve(LinkModuleUtils.REMOTE_LINK) - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await adminSeeder(dbConnection) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - describe("DELETE /store/carts/:id/promotions", () => { - it("should remove line item adjustments from a cart based on promotions", async () => { - const appliedPromotion = await promotionModuleService.create({ - code: "PROMOTION_APPLIED", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "items", - allocation: "each", - value: "300", - apply_to_quantity: 1, - max_quantity: 1, - target_rules: [ - { - attribute: "product_id", - operator: "eq", - values: "prod_tshirt", - }, - ], - }, + beforeAll(async () => { + appContainer = getContainer() + cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) + remoteLinkService = appContainer.resolve(LinkModuleUtils.REMOTE_LINK) + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) }) - const appliedPromotionToRemove = await promotionModuleService.create({ - code: "PROMOTION_APPLIED_TO_REMOVE", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "items", - allocation: "each", - value: "300", - apply_to_quantity: 1, - max_quantity: 1, - target_rules: [ - { - attribute: "product_id", - operator: "eq", - values: "prod_tshirt", - }, - ], - }, + beforeEach(async () => { + await adminSeeder(dbConnection) }) - const cart = await cartModuleService.create({ - currency_code: "usd", - items: [ - { - id: "item-1", - unit_price: 2000, - quantity: 1, - title: "Test item", - product_id: "prod_mat", - } as any, - { - id: "item-2", - unit_price: 1000, - quantity: 1, - title: "Test item", - product_id: "prod_tshirt", - } as any, - ], - }) - - const [adjustment1, adjustment2] = - await cartModuleService.addLineItemAdjustments([ - { - code: appliedPromotion.code!, - amount: 300, - item_id: "item-2", - promotion_id: appliedPromotionToRemove.id, - }, - { - code: appliedPromotionToRemove.code!, - amount: 150, - item_id: "item-1", - promotion_id: appliedPromotionToRemove.id, - }, - { - code: appliedPromotionToRemove.code!, - amount: 150, - item_id: "item-2", - promotion_id: appliedPromotionToRemove.id, - }, - ]) - - await remoteLinkService.create([ - { - [Modules.CART]: { cart_id: cart.id }, - [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, - }, - { - [Modules.CART]: { cart_id: cart.id }, - [Modules.PROMOTION]: { promotion_id: appliedPromotionToRemove.id }, - }, - ]) - - const api = useApi() as any - - const response = await api.delete(`/store/carts/${cart.id}/promotions`, { - data: { - promo_codes: [appliedPromotionToRemove.code], - }, - }) - - expect(response.status).toEqual(200) - expect(response.data.cart).toEqual( - expect.objectContaining({ - id: expect.any(String), - items: expect.arrayContaining([ - expect.objectContaining({ - id: "item-1", - adjustments: [], - }), - expect.objectContaining({ - id: "item-2", - adjustments: [ - expect.objectContaining({ - amount: 300, - code: appliedPromotion.code, - }), + describe("DELETE /store/carts/:id/promotions", () => { + it("should remove line item adjustments from a cart based on promotions", async () => { + const appliedPromotion = await promotionModuleService.create({ + code: "PROMOTION_APPLIED", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "items", + allocation: "each", + value: "300", + apply_to_quantity: 1, + max_quantity: 1, + target_rules: [ + { + attribute: "product_id", + operator: "eq", + values: "prod_tshirt", + }, ], - }), - ]), - }) - ) - }) - - it("should add shipping method adjustments to a cart based on promotions", async () => { - const appliedPromotion = await promotionModuleService.create({ - code: "PROMOTION_APPLIED", - type: PromotionType.STANDARD, - rules: [ - { - attribute: "customer_id", - operator: "in", - values: ["cus_test"], - }, - { - attribute: "currency_code", - operator: "in", - values: ["eur"], - }, - ], - application_method: { - type: "fixed", - target_type: "shipping_methods", - allocation: "each", - value: "100", - max_quantity: 1, - target_rules: [ - { - attribute: "name", - operator: "in", - values: ["express"], }, - ], - }, - }) + }) - const appliedPromotionToRemove = await promotionModuleService.create({ - code: "PROMOTION_APPLIED_TO_REMOVE", - type: PromotionType.STANDARD, - rules: [ - { - attribute: "customer_id", - operator: "in", - values: ["cus_test"], - }, - { - attribute: "currency_code", - operator: "in", - values: ["eur"], - }, - ], - application_method: { - type: "fixed", - target_type: "shipping_methods", - allocation: "each", - value: "100", - max_quantity: 1, - target_rules: [ - { - attribute: "name", - operator: "in", - values: ["express"], + const appliedPromotionToRemove = await promotionModuleService.create({ + code: "PROMOTION_APPLIED_TO_REMOVE", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "items", + allocation: "each", + value: "300", + apply_to_quantity: 1, + max_quantity: 1, + target_rules: [ + { + attribute: "product_id", + operator: "eq", + values: "prod_tshirt", + }, + ], }, - ], - }, - }) + }) - const cart = await cartModuleService.create({ - currency_code: "eur", - customer_id: "cus_test", - items: [ - { - unit_price: 2000, - quantity: 1, - title: "Test item", - product_id: "prod_mat", - }, - ], - }) + const cart = await cartModuleService.create({ + currency_code: "usd", + items: [ + { + id: "item-1", + unit_price: 2000, + quantity: 1, + title: "Test item", + product_id: "prod_mat", + } as any, + { + id: "item-2", + unit_price: 1000, + quantity: 1, + title: "Test item", + product_id: "prod_tshirt", + } as any, + ], + }) - const [express, standard] = await cartModuleService.addShippingMethods( - cart.id, - [ - { - amount: 500, - name: "express", - }, - { - amount: 500, - name: "standard", - }, - ] - ) + const [adjustment1, adjustment2] = + await cartModuleService.addLineItemAdjustments([ + { + code: appliedPromotion.code!, + amount: 300, + item_id: "item-2", + promotion_id: appliedPromotionToRemove.id, + }, + { + code: appliedPromotionToRemove.code!, + amount: 150, + item_id: "item-1", + promotion_id: appliedPromotionToRemove.id, + }, + { + code: appliedPromotionToRemove.code!, + amount: 150, + item_id: "item-2", + promotion_id: appliedPromotionToRemove.id, + }, + ]) - await cartModuleService.addShippingMethodAdjustments(cart.id, [ - { - shipping_method_id: express.id, - amount: 100, - code: appliedPromotion.code!, - }, - { - shipping_method_id: express.id, - amount: 100, - code: appliedPromotionToRemove.code!, - }, - ]) + await remoteLinkService.create([ + { + [Modules.CART]: { cart_id: cart.id }, + [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, + }, + { + [Modules.CART]: { cart_id: cart.id }, + [Modules.PROMOTION]: { + promotion_id: appliedPromotionToRemove.id, + }, + }, + ]) - await remoteLinkService.create([ - { - [Modules.CART]: { cart_id: cart.id }, - [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, - }, - { - [Modules.CART]: { cart_id: cart.id }, - [Modules.PROMOTION]: { promotion_id: appliedPromotionToRemove.id }, - }, - ]) + const response = await api.delete( + `/store/carts/${cart.id}/promotions`, + { + data: { + promo_codes: [appliedPromotionToRemove.code], + }, + } + ) - const api = useApi() as any - - const response = await api.delete(`/store/carts/${cart.id}/promotions`, { - data: { promo_codes: [appliedPromotionToRemove.code] }, - }) - - expect(response.status).toEqual(200) - expect(response.data.cart).toEqual( - expect.objectContaining({ - id: expect.any(String), - items: expect.arrayContaining([ + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( expect.objectContaining({ id: expect.any(String), - }), - ]), - shipping_methods: expect.arrayContaining([ - expect.objectContaining({ - id: express.id, - adjustments: [ + items: expect.arrayContaining([ expect.objectContaining({ - amount: 100, - code: appliedPromotion.code, + id: "item-1", + adjustments: [], }), - ], - }), - expect.objectContaining({ - id: standard.id, - adjustments: [], - }), - ]), + expect.objectContaining({ + id: "item-2", + adjustments: [ + expect.objectContaining({ + amount: 300, + code: appliedPromotion.code, + }), + ], + }), + ]), + }) + ) }) - ) + + it("should add shipping method adjustments to a cart based on promotions", async () => { + const appliedPromotion = await promotionModuleService.create({ + code: "PROMOTION_APPLIED", + type: PromotionType.STANDARD, + rules: [ + { + attribute: "customer_id", + operator: "in", + values: ["cus_test"], + }, + { + attribute: "currency_code", + operator: "in", + values: ["eur"], + }, + ], + application_method: { + type: "fixed", + target_type: "shipping_methods", + allocation: "each", + value: "100", + max_quantity: 1, + target_rules: [ + { + attribute: "name", + operator: "in", + values: ["express"], + }, + ], + }, + }) + + const appliedPromotionToRemove = await promotionModuleService.create({ + code: "PROMOTION_APPLIED_TO_REMOVE", + type: PromotionType.STANDARD, + rules: [ + { + attribute: "customer_id", + operator: "in", + values: ["cus_test"], + }, + { + attribute: "currency_code", + operator: "in", + values: ["eur"], + }, + ], + application_method: { + type: "fixed", + target_type: "shipping_methods", + allocation: "each", + value: "100", + max_quantity: 1, + target_rules: [ + { + attribute: "name", + operator: "in", + values: ["express"], + }, + ], + }, + }) + + const cart = await cartModuleService.create({ + currency_code: "eur", + customer_id: "cus_test", + items: [ + { + unit_price: 2000, + quantity: 1, + title: "Test item", + product_id: "prod_mat", + }, + ], + }) + + const [express, standard] = + await cartModuleService.addShippingMethods(cart.id, [ + { + amount: 500, + name: "express", + }, + { + amount: 500, + name: "standard", + }, + ]) + + await cartModuleService.addShippingMethodAdjustments(cart.id, [ + { + shipping_method_id: express.id, + amount: 100, + code: appliedPromotion.code!, + }, + { + shipping_method_id: express.id, + amount: 100, + code: appliedPromotionToRemove.code!, + }, + ]) + + await remoteLinkService.create([ + { + [Modules.CART]: { cart_id: cart.id }, + [Modules.PROMOTION]: { promotion_id: appliedPromotion.id }, + }, + { + [Modules.CART]: { cart_id: cart.id }, + [Modules.PROMOTION]: { + promotion_id: appliedPromotionToRemove.id, + }, + }, + ]) + + const response = await api.delete( + `/store/carts/${cart.id}/promotions`, + { + data: { promo_codes: [appliedPromotionToRemove.code] }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( + expect.objectContaining({ + id: expect.any(String), + items: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + }), + ]), + shipping_methods: expect.arrayContaining([ + expect.objectContaining({ + id: express.id, + adjustments: [ + expect.objectContaining({ + amount: 100, + code: appliedPromotion.code, + }), + ], + }), + expect.objectContaining({ + id: standard.id, + adjustments: [], + }), + ]), + }) + ) + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/currency/admin/currency.spec.ts b/integration-tests/modules/__tests__/currency/admin/currency.spec.ts index cce0123683..3101f1aac7 100644 --- a/integration-tests/modules/__tests__/currency/admin/currency.spec.ts +++ b/integration-tests/modules/__tests__/currency/admin/currency.spec.ts @@ -1,12 +1,5 @@ -import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import { ICurrencyModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { DataSource } from "typeorm" import { createAdminUser } from "../../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -15,53 +8,39 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("Currency - Admin", () => { - let dbConnection: DataSource - let appContainer - let shutdownServer - let service: ICurrencyModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, api, getContainer }) => { + describe("Currency - Admin", () => { + let container - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - service = appContainer.resolve(ModuleRegistrationName.CURRENCY) - }) + beforeEach(async () => { + container = getContainer() + await createAdminUser(dbConnection, adminHeaders, container) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should correctly retrieve and list currencies", async () => { + const listResp = await api.get("/admin/currencies", adminHeaders) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + expect(listResp.data.currencies).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + code: "aud", + }), + expect.objectContaining({ + code: "cad", + }), + ]) + ) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should correctly retrieve and list currencies", async () => { - const api = useApi() as any - const listResp = await api.get("/admin/currencies", adminHeaders) - - expect(listResp.data.currencies).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - code: "aud", - }), - expect.objectContaining({ - code: "cad", - }), - ]) - ) - - const retrieveResp = await api.get(`/admin/currencies/aud`, adminHeaders) - expect(retrieveResp.data.currency).toEqual( - listResp.data.currencies.find((c) => c.code === "aud") - ) - }) + const retrieveResp = await api.get( + `/admin/currencies/aud`, + adminHeaders + ) + expect(retrieveResp.data.currency).toEqual( + listResp.data.currencies.find((c) => c.code === "aud") + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/currency/store/currency.spec.ts b/integration-tests/modules/__tests__/currency/store/currency.spec.ts index bff9b72a54..b9fb905f37 100644 --- a/integration-tests/modules/__tests__/currency/store/currency.spec.ts +++ b/integration-tests/modules/__tests__/currency/store/currency.spec.ts @@ -1,11 +1,4 @@ -import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import { ICurrencyModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { DataSource } from "typeorm" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -14,49 +7,32 @@ const storeHeaders = { headers: {}, } -describe("Currency - Store", () => { - let dbConnection: DataSource - let appContainer - let shutdownServer - let service: ICurrencyModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ api }) => { + describe("Currency - Store", () => { + it("should correctly retrieve and list currencies", async () => { + const listResp = await api.get("/store/currencies", storeHeaders) - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - service = appContainer.resolve(ModuleRegistrationName.CURRENCY) - }) + expect(listResp.data.currencies).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + code: "aud", + }), + expect.objectContaining({ + code: "cad", + }), + ]) + ) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should correctly retrieve and list currencies", async () => { - const api = useApi() as any - const listResp = await api.get("/store/currencies", storeHeaders) - - expect(listResp.data.currencies).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - code: "aud", - }), - expect.objectContaining({ - code: "cad", - }), - ]) - ) - - const retrieveResp = await api.get(`/store/currencies/aud`, storeHeaders) - expect(retrieveResp.data.currency).toEqual( - listResp.data.currencies.find((c) => c.code === "aud") - ) - }) + const retrieveResp = await api.get( + `/store/currencies/aud`, + storeHeaders + ) + expect(retrieveResp.data.currency).toEqual( + listResp.data.currencies.find((c) => c.code === "aud") + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/batch-add-customers.ts b/integration-tests/modules/__tests__/customer-group/admin/batch-add-customers.ts index 917740c848..53b58c17be 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/batch-add-customers.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/batch-add-customers.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,74 +10,61 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/customer-groups/:id/customers/batch", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/customer-groups/:id/customers/batch", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should batch add customers to a group", async () => { + const group = await customerModuleService.createCustomerGroup({ + name: "VIP", + }) + const customers = await customerModuleService.create([ + { + first_name: "Test", + last_name: "Test", + }, + { + first_name: "Test2", + last_name: "Test2", + }, + { + first_name: "Test3", + last_name: "Test3", + }, + ]) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.post( + `/admin/customer-groups/${group.id}/customers/batch`, + { + customer_ids: customers.map((c) => ({ id: c.id })), + }, + adminHeaders + ) - it("should batch add customers to a group", async () => { - const api = useApi() as any + expect(response.status).toEqual(200) - const group = await customerModuleService.createCustomerGroup({ - name: "VIP", + const updatedGroup = await customerModuleService.retrieveCustomerGroup( + group.id, + { + relations: ["customers"], + } + ) + expect(updatedGroup.customers?.length).toEqual(3) + }) }) - const customers = await customerModuleService.create([ - { - first_name: "Test", - last_name: "Test", - }, - { - first_name: "Test2", - last_name: "Test2", - }, - { - first_name: "Test3", - last_name: "Test3", - }, - ]) - - const response = await api.post( - `/admin/customer-groups/${group.id}/customers/batch`, - { - customer_ids: customers.map((c) => ({ id: c.id })), - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - - const updatedGroup = await customerModuleService.retrieveCustomerGroup( - group.id, - { - relations: ["customers"], - } - ) - expect(updatedGroup.customers?.length).toEqual(3) - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/batch-remove-customers.ts b/integration-tests/modules/__tests__/customer-group/admin/batch-remove-customers.ts index 81ade3fc3f..70bf486cdc 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/batch-remove-customers.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/batch-remove-customers.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,78 +10,68 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("DELETE /admin/customer-groups/:id/customers/remove", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /admin/customer-groups/:id/customers/remove", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should batch delete customers from a group", async () => { + const group = await customerModuleService.createCustomerGroup({ + name: "VIP", + }) + const customers = await customerModuleService.create([ + { + first_name: "Test", + last_name: "Test", + }, + { + first_name: "Test2", + last_name: "Test2", + }, + { + first_name: "Test3", + last_name: "Test3", + }, + ]) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + await customerModuleService.addCustomerToGroup( + customers.map((c) => ({ + customer_id: c.id, + customer_group_id: group.id, + })) + ) - it("should batch delete customers from a group", async () => { - const api = useApi() as any + const response = await api.post( + `/admin/customer-groups/${group.id}/customers/remove`, + { + customer_ids: customers.map((c) => ({ id: c.id })), + }, + adminHeaders + ) - const group = await customerModuleService.createCustomerGroup({ - name: "VIP", + expect(response.status).toEqual(200) + + const updatedGroup = await customerModuleService.retrieveCustomerGroup( + group.id, + { + relations: ["customers"], + } + ) + expect(updatedGroup.customers?.length).toEqual(0) + }) }) - const customers = await customerModuleService.create([ - { - first_name: "Test", - last_name: "Test", - }, - { - first_name: "Test2", - last_name: "Test2", - }, - { - first_name: "Test3", - last_name: "Test3", - }, - ]) - - await customerModuleService.addCustomerToGroup( - customers.map((c) => ({ customer_id: c.id, customer_group_id: group.id })) - ) - - const response = await api.post( - `/admin/customer-groups/${group.id}/customers/remove`, - { - customer_ids: customers.map((c) => ({ id: c.id })), - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - - const updatedGroup = await customerModuleService.retrieveCustomerGroup( - group.id, - { - relations: ["customers"], - } - ) - expect(updatedGroup.customers?.length).toEqual(0) - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/create-customer-group.ts b/integration-tests/modules/__tests__/customer-group/admin/create-customer-group.ts index 7ee6b1b39b..4027709837 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/create-customer-group.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/create-customer-group.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,55 +10,43 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/customer-groups", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/customer-groups", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - // await adminSeeder(dbConnection) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should create a customer group", async () => { - const api = useApi() as any - const response = await api.post( - `/admin/customer-groups`, - { - name: "VIP", - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.customer_group).toEqual( - expect.objectContaining({ - id: expect.any(String), - name: "VIP", - created_by: "admin_user", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) + + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + // await adminSeeder(dbConnection) + }) + + it("should create a customer group", async () => { + const response = await api.post( + `/admin/customer-groups`, + { + name: "VIP", + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.customer_group).toEqual( + expect.objectContaining({ + id: expect.any(String), + name: "VIP", + created_by: "admin_user", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/delete-customer-group.ts b/integration-tests/modules/__tests__/customer-group/admin/delete-customer-group.ts index 78b8c31b88..56d297e9a4 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/delete-customer-group.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/delete-customer-group.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,54 +10,42 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("DELETE /admin/customer-groups/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /admin/customer-groups/:id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should delete a group", async () => { + const group = await customerModuleService.createCustomerGroup({ + name: "VIP", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.delete( + `/admin/customer-groups/${group.id}`, + adminHeaders + ) - it("should delete a group", async () => { - const group = await customerModuleService.createCustomerGroup({ - name: "VIP", + expect(response.status).toEqual(200) + + const deletedCustomer = + await customerModuleService.retrieveCustomerGroup(group.id, { + withDeleted: true, + }) + expect(deletedCustomer.deleted_at).toBeTruthy() + }) }) - - const api = useApi() as any - const response = await api.delete( - `/admin/customer-groups/${group.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - - const deletedCustomer = await customerModuleService.retrieveCustomerGroup( - group.id, - { withDeleted: true } - ) - expect(deletedCustomer.deleted_at).toBeTruthy() - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/list-customer-group-customers.ts b/integration-tests/modules/__tests__/customer-group/admin/list-customer-group-customers.ts index e0f6d80b5e..04d74a99b5 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/list-customer-group-customers.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/list-customer-group-customers.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,77 +10,67 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/customer-groups/:id/customers", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/customer-groups/:id/customers", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should get all customer groups and its count", async () => { + const group = await customerModuleService.createCustomerGroup({ + name: "Test", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const customers = await customerModuleService.create([ + { + first_name: "Test", + last_name: "Test", + }, + { + first_name: "Test2", + last_name: "Test2", + }, + ]) - it("should get all customer groups and its count", async () => { - const group = await customerModuleService.createCustomerGroup({ - name: "Test", + // add to group + + await customerModuleService.addCustomerToGroup( + customers.map((c) => ({ + customer_id: c.id, + customer_group_id: group.id, + })) + ) + + const response = await api.get( + `/admin/customer-groups/${group.id}/customers`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(2) + expect(response.data.customers).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: customers[0].id, + }), + expect.objectContaining({ + id: customers[1].id, + }), + ]) + ) + }) }) - - const customers = await customerModuleService.create([ - { - first_name: "Test", - last_name: "Test", - }, - { - first_name: "Test2", - last_name: "Test2", - }, - ]) - - // add to group - - await customerModuleService.addCustomerToGroup( - customers.map((c) => ({ customer_id: c.id, customer_group_id: group.id })) - ) - - const api = useApi() as any - - const response = await api.get( - `/admin/customer-groups/${group.id}/customers`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(2) - expect(response.data.customers).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: customers[0].id, - }), - expect.objectContaining({ - id: customers[1].id, - }), - ]) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/list-customer-groups.spec.ts b/integration-tests/modules/__tests__/customer-group/admin/list-customer-groups.spec.ts index ae67e163c2..794e897a71 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/list-customer-groups.spec.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/list-customer-groups.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,52 +10,40 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/customer-groups", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/customer-groups", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should get all customer groups and its count", async () => { + await customerModuleService.createCustomerGroup({ + name: "Test", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.get(`/admin/customer-groups`, adminHeaders) - it("should get all customer groups and its count", async () => { - await customerModuleService.createCustomerGroup({ - name: "Test", + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.customer_groups).toEqual([ + expect.objectContaining({ + id: expect.any(String), + name: "Test", + }), + ]) + }) }) - - const api = useApi() as any - const response = await api.get(`/admin/customer-groups`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.customer_groups).toEqual([ - expect.objectContaining({ - id: expect.any(String), - name: "Test", - }), - ]) - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/retrieve-customer-group.ts b/integration-tests/modules/__tests__/customer-group/admin/retrieve-customer-group.ts index 4bd648fa1b..b300a7892f 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/retrieve-customer-group.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/retrieve-customer-group.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,54 +10,42 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/customer-groups/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/customer-groups/:id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should retrieve customer group", async () => { - const group = await customerModuleService.createCustomerGroup({ - name: "Test", - }) - - const api = useApi() as any - const response = await api.get( - `/admin/customer-groups/${group.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.customer_group).toEqual( - expect.objectContaining({ - id: expect.any(String), - name: "Test", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) + + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should retrieve customer group", async () => { + const group = await customerModuleService.createCustomerGroup({ + name: "Test", + }) + + const response = await api.get( + `/admin/customer-groups/${group.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.customer_group).toEqual( + expect.objectContaining({ + id: expect.any(String), + name: "Test", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer-group/admin/update-customer-group.ts b/integration-tests/modules/__tests__/customer-group/admin/update-customer-group.ts index b9fb88e440..7f915584e5 100644 --- a/integration-tests/modules/__tests__/customer-group/admin/update-customer-group.ts +++ b/integration-tests/modules/__tests__/customer-group/admin/update-customer-group.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,57 +10,45 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/customer-groups/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/customer-groups/:id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should update a customer group", async () => { - const customer = await customerModuleService.createCustomerGroup({ - name: "VIP", - }) - - const api = useApi() as any - const response = await api.post( - `/admin/customer-groups/${customer.id}`, - { - name: "regular", - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.customer_group).toEqual( - expect.objectContaining({ - id: expect.any(String), - name: "regular", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) + + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should update a customer group", async () => { + const customer = await customerModuleService.createCustomerGroup({ + name: "VIP", + }) + + const response = await api.post( + `/admin/customer-groups/${customer.id}`, + { + name: "regular", + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.customer_group).toEqual( + expect.objectContaining({ + id: expect.any(String), + name: "regular", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/create-customer-addresses.ts b/integration-tests/modules/__tests__/customer/admin/create-customer-addresses.ts index 5deec17877..ad25b42557 100644 --- a/integration-tests/modules/__tests__/customer/admin/create-customer-addresses.ts +++ b/integration-tests/modules/__tests__/customer/admin/create-customer-addresses.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,142 +10,127 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/customers/:id/addresses", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/customers/:id/addresses", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should create a customer address", async () => { - // Create a customer - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", - }) - - const api = useApi() as any - const response = await api.post( - `/admin/customers/${customer.id}/addresses`, - { - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.address).toEqual( - expect.objectContaining({ - id: expect.any(String), - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - const customerWithAddresses = await customerModuleService.retrieve( - customer.id, - { relations: ["addresses"] } - ) - - expect(customerWithAddresses.addresses?.length).toEqual(1) - }) - - it("sets new shipping address as default and unsets the old one", async () => { - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", - addresses: [ - { + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + it("should create a customer address", async () => { + // Create a customer + const customer = await customerModuleService.create({ first_name: "John", last_name: "Doe", - address_1: "Test street 1", + }) + + const response = await api.post( + `/admin/customers/${customer.id}/addresses`, + { + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.address).toEqual( + expect.objectContaining({ + id: expect.any(String), + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }) + ) + + const customerWithAddresses = await customerModuleService.retrieve( + customer.id, + { relations: ["addresses"] } + ) + + expect(customerWithAddresses.addresses?.length).toEqual(1) + }) + + it("sets new shipping address as default and unsets the old one", async () => { + const customer = await customerModuleService.create({ + first_name: "John", + last_name: "Doe", + addresses: [ + { + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + is_default_shipping: true, + }, + ], + }) + + const response = await api.post( + `/admin/customers/${customer.id}/addresses`, + { + first_name: "John", + last_name: "Doe", + address_1: "Test street 2", + is_default_shipping: true, + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + + const [address] = await customerModuleService.listAddresses({ + customer_id: customer.id, is_default_shipping: true, - }, - ], - }) + }) - const api = useApi() as any - const response = await api.post( - `/admin/customers/${customer.id}/addresses`, - { - first_name: "John", - last_name: "Doe", - address_1: "Test street 2", - is_default_shipping: true, - }, - adminHeaders - ) + expect(address.address_1).toEqual("Test street 2") + }) - expect(response.status).toEqual(200) - - const [address] = await customerModuleService.listAddresses({ - customer_id: customer.id, - is_default_shipping: true, - }) - - expect(address.address_1).toEqual("Test street 2") - }) - - it("sets new billing address as default and unsets the old one", async () => { - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", - addresses: [ - { + it("sets new billing address as default and unsets the old one", async () => { + const customer = await customerModuleService.create({ first_name: "John", last_name: "Doe", - address_1: "Test street 1", + addresses: [ + { + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + is_default_billing: true, + }, + ], + }) + + const response = await api.post( + `/admin/customers/${customer.id}/addresses`, + { + first_name: "John", + last_name: "Doe", + address_1: "Test street 2", + is_default_billing: true, + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + + const [address] = await customerModuleService.listAddresses({ + customer_id: customer.id, is_default_billing: true, - }, - ], + }) + + expect(address.address_1).toEqual("Test street 2") + }) }) - - const api = useApi() as any - const response = await api.post( - `/admin/customers/${customer.id}/addresses`, - { - first_name: "John", - last_name: "Doe", - address_1: "Test street 2", - is_default_billing: true, - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - - const [address] = await customerModuleService.listAddresses({ - customer_id: customer.id, - is_default_billing: true, - }) - - expect(address.address_1).toEqual("Test street 2") - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/create-customer.ts b/integration-tests/modules/__tests__/customer/admin/create-customer.ts index 30e05dc05a..abf0dadbcb 100644 --- a/integration-tests/modules/__tests__/customer/admin/create-customer.ts +++ b/integration-tests/modules/__tests__/customer/admin/create-customer.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,56 +10,44 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/customers", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/customers", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should create a customer", async () => { - const api = useApi() as any - const response = await api.post( - `/admin/customers`, - { - first_name: "John", - last_name: "Doe", - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.customer).toEqual( - expect.objectContaining({ - id: expect.any(String), - first_name: "John", - last_name: "Doe", - created_by: "admin_user", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) + + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should create a customer", async () => { + const response = await api.post( + `/admin/customers`, + { + first_name: "John", + last_name: "Doe", + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.customer).toEqual( + expect.objectContaining({ + id: expect.any(String), + first_name: "John", + last_name: "Doe", + created_by: "admin_user", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/delete-customer-address.spec.ts b/integration-tests/modules/__tests__/customer/admin/delete-customer-address.spec.ts index 0d500cd840..6015b31290 100644 --- a/integration-tests/modules/__tests__/customer/admin/delete-customer-address.spec.ts +++ b/integration-tests/modules/__tests__/customer/admin/delete-customer-address.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,62 +10,53 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("DELETE /admin/customers/:id/addresses/:address_id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /admin/customers/:id/addresses/:address_id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should update a customer address", async () => { + const customer = await customerModuleService.create({ + first_name: "John", + last_name: "Doe", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const address = await customerModuleService.addAddresses({ + customer_id: customer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }) - it("should update a customer address", async () => { - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", + const response = await api.delete( + `/admin/customers/${customer.id}/addresses/${address.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + + const updatedCustomer = await customerModuleService.retrieve( + customer.id, + { + relations: ["addresses"], + } + ) + + expect(updatedCustomer.addresses?.length).toEqual(0) + }) }) - - const address = await customerModuleService.addAddresses({ - customer_id: customer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - }) - - const api = useApi() as any - const response = await api.delete( - `/admin/customers/${customer.id}/addresses/${address.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - - const updatedCustomer = await customerModuleService.retrieve(customer.id, { - relations: ["addresses"], - }) - - expect(updatedCustomer.addresses?.length).toEqual(0) - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/delete-customer.ts b/integration-tests/modules/__tests__/customer/admin/delete-customer.ts index f5ad2a8c1b..cf2213efaf 100644 --- a/integration-tests/modules/__tests__/customer/admin/delete-customer.ts +++ b/integration-tests/modules/__tests__/customer/admin/delete-customer.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,54 +10,45 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("DELETE /admin/customers/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /admin/customers/:id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should delete a customer", async () => { + const customer = await customerModuleService.create({ + first_name: "John", + last_name: "Doe", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.delete( + `/admin/customers/${customer.id}`, + adminHeaders + ) - it("should delete a customer", async () => { - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", + expect(response.status).toEqual(200) + + const deletedCustomer = await customerModuleService.retrieve( + customer.id, + { + withDeleted: true, + } + ) + expect(deletedCustomer.deleted_at).toBeTruthy() + }) }) - - const api = useApi() as any - const response = await api.delete( - `/admin/customers/${customer.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - - const deletedCustomer = await customerModuleService.retrieve(customer.id, { - withDeleted: true, - }) - expect(deletedCustomer.deleted_at).toBeTruthy() - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/list-customer-addresses.ts b/integration-tests/modules/__tests__/customer/admin/list-customer-addresses.ts index c77564825b..d0d35a0e84 100644 --- a/integration-tests/modules/__tests__/customer/admin/list-customer-addresses.ts +++ b/integration-tests/modules/__tests__/customer/admin/list-customer-addresses.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,100 +10,88 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/customers/:id/addresses", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/customers/:id/addresses", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should get all customer addresses and its count", async () => { - const [customer] = await customerModuleService.create([ - { - first_name: "Test", - last_name: "Test", - email: "test@me.com", - addresses: [ + it("should get all customer addresses and its count", async () => { + const [customer] = await customerModuleService.create([ { first_name: "Test", last_name: "Test", - address_1: "Test street 1", + email: "test@me.com", + addresses: [ + { + first_name: "Test", + last_name: "Test", + address_1: "Test street 1", + }, + { + first_name: "Test", + last_name: "Test", + address_1: "Test street 2", + }, + { + first_name: "Test", + last_name: "Test", + address_1: "Test street 3", + }, + ], }, { - first_name: "Test", - last_name: "Test", - address_1: "Test street 2", + first_name: "Test Test", + last_name: "Test Test", + addresses: [ + { + first_name: "Test TEST", + last_name: "Test TEST", + address_1: "NOT street 1", + }, + ], }, - { - first_name: "Test", - last_name: "Test", - address_1: "Test street 3", - }, - ], - }, - { - first_name: "Test Test", - last_name: "Test Test", - addresses: [ - { - first_name: "Test TEST", - last_name: "Test TEST", - address_1: "NOT street 1", - }, - ], - }, - ]) + ]) - const api = useApi() as any - const response = await api.get( - `/admin/customers/${customer.id}/addresses`, - adminHeaders - ) + const response = await api.get( + `/admin/customers/${customer.id}/addresses`, + adminHeaders + ) - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(3) - expect(response.data.addresses).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(String), - customer_id: customer.id, - address_1: "Test street 1", - }), - expect.objectContaining({ - id: expect.any(String), - customer_id: customer.id, - address_1: "Test street 2", - }), - expect.objectContaining({ - id: expect.any(String), - customer_id: customer.id, - address_1: "Test street 3", - }), - ]) - ) - }) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(3) + expect(response.data.addresses).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + customer_id: customer.id, + address_1: "Test street 1", + }), + expect.objectContaining({ + id: expect.any(String), + customer_id: customer.id, + address_1: "Test street 2", + }), + expect.objectContaining({ + id: expect.any(String), + customer_id: customer.id, + address_1: "Test street 3", + }), + ]) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/list-customers.spec.ts b/integration-tests/modules/__tests__/customer/admin/list-customers.spec.ts index 5c91af3337..583921c489 100644 --- a/integration-tests/modules/__tests__/customer/admin/list-customers.spec.ts +++ b/integration-tests/modules/__tests__/customer/admin/list-customers.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,108 +10,96 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/customers", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/customers", () => { + let appContainer + let shutdownServer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should get all customers and its count", async () => { - await customerModuleService.create([ - { - first_name: "Test", - last_name: "Test", - email: "test@me.com", - }, - ]) - - const api = useApi() as any - const response = await api.get(`/admin/customers`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.customers).toEqual([ - expect.objectContaining({ - id: expect.any(String), - first_name: "Test", - last_name: "Test", - email: "test@me.com", - }), - ]) - }) - - it("should filter customers by last name", async () => { - await customerModuleService.create([ - { - first_name: "Jane", - last_name: "Doe", - email: "jane@me.com", - }, - { - first_name: "John", - last_name: "Doe", - email: "john@me.com", - }, - { - first_name: "LeBron", - last_name: "James", - email: "lebron@me.com", - }, - { - first_name: "John", - last_name: "Silver", - email: "johns@me.com", - }, - ]) - - const api = useApi() as any - const response = await api.get( - `/admin/customers?last_name=Doe`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(2) - expect(response.data.customers).toContainEqual( - expect.objectContaining({ - id: expect.any(String), - first_name: "Jane", - last_name: "Doe", - email: "jane@me.com", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - expect(response.data.customers).toContainEqual( - expect.objectContaining({ - id: expect.any(String), - first_name: "John", - last_name: "Doe", - email: "john@me.com", + + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) }) - ) - }) + + it("should get all customers and its count", async () => { + await customerModuleService.create([ + { + first_name: "Test", + last_name: "Test", + email: "test@me.com", + }, + ]) + + const response = await api.get(`/admin/customers`, adminHeaders) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.customers).toEqual([ + expect.objectContaining({ + id: expect.any(String), + first_name: "Test", + last_name: "Test", + email: "test@me.com", + }), + ]) + }) + + it("should filter customers by last name", async () => { + await customerModuleService.create([ + { + first_name: "Jane", + last_name: "Doe", + email: "jane@me.com", + }, + { + first_name: "John", + last_name: "Doe", + email: "john@me.com", + }, + { + first_name: "LeBron", + last_name: "James", + email: "lebron@me.com", + }, + { + first_name: "John", + last_name: "Silver", + email: "johns@me.com", + }, + ]) + + const response = await api.get( + `/admin/customers?last_name=Doe`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(2) + expect(response.data.customers).toContainEqual( + expect.objectContaining({ + id: expect.any(String), + first_name: "Jane", + last_name: "Doe", + email: "jane@me.com", + }) + ) + expect(response.data.customers).toContainEqual( + expect.objectContaining({ + id: expect.any(String), + first_name: "John", + last_name: "Doe", + email: "john@me.com", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/update-customer-address.spec.ts b/integration-tests/modules/__tests__/customer/admin/update-customer-address.spec.ts index 2c42cdc33f..bed711345d 100644 --- a/integration-tests/modules/__tests__/customer/admin/update-customer-address.spec.ts +++ b/integration-tests/modules/__tests__/customer/admin/update-customer-address.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,151 +10,137 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/customers/:id/addresses/:address_id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/customers/:id/addresses/:address_id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should update a customer address", async () => { - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", - }) - - const address = await customerModuleService.addAddresses({ - customer_id: customer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - }) - - const api = useApi() as any - const response = await api.post( - `/admin/customers/${customer.id}/addresses/${address.id}`, - { - first_name: "Jane", - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.address).toEqual( - expect.objectContaining({ - id: expect.any(String), - first_name: "Jane", - last_name: "Doe", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) - it("updates a new address to be default and unsets old one", async () => { - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should update a customer address", async () => { + const customer = await customerModuleService.create({ + first_name: "John", + last_name: "Doe", + }) + + const address = await customerModuleService.addAddresses({ + customer_id: customer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }) + + const response = await api.post( + `/admin/customers/${customer.id}/addresses/${address.id}`, + { + first_name: "Jane", + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.address).toEqual( + expect.objectContaining({ + id: expect.any(String), + first_name: "Jane", + last_name: "Doe", + }) + ) + }) + + it("updates a new address to be default and unsets old one", async () => { + const customer = await customerModuleService.create({ + first_name: "John", + last_name: "Doe", + }) + const [, address] = await customerModuleService.addAddresses([ + { + customer_id: customer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + is_default_shipping: true, + }, + { + customer_id: customer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 2", + }, + ]) + + const response = await api.post( + `/admin/customers/${customer.id}/addresses/${address.id}`, + { + first_name: "jane", + is_default_shipping: true, + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + + const [defaultAddress] = await customerModuleService.listAddresses({ + customer_id: customer.id, + is_default_shipping: true, + }) + + expect(defaultAddress.first_name).toEqual("jane") + expect(defaultAddress.address_1).toEqual("Test street 2") + }) + + // do the same as above but for billing address + it("updates a new address to be default and unsets old one", async () => { + const customer = await customerModuleService.create({ + first_name: "John", + last_name: "Doe", + }) + const [, address] = await customerModuleService.addAddresses([ + { + customer_id: customer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + is_default_billing: true, + }, + { + customer_id: customer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 2", + }, + ]) + + const response = await api.post( + `/admin/customers/${customer.id}/addresses/${address.id}`, + { + first_name: "jane", + is_default_billing: true, + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + + const [defaultAddress] = await customerModuleService.listAddresses({ + customer_id: customer.id, + is_default_billing: true, + }) + + expect(defaultAddress.first_name).toEqual("jane") + expect(defaultAddress.address_1).toEqual("Test street 2") + }) }) - const [, address] = await customerModuleService.addAddresses([ - { - customer_id: customer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - is_default_shipping: true, - }, - { - customer_id: customer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 2", - }, - ]) - - const api = useApi() as any - const response = await api.post( - `/admin/customers/${customer.id}/addresses/${address.id}`, - { - first_name: "jane", - is_default_shipping: true, - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - - const [defaultAddress] = await customerModuleService.listAddresses({ - customer_id: customer.id, - is_default_shipping: true, - }) - - expect(defaultAddress.first_name).toEqual("jane") - expect(defaultAddress.address_1).toEqual("Test street 2") - }) - - // do the same as above but for billing address - it("updates a new address to be default and unsets old one", async () => { - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", - }) - const [, address] = await customerModuleService.addAddresses([ - { - customer_id: customer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - is_default_billing: true, - }, - { - customer_id: customer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 2", - }, - ]) - - const api = useApi() as any - const response = await api.post( - `/admin/customers/${customer.id}/addresses/${address.id}`, - { - first_name: "jane", - is_default_billing: true, - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - - const [defaultAddress] = await customerModuleService.listAddresses({ - customer_id: customer.id, - is_default_billing: true, - }) - - expect(defaultAddress.first_name).toEqual("jane") - expect(defaultAddress.address_1).toEqual("Test street 2") - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/admin/update-customer.ts b/integration-tests/modules/__tests__/customer/admin/update-customer.ts index 0c956e9e32..7a584a8762 100644 --- a/integration-tests/modules/__tests__/customer/admin/update-customer.ts +++ b/integration-tests/modules/__tests__/customer/admin/update-customer.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import adminSeeder from "../../../../helpers/admin-seeder" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,59 +10,47 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/customers/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/customers/:id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should update a customer", async () => { - const customer = await customerModuleService.create({ - first_name: "John", - last_name: "Doe", - }) - - const api = useApi() as any - const response = await api.post( - `/admin/customers/${customer.id}`, - { - first_name: "Jane", - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.customer).toEqual( - expect.objectContaining({ - id: expect.any(String), - first_name: "Jane", - last_name: "Doe", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) + + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should update a customer", async () => { + const customer = await customerModuleService.create({ + first_name: "John", + last_name: "Doe", + }) + + const response = await api.post( + `/admin/customers/${customer.id}`, + { + first_name: "Jane", + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.customer).toEqual( + expect.objectContaining({ + id: expect.any(String), + first_name: "Jane", + last_name: "Doe", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/store/create-customer-addresses.ts b/integration-tests/modules/__tests__/customer/store/create-customer-addresses.ts index ae7d13a128..5cb99635ec 100644 --- a/integration-tests/modules/__tests__/customer/store/create-customer-addresses.ts +++ b/integration-tests/modules/__tests__/customer/store/create-customer-addresses.ts @@ -1,74 +1,59 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("POST /store/customers/me/addresses", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /store/customers/me/addresses", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should create a customer address", async () => { - const { customer, jwt } = await createAuthenticatedCustomer(appContainer) - - const api = useApi() as any - const response = await api.post( - `/store/customers/me/addresses`, - { - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - }, - { headers: { authorization: `Bearer ${jwt}` } } - ) - - expect(response.status).toEqual(200) - expect(response.data.address).toEqual( - expect.objectContaining({ - id: expect.any(String), - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - customer_id: customer.id, + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - const customerWithAddresses = await customerModuleService.retrieve( - customer.id, - { relations: ["addresses"] } - ) + it("should create a customer address", async () => { + const { customer, jwt } = await createAuthenticatedCustomer( + appContainer + ) - expect(customerWithAddresses.addresses?.length).toEqual(1) - }) + const response = await api.post( + `/store/customers/me/addresses`, + { + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }, + { headers: { authorization: `Bearer ${jwt}` } } + ) + + expect(response.status).toEqual(200) + expect(response.data.address).toEqual( + expect.objectContaining({ + id: expect.any(String), + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + customer_id: customer.id, + }) + ) + + const customerWithAddresses = await customerModuleService.retrieve( + customer.id, + { relations: ["addresses"] } + ) + + expect(customerWithAddresses.addresses?.length).toEqual(1) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/store/create-customer.spec.ts b/integration-tests/modules/__tests__/customer/store/create-customer.spec.ts index ae1f6c0576..d47dfa265e 100644 --- a/integration-tests/modules/__tests__/customer/store/create-customer.spec.ts +++ b/integration-tests/modules/__tests__/customer/store/create-customer.spec.ts @@ -1,82 +1,66 @@ import { IAuthModuleService, ICustomerModuleService } from "@medusajs/types" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import adminSeeder from "../../../../helpers/admin-seeder" -import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" import jwt from "jsonwebtoken" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("POST /store/customers", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /store/customers", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await adminSeeder(dbConnection) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should create a customer", async () => { - const authService: IAuthModuleService = appContainer.resolve( - ModuleRegistrationName.AUTH - ) - const { jwt_secret } = appContainer.resolve("configModule").projectConfig - const authUser = await authService.create({ - entity_id: "store_user", - provider: "emailpass", - scope: "store", - }) - - const token = jwt.sign(authUser, jwt_secret) - - const api = useApi() as any - const response = await api.post( - `/store/customers`, - { - first_name: "John", - last_name: "Doe", - email: "john@me.com", - }, - { headers: { authorization: `Bearer ${token}` } } - ) - - expect(response.status).toEqual(200) - expect(response.data.customer).toEqual( - expect.objectContaining({ - id: expect.any(String), - first_name: "John", - last_name: "Doe", - email: "john@me.com", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + }) + + it("should create a customer", async () => { + const authService: IAuthModuleService = appContainer.resolve( + ModuleRegistrationName.AUTH + ) + const { jwt_secret } = + appContainer.resolve("configModule").projectConfig + const authUser = await authService.create({ + entity_id: "store_user", + provider: "emailpass", + scope: "store", + }) + + const token = jwt.sign(authUser, jwt_secret) + + const response = await api.post( + `/store/customers`, + { + first_name: "John", + last_name: "Doe", + email: "john@me.com", + }, + { headers: { authorization: `Bearer ${token}` } } + ) + + expect(response.status).toEqual(200) + expect(response.data.customer).toEqual( + expect.objectContaining({ + id: expect.any(String), + first_name: "John", + last_name: "Doe", + email: "john@me.com", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/store/delete-customer-address.spec.ts b/integration-tests/modules/__tests__/customer/store/delete-customer-address.spec.ts index 723163e74d..411d6bb3f4 100644 --- a/integration-tests/modules/__tests__/customer/store/delete-customer-address.spec.ts +++ b/integration-tests/modules/__tests__/customer/store/delete-customer-address.spec.ts @@ -1,90 +1,77 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" const env = { MEDUSA_FF_MEDUSA_V2: true } jest.setTimeout(50000) -describe("DELETE /store/customers/me/addresses/:address_id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /store/customers/me/addresses/:address_id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should delete a customer address", async () => { - const { customer, jwt } = await createAuthenticatedCustomer(appContainer) - - const address = await customerModuleService.addAddresses({ - customer_id: customer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - }) - - const api = useApi() as any - const response = await api.delete( - `/store/customers/me/addresses/${address.id}`, - { headers: { authorization: `Bearer ${jwt}` } } - ) - - expect(response.status).toEqual(200) - - const updatedCustomer = await customerModuleService.retrieve(customer.id, { - relations: ["addresses"], - }) - - expect(updatedCustomer.addresses?.length).toEqual(0) - }) - - it("should fail to delete another customer's address", async () => { - const { jwt } = await createAuthenticatedCustomer(appContainer) - - const otherCustomer = await customerModuleService.create({ - first_name: "Jane", - last_name: "Doe", - }) - const address = await customerModuleService.addAddresses({ - customer_id: otherCustomer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - }) - - const api = useApi() as any - const response = await api - .delete(`/store/customers/me/addresses/${address.id}`, { - headers: { authorization: `Bearer ${jwt}` }, + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - .catch((e) => e.response) - expect(response.status).toEqual(404) - }) + it("should delete a customer address", async () => { + const { customer, jwt } = await createAuthenticatedCustomer( + appContainer + ) + + const address = await customerModuleService.addAddresses({ + customer_id: customer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }) + + const response = await api.delete( + `/store/customers/me/addresses/${address.id}`, + { headers: { authorization: `Bearer ${jwt}` } } + ) + + expect(response.status).toEqual(200) + + const updatedCustomer = await customerModuleService.retrieve( + customer.id, + { + relations: ["addresses"], + } + ) + + expect(updatedCustomer.addresses?.length).toEqual(0) + }) + + it("should fail to delete another customer's address", async () => { + const { jwt } = await createAuthenticatedCustomer(appContainer) + + const otherCustomer = await customerModuleService.create({ + first_name: "Jane", + last_name: "Doe", + }) + const address = await customerModuleService.addAddresses({ + customer_id: otherCustomer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }) + + const response = await api + .delete(`/store/customers/me/addresses/${address.id}`, { + headers: { authorization: `Bearer ${jwt}` }, + }) + .catch((e) => e.response) + + expect(response.status).toEqual(404) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/store/get-me.spec.ts b/integration-tests/modules/__tests__/customer/store/get-me.spec.ts index d30fca0bc8..9e305215c2 100644 --- a/integration-tests/modules/__tests__/customer/store/get-me.spec.ts +++ b/integration-tests/modules/__tests__/customer/store/get-me.spec.ts @@ -1,60 +1,45 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("GET /store/customers", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /store/customers", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should retrieve auth user's customer", async () => { - const { customer, jwt } = await createAuthenticatedCustomer(appContainer) - - const api = useApi() as any - const response = await api.get(`/store/customers/me`, { - headers: { authorization: `Bearer ${jwt}` }, - }) - - expect(response.status).toEqual(200) - expect(response.data.customer).toEqual( - expect.objectContaining({ - id: customer.id, - first_name: "John", - last_name: "Doe", - email: "john@me.com", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) + + it("should retrieve auth user's customer", async () => { + const { customer, jwt } = await createAuthenticatedCustomer( + appContainer + ) + + const response = await api.get(`/store/customers/me`, { + headers: { authorization: `Bearer ${jwt}` }, + }) + + expect(response.status).toEqual(200) + expect(response.data.customer).toEqual( + expect.objectContaining({ + id: customer.id, + first_name: "John", + last_name: "Doe", + email: "john@me.com", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/store/list-customer-addresses.ts b/integration-tests/modules/__tests__/customer/store/list-customer-addresses.ts index 4e7cf97582..685cf19cb8 100644 --- a/integration-tests/modules/__tests__/customer/store/list-customer-addresses.ts +++ b/integration-tests/modules/__tests__/customer/store/list-customer-addresses.ts @@ -1,109 +1,90 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ICustomerModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import {medusaIntegrationTestRunner} from "medusa-test-utils"; const env = { MEDUSA_FF_MEDUSA_V2: true } jest.setTimeout(100000) -describe("GET /store/customers/me/addresses", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /store/customers/me/addresses", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - try { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - } catch (error) { - console.error(error) - } - }) + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should get all customer addresses and its count", async () => { + const { customer, jwt } = await createAuthenticatedCustomer( + appContainer + ) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + await customerModuleService.addAddresses([ + { + first_name: "Test", + last_name: "Test", + address_1: "Test street 1", + customer_id: customer.id, + }, + { + first_name: "Test", + last_name: "Test", + address_1: "Test street 2", + customer_id: customer.id, + }, + { + first_name: "Test", + last_name: "Test", + address_1: "Test street 3", + customer_id: customer.id, + }, + ]) - it("should get all customer addresses and its count", async () => { - const { customer, jwt } = await createAuthenticatedCustomer(appContainer) + await customerModuleService.create({ + first_name: "Test Test", + last_name: "Test Test", + addresses: [ + { + first_name: "Test TEST", + last_name: "Test TEST", + address_1: "NOT street 1", + }, + ], + }) - await customerModuleService.addAddresses([ - { - first_name: "Test", - last_name: "Test", - address_1: "Test street 1", - customer_id: customer.id, - }, - { - first_name: "Test", - last_name: "Test", - address_1: "Test street 2", - customer_id: customer.id, - }, - { - first_name: "Test", - last_name: "Test", - address_1: "Test street 3", - customer_id: customer.id, - }, - ]) + const response = await api.get(`/store/customers/me/addresses`, { + headers: { authorization: `Bearer ${jwt}` }, + }) - await customerModuleService.create({ - first_name: "Test Test", - last_name: "Test Test", - addresses: [ - { - first_name: "Test TEST", - last_name: "Test TEST", - address_1: "NOT street 1", - }, - ], + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(3) + expect(response.data.addresses).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + customer_id: customer.id, + address_1: "Test street 1", + }), + expect.objectContaining({ + id: expect.any(String), + customer_id: customer.id, + address_1: "Test street 2", + }), + expect.objectContaining({ + id: expect.any(String), + customer_id: customer.id, + address_1: "Test street 3", + }), + ]) + ) + }) }) - - const api = useApi() as any - const response = await api.get(`/store/customers/me/addresses`, { - headers: { authorization: `Bearer ${jwt}` }, - }) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(3) - expect(response.data.addresses).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(String), - customer_id: customer.id, - address_1: "Test street 1", - }), - expect.objectContaining({ - id: expect.any(String), - customer_id: customer.id, - address_1: "Test street 2", - }), - expect.objectContaining({ - id: expect.any(String), - customer_id: customer.id, - address_1: "Test street 3", - }), - ]) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/customer/store/update-customer-address.spec.ts b/integration-tests/modules/__tests__/customer/store/update-customer-address.spec.ts index 255af7e6bd..a7e0654495 100644 --- a/integration-tests/modules/__tests__/customer/store/update-customer-address.spec.ts +++ b/integration-tests/modules/__tests__/customer/store/update-customer-address.spec.ts @@ -1,97 +1,81 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { ICustomerModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" import { createAuthenticatedCustomer } from "../../../helpers/create-authenticated-customer" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("POST /store/customers/:id/addresses/:address_id", () => { - let dbConnection - let appContainer - let shutdownServer - let customerModuleService: ICustomerModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /store/customers/:id/addresses/:address_id", () => { + let appContainer + let customerModuleService: ICustomerModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - customerModuleService = appContainer.resolve( - ModuleRegistrationName.CUSTOMER - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should update a customer address", async () => { - const { customer, jwt } = await createAuthenticatedCustomer(appContainer) - - const address = await customerModuleService.addAddresses({ - customer_id: customer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - }) - - const api = useApi() as any - const response = await api.post( - `/store/customers/me/addresses/${address.id}`, - { - first_name: "Jane", - }, - { headers: { authorization: `Bearer ${jwt}` } } - ) - - expect(response.status).toEqual(200) - expect(response.data.address).toEqual( - expect.objectContaining({ - id: address.id, - first_name: "Jane", - last_name: "Doe", + beforeAll(async () => { + appContainer = getContainer() + customerModuleService = appContainer.resolve( + ModuleRegistrationName.CUSTOMER + ) }) - ) - }) - it("should fail to update another customer's address", async () => { - const { jwt } = await createAuthenticatedCustomer(appContainer) + it("should update a customer address", async () => { + const { customer, jwt } = await createAuthenticatedCustomer( + appContainer + ) - const otherCustomer = await customerModuleService.create({ - first_name: "Jane", - last_name: "Doe", + const address = await customerModuleService.addAddresses({ + customer_id: customer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }) + + const response = await api.post( + `/store/customers/me/addresses/${address.id}`, + { + first_name: "Jane", + }, + { headers: { authorization: `Bearer ${jwt}` } } + ) + + expect(response.status).toEqual(200) + expect(response.data.address).toEqual( + expect.objectContaining({ + id: address.id, + first_name: "Jane", + last_name: "Doe", + }) + ) + }) + + it("should fail to update another customer's address", async () => { + const { jwt } = await createAuthenticatedCustomer(appContainer) + + const otherCustomer = await customerModuleService.create({ + first_name: "Jane", + last_name: "Doe", + }) + + const address = await customerModuleService.addAddresses({ + customer_id: otherCustomer.id, + first_name: "John", + last_name: "Doe", + address_1: "Test street 1", + }) + + const response = await api + .post( + `/store/customers/me/addresses/${address.id}`, + { first_name: "Jane" }, + { headers: { authorization: `Bearer ${jwt}` } } + ) + .catch((e) => e.response) + + expect(response.status).toEqual(404) + }) }) - - const address = await customerModuleService.addAddresses({ - customer_id: otherCustomer.id, - first_name: "John", - last_name: "Doe", - address_1: "Test street 1", - }) - - const api = useApi() as any - const response = await api - .post( - `/store/customers/me/addresses/${address.id}`, - { first_name: "Jane" }, - { headers: { authorization: `Bearer ${jwt}` } } - ) - .catch((e) => e.response) - - expect(response.status).toEqual(404) - }) + }, }) diff --git a/integration-tests/modules/__tests__/invites/accept-invite.spec.ts b/integration-tests/modules/__tests__/invites/accept-invite.spec.ts index 02e56d759f..a1f715005c 100644 --- a/integration-tests/modules/__tests__/invites/accept-invite.spec.ts +++ b/integration-tests/modules/__tests__/invites/accept-invite.spec.ts @@ -1,13 +1,7 @@ -import { IAuthModuleService, IUserModuleService } from "@medusajs/types" -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" +import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../helpers/create-admin-user" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,97 +10,82 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/invites/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/invites/:id", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should fail to accept an invite with an invalid invite token", async () => { - const api = useApi()! as AxiosInstance - - const authResponse = await api.post(`/auth/admin/emailpass`, { - email: "potential_member@test.com", - password: "supersecret", - }) - - expect(authResponse.status).toEqual(200) - const token = authResponse.data.token - - const acceptResponse = await api - .post( - `/admin/invites/accept?token=${"non-existing-token"}`, - { - first_name: "John", - }, - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ) - .catch((e) => e) - - expect(acceptResponse.response.status).toEqual(401) - expect(acceptResponse.response.data.message).toEqual("Unauthorized") - }) - - it("should accept an invite", async () => { - const invite = await userModuleService.createInvites({ - email: "potential_member@test.com", - }) - - const api = useApi()! as AxiosInstance - - const authResponse = await api.post(`/auth/admin/emailpass`, { - email: "potential_member@test.com", - password: "supersecret", - }) - - expect(authResponse.status).toEqual(200) - const token = authResponse.data.token - - const acceptResponse = await api.post( - `/admin/invites/accept?token=${invite.token}`, - { - first_name: "John", - }, - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ) - - expect(acceptResponse.status).toEqual(200) - expect(acceptResponse.data.user).toEqual( - expect.objectContaining({ - email: "potential_member@test.com", - first_name: "John", + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) }) - ) - }) + + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should fail to accept an invite with an invalid invite token", async () => { + const authResponse = await api.post(`/auth/admin/emailpass`, { + email: "potential_member@test.com", + password: "supersecret", + }) + + expect(authResponse.status).toEqual(200) + const token = authResponse.data.token + + const acceptResponse = await api + .post( + `/admin/invites/accept?token=${"non-existing-token"}`, + { + first_name: "John", + }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ) + .catch((e) => e) + + expect(acceptResponse.response.status).toEqual(401) + expect(acceptResponse.response.data.message).toEqual("Unauthorized") + }) + + it("should accept an invite", async () => { + const invite = await userModuleService.createInvites({ + email: "potential_member@test.com", + }) + + const authResponse = await api.post(`/auth/admin/emailpass`, { + email: "potential_member@test.com", + password: "supersecret", + }) + + expect(authResponse.status).toEqual(200) + const token = authResponse.data.token + + const acceptResponse = await api.post( + `/admin/invites/accept?token=${invite.token}`, + { + first_name: "John", + }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ) + + expect(acceptResponse.status).toEqual(200) + expect(acceptResponse.data.user).toEqual( + expect.objectContaining({ + email: "potential_member@test.com", + first_name: "John", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/invites/create-invite.spec.ts b/integration-tests/modules/__tests__/invites/create-invite.spec.ts index 5d36823db9..14fa28b48b 100644 --- a/integration-tests/modules/__tests__/invites/create-invite.spec.ts +++ b/integration-tests/modules/__tests__/invites/create-invite.spec.ts @@ -1,11 +1,5 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" -import adminSeeder from "../../../helpers/admin-seeder" -import { AxiosInstance } from "axios" import { createAdminUser } from "../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -14,43 +8,26 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/invites", () => { - let dbConnection - let shutdownServer +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/invites", () => { + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, getContainer()) + }) - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - }) + it("create an invite", async () => { + const body = { + email: "test_member@test.com", + } - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + const response = await api.post(`/admin/invites`, body, adminHeaders) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("create an invite", async () => { - const api = useApi()! as AxiosInstance - - const body = { - email: "test_member@test.com", - } - - const response = await api.post(`/admin/invites`, body, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data).toEqual({ - invite: expect.objectContaining(body), + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + invite: expect.objectContaining(body), + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/invites/delete-invite.spec.ts b/integration-tests/modules/__tests__/invites/delete-invite.spec.ts index cfb7b069f0..b062178eb0 100644 --- a/integration-tests/modules/__tests__/invites/delete-invite.spec.ts +++ b/integration-tests/modules/__tests__/invites/delete-invite.spec.ts @@ -1,14 +1,7 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" -import adminSeeder from "../../../helpers/admin-seeder" -import { AxiosInstance } from "axios" import { createAdminUser } from "../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -17,61 +10,48 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("DELETE /admin/invites/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /admin/invites/:id", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should delete a single invite", async () => { + const invite = await userModuleService.createInvites({ + email: "potential_member@test.com", + token: "test", + expires_at: new Date(), + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.delete( + `/admin/invites/${invite.id}`, + adminHeaders + ) - it("should delete a single invite", async () => { - const invite = await userModuleService.createInvites({ - email: "potential_member@test.com", - token: "test", - expires_at: new Date(), + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + id: invite.id, + object: "invite", + deleted: true, + }) + + const { response: deletedResponse } = await api + .get(`/admin/invites/${invite.id}`, adminHeaders) + .catch((e) => e) + + expect(deletedResponse.status).toEqual(404) + expect(deletedResponse.data.type).toEqual("not_found") + }) }) - - const api = useApi()! as AxiosInstance - - const response = await api.delete( - `/admin/invites/${invite.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data).toEqual({ - id: invite.id, - object: "invite", - deleted: true, - }) - - const { response: deletedResponse } = await api - .get(`/admin/invites/${invite.id}`, adminHeaders) - .catch((e) => e) - - expect(deletedResponse.status).toEqual(404) - expect(deletedResponse.data.type).toEqual("not_found") - }) + }, }) diff --git a/integration-tests/modules/__tests__/invites/list-invites.spec.ts b/integration-tests/modules/__tests__/invites/list-invites.spec.ts index b172af9c5a..412ad9573b 100644 --- a/integration-tests/modules/__tests__/invites/list-invites.spec.ts +++ b/integration-tests/modules/__tests__/invites/list-invites.spec.ts @@ -1,14 +1,7 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" -import adminSeeder from "../../../helpers/admin-seeder" -import { AxiosInstance } from "axios" import { createAdminUser } from "../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -17,54 +10,41 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/invites", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/invites", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should list invites", async () => { + await userModuleService.createInvites({ + email: "potential_member@test.com", + token: "test", + expires_at: new Date(), + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.get(`/admin/invites`, adminHeaders) - it("should list invites", async () => { - await userModuleService.createInvites({ - email: "potential_member@test.com", - token: "test", - expires_at: new Date(), + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + invites: [ + expect.objectContaining({ email: "potential_member@test.com" }), + ], + count: 1, + offset: 0, + limit: 50, + }) + }) }) - - const api = useApi()! as AxiosInstance - - const response = await api.get(`/admin/invites`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data).toEqual({ - invites: [ - expect.objectContaining({ email: "potential_member@test.com" }), - ], - count: 1, - offset: 0, - limit: 50, - }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/invites/resend-invite.spec.ts b/integration-tests/modules/__tests__/invites/resend-invite.spec.ts index 5a1237d160..a17be34635 100644 --- a/integration-tests/modules/__tests__/invites/resend-invite.spec.ts +++ b/integration-tests/modules/__tests__/invites/resend-invite.spec.ts @@ -1,13 +1,7 @@ -import { IAuthModuleService, IUserModuleService } from "@medusajs/types" -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" +import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../helpers/create-admin-user" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,52 +10,39 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/invites/:id/resend", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/invites/:id/resend", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should resend a single invite", async () => { + const invite = await userModuleService.createInvites({ + email: "potential_member@test.com", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.post( + `/admin/invites/${invite.id}/resend`, + {}, + adminHeaders + ) - it("should resend a single invite", async () => { - const invite = await userModuleService.createInvites({ - email: "potential_member@test.com", + expect(response.status).toEqual(200) + expect(response.data.invite.token).not.toEqual(invite.token) + expect(response.data.invite).toEqual( + expect.objectContaining({ email: "potential_member@test.com" }) + ) + }) }) - - const api = useApi()! as AxiosInstance - - const response = await api.post( - `/admin/invites/${invite.id}/resend`, - {}, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.invite.token).not.toEqual(invite.token) - expect(response.data.invite).toEqual( - expect.objectContaining({ email: "potential_member@test.com" }) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/invites/retrieve-invite.spec.ts b/integration-tests/modules/__tests__/invites/retrieve-invite.spec.ts index f81897f33e..bbe30c5306 100644 --- a/integration-tests/modules/__tests__/invites/retrieve-invite.spec.ts +++ b/integration-tests/modules/__tests__/invites/retrieve-invite.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { IAuthModuleService, IUserModuleService } from "@medusajs/types" +import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" -import { AxiosInstance } from "axios" import { createAdminUser } from "../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,47 +10,37 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/invites/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/invites/:id", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should retrieve a single invite", async () => { + const invite = await userModuleService.createInvites({ + email: "potential_member@test.com", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.get( + `/admin/invites/${invite.id}`, + adminHeaders + ) - it("should retrieve a single invite", async () => { - const invite = await userModuleService.createInvites({ - email: "potential_member@test.com", + expect(response.status).toEqual(200) + expect(response.data.invite).toEqual( + expect.objectContaining({ email: "potential_member@test.com" }) + ) + }) }) - - const api = useApi()! as AxiosInstance - - const response = await api.get(`/admin/invites/${invite.id}`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data.invite).toEqual( - expect.objectContaining({ email: "potential_member@test.com" }) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/link-modules/cart-links.spec.ts b/integration-tests/modules/__tests__/link-modules/cart-links.spec.ts index c4fb270033..1767b94317 100644 --- a/integration-tests/modules/__tests__/link-modules/cart-links.spec.ts +++ b/integration-tests/modules/__tests__/link-modules/cart-links.spec.ts @@ -6,200 +6,190 @@ import { IRegionModuleService, ISalesChannelModuleService, } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { getContainer } from "../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../environment-helpers/use-db" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Cart links", () => { - let dbConnection - let appContainer - let shutdownServer - let cartModuleService: ICartModuleService - let regionModule: IRegionModuleService - let customerModule: ICustomerModuleService - let scModuleService: ISalesChannelModuleService - let paymentModuleService: IPaymentModuleService - let remoteQuery, remoteLink +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Cart links", () => { + let appContainer + let cartModuleService: ICartModuleService + let regionModule: IRegionModuleService + let customerModule: ICustomerModuleService + let scModuleService: ISalesChannelModuleService + let paymentModuleService: IPaymentModuleService + let remoteQuery, remoteLink - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) - regionModule = appContainer.resolve(ModuleRegistrationName.REGION) - customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER) - scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL) - regionModule = appContainer.resolve(ModuleRegistrationName.REGION) - paymentModuleService = appContainer.resolve(ModuleRegistrationName.PAYMENT) - remoteQuery = appContainer.resolve("remoteQuery") - remoteLink = appContainer.resolve("remoteLink") - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should query carts, sales channels, customers, regions with remote query", async () => { - const region = await regionModule.create({ - name: "Region", - currency_code: "usd", - }) - - const customer = await customerModule.create({ - email: "tony@stark.com", - }) - - const salesChannel = await scModuleService.create({ - name: "Webshop", - }) - - const cart = await cartModuleService.create({ - email: "tony@stark.com", - currency_code: "usd", - region_id: region.id, - sales_channel_id: salesChannel.id, - customer_id: customer.id, - }) - - const paymentCollection = - await paymentModuleService.createPaymentCollections({ - currency_code: "usd", - region_id: region.id, - amount: 1000, + beforeAll(async () => { + appContainer = getContainer() + cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) + regionModule = appContainer.resolve(ModuleRegistrationName.REGION) + customerModule = appContainer.resolve(ModuleRegistrationName.CUSTOMER) + scModuleService = appContainer.resolve( + ModuleRegistrationName.SALES_CHANNEL + ) + regionModule = appContainer.resolve(ModuleRegistrationName.REGION) + paymentModuleService = appContainer.resolve( + ModuleRegistrationName.PAYMENT + ) + remoteQuery = appContainer.resolve("remoteQuery") + remoteLink = appContainer.resolve("remoteLink") }) - await remoteLink.create([ - { - [Modules.CART]: { - cart_id: cart.id, - }, - [Modules.PAYMENT]: { - payment_collection_id: paymentCollection.id, - }, - }, - ]) + it("should query carts, sales channels, customers, regions with remote query", async () => { + const region = await regionModule.create({ + name: "Region", + currency_code: "usd", + }) - const carts = await remoteQuery({ - cart: { - fields: ["id"], - region: { - fields: ["id"], - }, - customer: { - fields: ["id"], - }, - sales_channel: { - fields: ["id"], - }, - payment_collection: { - fields: ["id"], - }, - }, + const customer = await customerModule.create({ + email: "tony@stark.com", + }) + + const salesChannel = await scModuleService.create({ + name: "Webshop", + }) + + const cart = await cartModuleService.create({ + email: "tony@stark.com", + currency_code: "usd", + region_id: region.id, + sales_channel_id: salesChannel.id, + customer_id: customer.id, + }) + + const paymentCollection = + await paymentModuleService.createPaymentCollections({ + currency_code: "usd", + region_id: region.id, + amount: 1000, + }) + + await remoteLink.create([ + { + [Modules.CART]: { + cart_id: cart.id, + }, + [Modules.PAYMENT]: { + payment_collection_id: paymentCollection.id, + }, + }, + ]) + + const carts = await remoteQuery({ + cart: { + fields: ["id"], + region: { + fields: ["id"], + }, + customer: { + fields: ["id"], + }, + sales_channel: { + fields: ["id"], + }, + payment_collection: { + fields: ["id"], + }, + }, + }) + + const salesChannels = await remoteQuery({ + sales_channel: { + fields: ["id"], + carts: { + fields: ["id"], + }, + }, + }) + + const customers = await remoteQuery({ + customer: { + fields: ["id"], + carts: { + fields: ["id"], + }, + }, + }) + + const regions = await remoteQuery({ + region: { + fields: ["id"], + carts: { + fields: ["id"], + }, + }, + }) + + const paymentCollections = await remoteQuery({ + payment: { + fields: ["id"], + cart: { + fields: ["id"], + }, + }, + }) + + expect(carts).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: cart.id, + customer: expect.objectContaining({ id: customer.id }), + sales_channel: expect.objectContaining({ id: salesChannel.id }), + region: expect.objectContaining({ id: region.id }), + payment_collection: expect.objectContaining({ + id: paymentCollection.id, + }), + }), + ]) + ) + + expect(salesChannels).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: salesChannel.id, + carts: expect.arrayContaining([ + expect.objectContaining({ id: cart.id }), + ]), + }), + ]) + ) + + expect(customers).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: customer.id, + carts: expect.arrayContaining([ + expect.objectContaining({ id: cart.id }), + ]), + }), + ]) + ) + + expect(regions).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: region.id, + carts: expect.arrayContaining([ + expect.objectContaining({ id: cart.id }), + ]), + }), + ]) + ) + + expect(paymentCollections).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: paymentCollection.id, + cart: expect.objectContaining({ id: cart.id }), + }), + ]) + ) + }) }) - - const salesChannels = await remoteQuery({ - sales_channel: { - fields: ["id"], - carts: { - fields: ["id"], - }, - }, - }) - - const customers = await remoteQuery({ - customer: { - fields: ["id"], - carts: { - fields: ["id"], - }, - }, - }) - - const regions = await remoteQuery({ - region: { - fields: ["id"], - carts: { - fields: ["id"], - }, - }, - }) - - const paymentCollections = await remoteQuery({ - payment: { - fields: ["id"], - cart: { - fields: ["id"], - }, - }, - }) - - expect(carts).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: cart.id, - customer: expect.objectContaining({ id: customer.id }), - sales_channel: expect.objectContaining({ id: salesChannel.id }), - region: expect.objectContaining({ id: region.id }), - payment_collection: expect.objectContaining({ - id: paymentCollection.id, - }), - }), - ]) - ) - - expect(salesChannels).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: salesChannel.id, - carts: expect.arrayContaining([ - expect.objectContaining({ id: cart.id }), - ]), - }), - ]) - ) - - expect(customers).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: customer.id, - carts: expect.arrayContaining([ - expect.objectContaining({ id: cart.id }), - ]), - }), - ]) - ) - - expect(regions).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: region.id, - carts: expect.arrayContaining([ - expect.objectContaining({ id: cart.id }), - ]), - }), - ]) - ) - - expect(paymentCollections).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: paymentCollection.id, - cart: expect.objectContaining({ id: cart.id }), - }), - ]) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/link-modules/cart-region.spec.ts b/integration-tests/modules/__tests__/link-modules/cart-region.spec.ts index d0c67991b5..aca1502f71 100644 --- a/integration-tests/modules/__tests__/link-modules/cart-region.spec.ts +++ b/integration-tests/modules/__tests__/link-modules/cart-region.spec.ts @@ -1,91 +1,77 @@ import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { ICartModuleService, IRegionModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { getContainer } from "../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../environment-helpers/use-db" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Link: Cart Region", () => { - let dbConnection - let appContainer - let shutdownServer - let cartModuleService: ICartModuleService - let regionModule: IRegionModuleService - let remoteQuery +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Link: Cart Region", () => { + let appContainer + let cartModuleService: ICartModuleService + let regionModule: IRegionModuleService + let remoteQuery - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) - regionModule = appContainer.resolve(ModuleRegistrationName.REGION) - remoteQuery = appContainer.resolve("remoteQuery") - }) + beforeAll(async () => { + appContainer = getContainer() + cartModuleService = appContainer.resolve(ModuleRegistrationName.CART) + regionModule = appContainer.resolve(ModuleRegistrationName.REGION) + remoteQuery = appContainer.resolve("remoteQuery") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should query carts and regions with remote query", async () => { + const region = await regionModule.create({ + name: "Region", + currency_code: "usd", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const cart = await cartModuleService.create({ + email: "tony@stark.com", + currency_code: "usd", + region_id: region.id, + }) - it("should query carts and regions with remote query", async () => { - const region = await regionModule.create({ - name: "Region", - currency_code: "usd", + const carts = await remoteQuery({ + cart: { + fields: ["id"], + region: { + fields: ["id"], + }, + }, + }) + + const regions = await remoteQuery({ + region: { + fields: ["id"], + carts: { + fields: ["id"], + }, + }, + }) + + expect(carts).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: cart.id, + region: expect.objectContaining({ id: region.id }), + }), + ]) + ) + + expect(regions).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: region.id, + carts: expect.arrayContaining([ + expect.objectContaining({ id: cart.id }), + ]), + }), + ]) + ) + }) }) - - const cart = await cartModuleService.create({ - email: "tony@stark.com", - currency_code: "usd", - region_id: region.id, - }) - - const carts = await remoteQuery({ - cart: { - fields: ["id"], - region: { - fields: ["id"], - }, - }, - }) - - const regions = await remoteQuery({ - region: { - fields: ["id"], - carts: { - fields: ["id"], - }, - }, - }) - - expect(carts).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: cart.id, - region: expect.objectContaining({ id: region.id }), - }), - ]) - ) - - expect(regions).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: region.id, - carts: expect.arrayContaining([ - expect.objectContaining({ id: cart.id }), - ]), - }), - ]) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/link-modules/publishable-key-sales-channel.spec.ts b/integration-tests/modules/__tests__/link-modules/publishable-key-sales-channel.spec.ts index 7a48d8b329..60330d50b8 100644 --- a/integration-tests/modules/__tests__/link-modules/publishable-key-sales-channel.spec.ts +++ b/integration-tests/modules/__tests__/link-modules/publishable-key-sales-channel.spec.ts @@ -3,103 +3,91 @@ import { IApiKeyModuleService, ISalesChannelModuleService, } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { getContainer } from "../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../environment-helpers/use-db" import { remoteQueryObjectFromString } from "@medusajs/utils" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Publishable keys and sales channel link", () => { - let dbConnection - let appContainer - let shutdownServer - let apiKeyModule: IApiKeyModuleService - let scModuleService: ISalesChannelModuleService - let remoteQuery - let remoteLink +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Publishable keys and sales channel link", () => { + let appContainer + let apiKeyModule: IApiKeyModuleService + let scModuleService: ISalesChannelModuleService + let remoteQuery + let remoteLink - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - apiKeyModule = appContainer.resolve(ModuleRegistrationName.API_KEY) - scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL) - remoteQuery = appContainer.resolve("remoteQuery") - remoteLink = appContainer.resolve("remoteLink") - }) + beforeAll(async () => { + appContainer = getContainer() + apiKeyModule = appContainer.resolve(ModuleRegistrationName.API_KEY) + scModuleService = appContainer.resolve( + ModuleRegistrationName.SALES_CHANNEL + ) + remoteQuery = appContainer.resolve("remoteQuery") + remoteLink = appContainer.resolve("remoteLink") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should query api key and sales channels link with remote query", async () => { + const salesChannel = await scModuleService.create({ + name: "Webshop", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const apiKeys = await apiKeyModule.create([ + { + title: "Api key", + type: "publishable", + created_by: "test", + }, + { + title: "Api key 2", + type: "publishable", + created_by: "test", + }, + ]) - it("should query api key and sales channels link with remote query", async () => { - const salesChannel = await scModuleService.create({ - name: "Webshop", + await remoteLink.create([ + { + [Modules.API_KEY]: { + publishable_key_id: apiKeys[0].id, + }, + [Modules.SALES_CHANNEL]: { + sales_channel_id: salesChannel.id, + }, + }, + { + [Modules.API_KEY]: { + publishable_key_id: apiKeys[1].id, + }, + [Modules.SALES_CHANNEL]: { + sales_channel_id: salesChannel.id, + }, + }, + ]) + + const queryObject = remoteQueryObjectFromString({ + entryPoint: "api_key", + variables: { + filters: { token: apiKeys[0].token }, + }, + fields: ["id", "sales_channels.id"], + }) + const keyLinks = await remoteQuery(queryObject) + + expect(keyLinks).toHaveLength(1) + expect(keyLinks).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: apiKeys[0].id, + sales_channels: expect.arrayContaining([ + expect.objectContaining({ id: salesChannel.id }), + ]), + }), + ]) + ) + }) }) - - const apiKeys = await apiKeyModule.create([ - { - title: "Api key", - type: "publishable", - created_by: "test", - }, - { - title: "Api key 2", - type: "publishable", - created_by: "test", - }, - ]) - - await remoteLink.create([ - { - [Modules.API_KEY]: { - publishable_key_id: apiKeys[0].id, - }, - [Modules.SALES_CHANNEL]: { - sales_channel_id: salesChannel.id, - }, - }, - { - [Modules.API_KEY]: { - publishable_key_id: apiKeys[1].id, - }, - [Modules.SALES_CHANNEL]: { - sales_channel_id: salesChannel.id, - }, - }, - ]) - - const queryObject = remoteQueryObjectFromString({ - entryPoint: "api_key", - variables: { - filters: { token: apiKeys[0].token }, - }, - fields: ["id", "sales_channels.id"], - }) - const keyLinks = await remoteQuery(queryObject) - - expect(keyLinks).toHaveLength(1) - expect(keyLinks).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: apiKeys[0].id, - sales_channels: expect.arrayContaining([ - expect.objectContaining({ id: salesChannel.id }), - ]), - }), - ]) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/link-modules/region-payment-provider.spec.ts b/integration-tests/modules/__tests__/link-modules/region-payment-provider.spec.ts index 7c6b716a33..0b5be981f8 100644 --- a/integration-tests/modules/__tests__/link-modules/region-payment-provider.spec.ts +++ b/integration-tests/modules/__tests__/link-modules/region-payment-provider.spec.ts @@ -1,106 +1,92 @@ import { ModuleRegistrationName, Modules } from "@medusajs/modules-sdk" import { IPaymentModuleService, IRegionModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { getContainer } from "../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../environment-helpers/use-db" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Region and Payment Providers", () => { - let dbConnection - let appContainer - let shutdownServer - let regionModule: IRegionModuleService - let paymentModule: IPaymentModuleService - let remoteQuery - let remoteLink +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Region and Payment Providers", () => { + let appContainer + let regionModule: IRegionModuleService + let paymentModule: IPaymentModuleService + let remoteQuery + let remoteLink - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - regionModule = appContainer.resolve(ModuleRegistrationName.REGION) - paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT) - remoteQuery = appContainer.resolve("remoteQuery") - remoteLink = appContainer.resolve("remoteLink") - }) + beforeAll(async () => { + appContainer = getContainer() + regionModule = appContainer.resolve(ModuleRegistrationName.REGION) + paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT) + remoteQuery = appContainer.resolve("remoteQuery") + remoteLink = appContainer.resolve("remoteLink") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should query region and payment provider link with remote query", async () => { + const region = await regionModule.create({ + name: "North America", + currency_code: "usd", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + await remoteLink.create([ + { + [Modules.REGION]: { + region_id: region.id, + }, + [Modules.PAYMENT]: { + payment_provider_id: "pp_system_default", + }, + }, + ]) - it("should query region and payment provider link with remote query", async () => { - const region = await regionModule.create({ - name: "North America", - currency_code: "usd", - }) + const links = await remoteQuery({ + region: { + fields: ["id"], + payment_providers: { + fields: ["id"], + }, + }, + }) - await remoteLink.create([ - { - [Modules.REGION]: { - region_id: region.id, - }, - [Modules.PAYMENT]: { - payment_provider_id: "pp_system_default", - }, - }, - ]) + const otherLink = await remoteQuery({ + payment_providers: { + fields: ["id"], + regions: { + fields: ["id"], + }, + }, + }) - const links = await remoteQuery({ - region: { - fields: ["id"], - payment_providers: { - fields: ["id"], - }, - }, - }) - - const otherLink = await remoteQuery({ - payment_providers: { - fields: ["id"], - regions: { - fields: ["id"], - }, - }, - }) - - expect(links).toHaveLength(1) - expect(links).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: region.id, - payment_providers: expect.arrayContaining([ - expect.objectContaining({ - id: "pp_system_default", - }), - ]), - }), - ]) - ) - - expect(otherLink).toHaveLength(1) - expect(otherLink).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: "pp_system_default", - regions: expect.arrayContaining([ + expect(links).toHaveLength(1) + expect(links).toEqual( + expect.arrayContaining([ expect.objectContaining({ id: region.id, + payment_providers: expect.arrayContaining([ + expect.objectContaining({ + id: "pp_system_default", + }), + ]), }), - ]), - }), - ]) - ) - }) + ]) + ) + + expect(otherLink).toHaveLength(1) + expect(otherLink).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: "pp_system_default", + regions: expect.arrayContaining([ + expect.objectContaining({ + id: region.id, + }), + ]), + }), + ]) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/modules/load-standalone.ts b/integration-tests/modules/__tests__/modules/load-standalone.ts index 4f6296d1c8..6c8240c02b 100644 --- a/integration-tests/modules/__tests__/modules/load-standalone.ts +++ b/integration-tests/modules/__tests__/modules/load-standalone.ts @@ -1,29 +1,27 @@ -import dbFactory from "./../../../environment-helpers/use-template-db" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(30000) -describe("Standalone Modules", () => { - beforeAll(async () => { - const DB_HOST = process.env.DB_HOST - const DB_USERNAME = process.env.DB_USERNAME - const DB_PASSWORD = process.env.DB_PASSWORD - const DB_NAME = process.env.DB_TEMP_NAME +medusaIntegrationTestRunner({ + testSuite: ({ dbConnection }) => { + describe("Standalone Modules", () => { + beforeAll(async () => { + process.env.POSTGRES_URL = dbConnection.manager.connection.options.url + }) - process.env.POSTGRES_URL = `postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}/${DB_NAME}` - await dbFactory.createFromTemplate(DB_NAME) - }) + afterAll(async () => { + process.env.POSTGRES_URL = undefined + }) - afterAll(async () => { - process.env.POSTGRES_URL = undefined - }) + it("Should migrate database and initialize Product module using connection string from environment variable ", async function () { + const { initialize, runMigrations } = require("@medusajs/product") + await runMigrations() - it("Should migrate database and initialize Product module using connection string from environment variable ", async function () { - const { initialize, runMigrations } = require("@medusajs/product") - await runMigrations() + const product = await initialize() + const productList = await product.list() - const product = await initialize() - const productList = await product.list() - - expect(productList).toEqual(expect.arrayContaining([])) - }) + expect(productList).toEqual(expect.arrayContaining([])) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/payment/payment-session.workflows.spec.ts b/integration-tests/modules/__tests__/payment/payment-session.workflows.spec.ts index 2660280b5d..d05a8ceb9e 100644 --- a/integration-tests/modules/__tests__/payment/payment-session.workflows.spec.ts +++ b/integration-tests/modules/__tests__/payment/payment-session.workflows.spec.ts @@ -4,139 +4,126 @@ import { } from "@medusajs/core-flows" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IPaymentModuleService, IRegionModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { getContainer } from "../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../environment-helpers/use-db" +import { medusaIntegrationTestRunner } from "medusa-test-utils/dist" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Carts workflows", () => { - let dbConnection - let appContainer - let shutdownServer - let paymentModule: IPaymentModuleService - let regionModule: IRegionModuleService - let remoteLink +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Carts workflows", () => { + let appContainer + let paymentModule: IPaymentModuleService + let regionModule: IRegionModuleService + let remoteLink - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT) - regionModule = appContainer.resolve(ModuleRegistrationName.REGION) - remoteLink = appContainer.resolve("remoteLink") - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - describe("createPaymentSessionWorkflow", () => { - it("should create payment sessions", async () => { - const region = await regionModule.create({ - currency_code: "usd", - name: "US", + beforeAll(async () => { + appContainer = getContainer() + paymentModule = appContainer.resolve(ModuleRegistrationName.PAYMENT) + regionModule = appContainer.resolve(ModuleRegistrationName.REGION) + remoteLink = appContainer.resolve("remoteLink") }) - let paymentCollection = await paymentModule.createPaymentCollections({ - currency_code: "usd", - amount: 1000, - region_id: region.id, - }) + describe("createPaymentSessionWorkflow", () => { + it("should create payment sessions", async () => { + const region = await regionModule.create({ + currency_code: "usd", + name: "US", + }) - await createPaymentSessionsWorkflow(appContainer).run({ - input: { - payment_collection_id: paymentCollection.id, - provider_id: "pp_system_default", - context: {}, - data: {}, - }, - }) + let paymentCollection = await paymentModule.createPaymentCollections({ + currency_code: "usd", + amount: 1000, + region_id: region.id, + }) - paymentCollection = await paymentModule.retrievePaymentCollection( - paymentCollection.id, - { - relations: ["payment_sessions"], - } - ) - - expect(paymentCollection).toEqual( - expect.objectContaining({ - id: paymentCollection.id, - currency_code: "usd", - amount: 1000, - region_id: region.id, - payment_sessions: expect.arrayContaining([ - expect.objectContaining({ - amount: 1000, - currency_code: "usd", + await createPaymentSessionsWorkflow(appContainer).run({ + input: { + payment_collection_id: paymentCollection.id, provider_id: "pp_system_default", - }), - ]), - }) - ) - }) + context: {}, + data: {}, + }, + }) - describe("compensation", () => { - it("should delete created payment collection if a subsequent step fails", async () => { - const workflow = createPaymentSessionsWorkflow(appContainer) + paymentCollection = await paymentModule.retrievePaymentCollection( + paymentCollection.id, + { + relations: ["payment_sessions"], + } + ) - workflow.appendAction("throw", createPaymentSessionsWorkflowId, { - invoke: async function failStep() { - throw new Error( - `Failed to do something after creating payment sessions` - ) - }, + expect(paymentCollection).toEqual( + expect.objectContaining({ + id: paymentCollection.id, + currency_code: "usd", + amount: 1000, + region_id: region.id, + payment_sessions: expect.arrayContaining([ + expect.objectContaining({ + amount: 1000, + currency_code: "usd", + provider_id: "pp_system_default", + }), + ]), + }) + ) }) - const region = await regionModule.create({ - currency_code: "usd", - name: "US", + describe("compensation", () => { + it("should delete created payment collection if a subsequent step fails", async () => { + const workflow = createPaymentSessionsWorkflow(appContainer) + + workflow.appendAction("throw", createPaymentSessionsWorkflowId, { + invoke: async function failStep() { + throw new Error( + `Failed to do something after creating payment sessions` + ) + }, + }) + + const region = await regionModule.create({ + currency_code: "usd", + name: "US", + }) + + let paymentCollection = + await paymentModule.createPaymentCollections({ + currency_code: "usd", + amount: 1000, + region_id: region.id, + }) + + const { errors } = await workflow.run({ + input: { + payment_collection_id: paymentCollection.id, + provider_id: "pp_system_default", + context: {}, + data: {}, + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "throw", + handlerType: "invoke", + error: new Error( + `Failed to do something after creating payment sessions` + ), + }, + ]) + + const sessions = await paymentModule.listPaymentSessions({ + payment_collection_id: paymentCollection.id, + }) + + expect(sessions).toHaveLength(0) + }) }) - - let paymentCollection = await paymentModule.createPaymentCollections({ - currency_code: "usd", - amount: 1000, - region_id: region.id, - }) - - const { errors } = await workflow.run({ - input: { - payment_collection_id: paymentCollection.id, - provider_id: "pp_system_default", - context: {}, - data: {}, - }, - throwOnError: false, - }) - - expect(errors).toEqual([ - { - action: "throw", - handlerType: "invoke", - error: new Error( - `Failed to do something after creating payment sessions` - ), - }, - ]) - - const sessions = await paymentModule.listPaymentSessions({ - payment_collection_id: paymentCollection.id, - }) - - expect(sessions).toHaveLength(0) }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/payment/payments.spec.ts b/integration-tests/modules/__tests__/payment/payments.spec.ts index 54aa7de813..3c232d7cd1 100644 --- a/integration-tests/modules/__tests__/payment/payments.spec.ts +++ b/integration-tests/modules/__tests__/payment/payments.spec.ts @@ -1,74 +1,60 @@ import { ModuleRegistrationName, Modules } from "@medusajs/modules-sdk" import { IRegionModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" -import { getContainer } from "../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../environment-helpers/use-db" +import { medusaIntegrationTestRunner } from "medusa-test-utils/dist" jest.setTimeout(50000) const env = { MEDUSA_FF_MEDUSA_V2: true } -describe("Payments", () => { - let dbConnection - let appContainer - let shutdownServer - let regionService: IRegionModuleService - let remoteLink +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Payments", () => { + let appContainer + let regionService: IRegionModuleService + let remoteLink - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - regionService = appContainer.resolve(ModuleRegistrationName.REGION) - remoteLink = appContainer.resolve("remoteLink") - }) + beforeAll(async () => { + appContainer = getContainer() + regionService = appContainer.resolve(ModuleRegistrationName.REGION) + remoteLink = appContainer.resolve("remoteLink") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should list payment providers", async () => { + const region = await regionService.create({ + name: "Test Region", + currency_code: "usd", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + let response = await api.get( + `/store/regions/${region.id}/payment-providers` + ) - it("should list payment providers", async () => { - const region = await regionService.create({ - name: "Test Region", - currency_code: "usd", + expect(response.status).toEqual(200) + expect(response.data.payment_providers).toEqual([]) + + await remoteLink.create([ + { + [Modules.REGION]: { + region_id: region.id, + }, + [Modules.PAYMENT]: { + payment_provider_id: "pp_system_default", + }, + }, + ]) + + response = await api.get( + `/store/regions/${region.id}/payment-providers` + ) + + expect(response.status).toEqual(200) + expect(response.data.payment_providers).toEqual([ + expect.objectContaining({ + id: "pp_system_default", + }), + ]) + }) }) - - const api = useApi() as any - let response = await api.get( - `/store/regions/${region.id}/payment-providers` - ) - - expect(response.status).toEqual(200) - expect(response.data.payment_providers).toEqual([]) - - await remoteLink.create([ - { - [Modules.REGION]: { - region_id: region.id, - }, - [Modules.PAYMENT]: { - payment_provider_id: "pp_system_default", - }, - }, - ]) - - response = await api.get(`/store/regions/${region.id}/payment-providers`) - - expect(response.status).toEqual(200) - expect(response.data.payment_providers).toEqual([ - expect.objectContaining({ - id: "pp_system_default", - }), - ]) - }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts b/integration-tests/modules/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts index fa8eb5036e..a8e997b98b 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/add-price-list-price-batch.spec.ts @@ -1,6 +1,3 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory, simpleRegionFactory, @@ -11,11 +8,10 @@ import { PriceListStatus, PriceListType, } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -29,205 +25,193 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("POST /admin/price-lists/:id/prices/batch", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("POST /admin/price-lists/:id/prices/batch", () => { + let appContainer + let product + let variant + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) - - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) - - variant = product.variants[0] - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should update money amounts if variant id is present in prices", async () => { - const [priceList] = await pricingModuleService.createPriceLists([ - { - title: "test price list", - description: "test", - ends_at: new Date().toISOString(), - starts_at: new Date().toISOString(), - status: PriceListStatus.ACTIVE, - type: PriceListType.OVERRIDE, - }, - ]) - - await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - }) - - const api = useApi() as any - const data = { - prices: [ - { - variant_id: variant.id, - amount: 5000, - currency_code: "usd", - }, - { - amount: 6000, - region_id: "test-region", - variant_id: variant.id, - }, - ], - } - - await api.post( - `admin/price-lists/${priceList.id}/prices/batch`, - data, - adminHeaders - ) - - const response = await api.get( - `/admin/price-lists/${priceList.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.price_list).toEqual( - expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - name: "test price list", - description: "test", - type: "override", - status: "active", - starts_at: expect.any(String), - ends_at: expect.any(String), - customer_groups: [], - prices: [ - expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - currency_code: "usd", - amount: 5000, - min_quantity: null, - max_quantity: null, - price_list_id: expect.any(String), - region_id: null, - variant: expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - title: expect.any(String), - product_id: expect.any(String), - sku: null, - barcode: null, - ean: null, - upc: null, - variant_rank: 0, - inventory_quantity: 10, - allow_backorder: false, - manage_inventory: true, - hs_code: null, - origin_country: null, - mid_code: null, - material: null, - weight: null, - length: null, - height: null, - width: null, - metadata: null, - }), - variant_id: expect.any(String), - }), - expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - currency_code: "usd", - amount: 6000, - min_quantity: null, - max_quantity: null, - price_list_id: expect.any(String), - region_id: "test-region", - variant: expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - title: expect.any(String), - product_id: expect.any(String), - sku: null, - barcode: null, - ean: null, - upc: null, - variant_rank: 0, - inventory_quantity: 10, - allow_backorder: false, - manage_inventory: true, - hs_code: null, - origin_country: null, - mid_code: null, - material: null, - weight: null, - length: null, - height: null, - width: null, - metadata: null, - }), - variant_id: expect.any(String), - }), - ], + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") }) - ) - }) + + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + it("should update money amounts if variant id is present in prices", async () => { + const [priceList] = await pricingModuleService.createPriceLists([ + { + title: "test price list", + description: "test", + ends_at: new Date().toISOString(), + starts_at: new Date().toISOString(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + }, + ]) + + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + const data = { + prices: [ + { + variant_id: variant.id, + amount: 5000, + currency_code: "usd", + }, + { + amount: 6000, + region_id: "test-region", + variant_id: variant.id, + }, + ], + } + + await api.post( + `admin/price-lists/${priceList.id}/prices/batch`, + data, + adminHeaders + ) + + const response = await api.get( + `/admin/price-lists/${priceList.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "test price list", + description: "test", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: expect.any(String), + customer_groups: [], + prices: [ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 5000, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: null, + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 6000, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: "test-region", + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + ], + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/create-price-list.spec.ts b/integration-tests/modules/__tests__/price-lists/admin/create-price-list.spec.ts index cb3c909f25..c1d88bf363 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/create-price-list.spec.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/create-price-list.spec.ts @@ -1,6 +1,3 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleCustomerGroupFactory, simpleProductFactory, @@ -8,11 +5,10 @@ import { } from "../../../../factories" import { IPricingModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -26,166 +22,154 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("POST /admin/price-lists", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("POST /admin/price-lists", () => { + let appContainer + let product + let variant + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + await simpleCustomerGroupFactory(dbConnection, { + id: "customer-group-1", + name: "Test Group", + }) - beforeEach(async () => { - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - await simpleCustomerGroupFactory(dbConnection, { - id: "customer-group-1", - name: "Test Group", - }) - - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) - - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) - - variant = product.variants[0] - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should create price list and money amounts", async () => { - await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", currency_code: "usd", - }, - ], - }) + tax_rate: 0, + }) - const api = useApi() as any - const data = { - name: "test price list", - description: "test", - type: "override", - customer_groups: [{ id: "customer-group-1" }], - status: "active", - starts_at: new Date(), - prices: [ - { - amount: 400, - variant_id: variant.id, - currency_code: "usd", - }, - ], - } + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) - const result = await api.post(`admin/price-lists`, data, adminHeaders) + variant = product.variants[0] + }) - let response = await api.get( - `/admin/price-lists/${result.data.price_list.id}`, - adminHeaders - ) + it("should create price list and money amounts", async () => { + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) - expect(response.status).toEqual(200) - expect(response.data.price_list).toEqual( - expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - name: "test price list", - description: "test", - type: "override", - status: "active", - starts_at: expect.any(String), - ends_at: null, - customer_groups: [ - { - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - name: "Test Group", - metadata: null, - }, - ], - prices: [ + const data = { + name: "test price list", + description: "test", + type: "override", + customer_groups: [{ id: "customer-group-1" }], + status: "active", + starts_at: new Date(), + prices: [ + { + amount: 400, + variant_id: variant.id, + currency_code: "usd", + }, + ], + } + + const result = await api.post(`admin/price-lists`, data, adminHeaders) + + let response = await api.get( + `/admin/price-lists/${result.data.price_list.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( expect.objectContaining({ id: expect.any(String), created_at: expect.any(String), updated_at: expect.any(String), deleted_at: null, - currency_code: "usd", - amount: 400, - min_quantity: null, - max_quantity: null, - price_list_id: expect.any(String), - region_id: null, - variant: expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - title: expect.any(String), - product_id: expect.any(String), - sku: null, - barcode: null, - ean: null, - upc: null, - variant_rank: 0, - inventory_quantity: 10, - allow_backorder: false, - manage_inventory: true, - hs_code: null, - origin_country: null, - mid_code: null, - material: null, - weight: null, - length: null, - height: null, - width: null, - metadata: null, - }), - variant_id: expect.any(String), - }), - ], + name: "test price list", + description: "test", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: null, + customer_groups: [ + { + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "Test Group", + metadata: null, + }, + ], + prices: [ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 400, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: null, + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + ], + }) + ) }) - ) - }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts b/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts index ecf6e4ec36..39f1841ef3 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices-by-product.ts @@ -1,18 +1,13 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory, simpleRegionFactory, } from "../../../../factories" import { IPricingModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" -import { AxiosInstance } from "axios" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -26,155 +21,140 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("DELETE /admin/price-lists/:id/products/:productId/batch", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant1 - let priceSet - let priceListId - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("DELETE /admin/price-lists/:id/products/:productId/batch", () => { + let appContainer + let product + let variant1 + let priceSet + let priceListId + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - const api = useApi()! as AxiosInstance - - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) - - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) - - variant1 = product.variants[0] - - priceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant1.id, - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - }) - - const data = { - name: "test price list", - description: "test", - type: "override", - customer_groups: [], - status: "active", - prices: [ - { - amount: 400, - variant_id: variant1.id, - currency_code: "usd", - }, - ], - } - - const priceListResult = await api.post( - `admin/price-lists`, - data, - adminHeaders - ) - priceListId = priceListResult.data.price_list.id - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should delete prices in batch based on product ids", async () => { - const api = useApi()! as AxiosInstance - - let priceSetMoneyAmounts = - await pricingModuleService.listPriceSetMoneyAmounts({ - price_set_id: [priceSet.id], + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") }) - expect(priceSetMoneyAmounts.length).toEqual(2) - const deleteRes = await api.delete( - `/admin/price-lists/${priceListId}/products/prices/batch`, - { - headers: adminHeaders.headers, - data: { - product_ids: [product.id], - }, - } - ) - expect(deleteRes.status).toEqual(200) + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) - priceSetMoneyAmounts = await pricingModuleService.listPriceSetMoneyAmounts({ - price_set_id: [priceSet.id], - }) + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) - expect(priceSetMoneyAmounts.length).toEqual(1) - expect(priceSetMoneyAmounts).toEqual([ - expect.objectContaining({ - price_list: null, - }), - ]) - }) + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) - it("should delete prices based on single product id", async () => { - const api = useApi()! as AxiosInstance + variant1 = product.variants[0] - let priceSetMoneyAmounts = - await pricingModuleService.listPriceSetMoneyAmounts({ - price_set_id: [priceSet.id], + priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant1.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + const data = { + name: "test price list", + description: "test", + type: "override", + customer_groups: [], + status: "active", + prices: [ + { + amount: 400, + variant_id: variant1.id, + currency_code: "usd", + }, + ], + } + + const priceListResult = await api.post( + `admin/price-lists`, + data, + adminHeaders + ) + priceListId = priceListResult.data.price_list.id }) - expect(priceSetMoneyAmounts.length).toEqual(2) - const deleteRes = await api.delete( - `/admin/price-lists/${priceListId}/products/${product.id}/prices`, - adminHeaders - ) - expect(deleteRes.status).toEqual(200) + it("should delete prices in batch based on product ids", async () => { + let priceSetMoneyAmounts = + await pricingModuleService.listPriceSetMoneyAmounts({ + price_set_id: [priceSet.id], + }) + expect(priceSetMoneyAmounts.length).toEqual(2) - priceSetMoneyAmounts = await pricingModuleService.listPriceSetMoneyAmounts({ - price_set_id: [priceSet.id], + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}/products/prices/batch`, + { + headers: adminHeaders.headers, + data: { + product_ids: [product.id], + }, + } + ) + expect(deleteRes.status).toEqual(200) + + priceSetMoneyAmounts = + await pricingModuleService.listPriceSetMoneyAmounts({ + price_set_id: [priceSet.id], + }) + + expect(priceSetMoneyAmounts.length).toEqual(1) + expect(priceSetMoneyAmounts).toEqual([ + expect.objectContaining({ + price_list: null, + }), + ]) + }) + + it("should delete prices based on single product id", async () => { + let priceSetMoneyAmounts = + await pricingModuleService.listPriceSetMoneyAmounts({ + price_set_id: [priceSet.id], + }) + expect(priceSetMoneyAmounts.length).toEqual(2) + + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}/products/${product.id}/prices`, + adminHeaders + ) + expect(deleteRes.status).toEqual(200) + + priceSetMoneyAmounts = + await pricingModuleService.listPriceSetMoneyAmounts({ + price_set_id: [priceSet.id], + }) + + expect(priceSetMoneyAmounts.length).toEqual(1) + expect(priceSetMoneyAmounts).toEqual([ + expect.objectContaining({ + price_list: null, + }), + ]) + }) }) - - expect(priceSetMoneyAmounts.length).toEqual(1) - expect(priceSetMoneyAmounts).toEqual([ - expect.objectContaining({ - price_list: null, - }), - ]) - }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts b/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts index ad30e08a0b..4aa578ac24 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices-by-variant.ts @@ -1,17 +1,13 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory, simpleRegionFactory, } from "../../../../factories" import { IPricingModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -25,107 +21,95 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("DELETE /admin/price-lists/:id/variants/:variantId/prices", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("DELETE /admin/price-lists/:id/variants/:variantId/prices", () => { + let appContainer + let product + let variant + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) - beforeEach(async () => { - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) - - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) - - variant = product.variants[0] - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should delete all prices based on product variant ids", async () => { - const priceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", currency_code: "usd", - }, - ], + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + it("should delete all prices based on product variant ids", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + const data = { + name: "test price list", + description: "test", + type: "override", + customer_groups: [], + status: "active", + prices: [ + { + amount: 400, + variant_id: variant.id, + currency_code: "usd", + }, + ], + } + + const result = await api.post(`admin/price-lists`, data, adminHeaders) + const priceListId = result.data.price_list.id + + let psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(1) + + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}/variants/${variant.id}/prices`, + adminHeaders + ) + expect(deleteRes.status).toEqual(200) + + psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(0) + }) }) - - const api = useApi() as any - const data = { - name: "test price list", - description: "test", - type: "override", - customer_groups: [], - status: "active", - prices: [ - { - amount: 400, - variant_id: variant.id, - currency_code: "usd", - }, - ], - } - - const result = await api.post(`admin/price-lists`, data, adminHeaders) - const priceListId = result.data.price_list.id - - let psmas = await pricingModuleService.listPriceSetMoneyAmounts({ - price_list_id: [priceListId], - }) - expect(psmas.length).toEqual(1) - - const deleteRes = await api.delete( - `/admin/price-lists/${priceListId}/variants/${variant.id}/prices`, - adminHeaders - ) - expect(deleteRes.status).toEqual(200) - - psmas = await pricingModuleService.listPriceSetMoneyAmounts({ - price_list_id: [priceListId], - }) - expect(psmas.length).toEqual(0) - }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices.ts b/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices.ts index af0b6dd078..c7ca96b706 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-prices.ts @@ -1,17 +1,13 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory, simpleRegionFactory, } from "../../../../factories" import { IPricingModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -25,121 +21,109 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("DELETE /admin/price-lists/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("DELETE /admin/price-lists/:id", () => { + let appContainer + let product + let variant + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) - beforeEach(async () => { - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) - - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) - - variant = product.variants[0] - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should delete price list prices by money amount ids", async () => { - await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", currency_code: "usd", - }, - ], + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + it("should delete price list prices by money amount ids", async () => { + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + const data = { + name: "test price list", + description: "test", + type: "override", + status: "active", + prices: [ + { + amount: 400, + variant_id: variant.id, + currency_code: "usd", + }, + { + amount: 4000, + variant_id: variant.id, + currency_code: "usd", + }, + ], + } + + const res = await api.post(`admin/price-lists`, data, adminHeaders) + + const priceListId = res.data.price_list.id + let psmas = await pricingModuleService.listPriceSetMoneyAmounts( + { + price_list_id: [priceListId], + }, + { relations: ["money_amount"] } + ) + + expect(psmas.length).toEqual(2) + + const deletePrice = psmas[0].money_amount + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}/prices/batch`, + { + data: { + price_ids: [deletePrice?.id], + }, + ...adminHeaders, + } + ) + expect(deleteRes.status).toEqual(200) + + psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(1) + }) }) - - const api = useApi() as any - const data = { - name: "test price list", - description: "test", - type: "override", - status: "active", - prices: [ - { - amount: 400, - variant_id: variant.id, - currency_code: "usd", - }, - { - amount: 4000, - variant_id: variant.id, - currency_code: "usd", - }, - ], - } - - const res = await api.post(`admin/price-lists`, data, adminHeaders) - - const priceListId = res.data.price_list.id - let psmas = await pricingModuleService.listPriceSetMoneyAmounts( - { - price_list_id: [priceListId], - }, - { relations: ["money_amount"] } - ) - - expect(psmas.length).toEqual(2) - - const deletePrice = psmas[0].money_amount - const deleteRes = await api.delete( - `/admin/price-lists/${priceListId}/prices/batch`, - { - data: { - price_ids: [deletePrice?.id], - }, - ...adminHeaders, - } - ) - expect(deleteRes.status).toEqual(200) - - psmas = await pricingModuleService.listPriceSetMoneyAmounts({ - price_list_id: [priceListId], - }) - expect(psmas.length).toEqual(1) - }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-spec.ts b/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-spec.ts index 2102356c88..b7a7a01325 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-spec.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/delete-price-list-spec.ts @@ -1,17 +1,13 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory, simpleRegionFactory, } from "../../../../factories" import { IPricingModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -25,120 +21,108 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("DELETE /admin/price-lists/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("DELETE /admin/price-lists/:id", () => { + let appContainer + let product + let variant + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) - - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) - - variant = product.variants[0] - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should delete price list and money amounts", async () => { - const priceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - }) - - const api = useApi() as any - const data = { - name: "test price list", - description: "test", - type: "override", - customer_groups: [], - status: "active", - prices: [ - { - amount: 400, - variant_id: variant.id, - currency_code: "usd", - }, - ], - } - - const result = await api.post(`admin/price-lists`, data, adminHeaders) - const priceListId = result.data.price_list.id - - const getResponse = await api.get( - `/admin/price-lists/${priceListId}`, - adminHeaders - ) - expect(getResponse.status).toEqual(200) - - let psmas = await pricingModuleService.listPriceSetMoneyAmounts({ - price_list_id: [priceListId], - }) - expect(psmas.length).toEqual(1) - - const deleteRes = await api.delete( - `/admin/price-lists/${priceListId}`, - adminHeaders - ) - expect(deleteRes.status).toEqual(200) - - const afterDelete = await api - .get(`/admin/price-lists/${priceListId}`, adminHeaders) - .catch((err) => { - return err + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") }) - expect(afterDelete.response.status).toEqual(404) - psmas = await pricingModuleService.listPriceSetMoneyAmounts({ - price_list_id: [priceListId], + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) + + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) + + variant = product.variants[0] + }) + + it("should delete price list and money amounts", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + const data = { + name: "test price list", + description: "test", + type: "override", + customer_groups: [], + status: "active", + prices: [ + { + amount: 400, + variant_id: variant.id, + currency_code: "usd", + }, + ], + } + + const result = await api.post(`admin/price-lists`, data, adminHeaders) + const priceListId = result.data.price_list.id + + const getResponse = await api.get( + `/admin/price-lists/${priceListId}`, + adminHeaders + ) + expect(getResponse.status).toEqual(200) + + let psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(1) + + const deleteRes = await api.delete( + `/admin/price-lists/${priceListId}`, + adminHeaders + ) + expect(deleteRes.status).toEqual(200) + + const afterDelete = await api + .get(`/admin/price-lists/${priceListId}`, adminHeaders) + .catch((err) => { + return err + }) + expect(afterDelete.response.status).toEqual(404) + + psmas = await pricingModuleService.listPriceSetMoneyAmounts({ + price_list_id: [priceListId], + }) + expect(psmas.length).toEqual(0) + }) }) - expect(psmas.length).toEqual(0) - }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/get-price-list.spec.ts b/integration-tests/modules/__tests__/price-lists/admin/get-price-list.spec.ts index 7aa9bfdbef..664ba69a3a 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/get-price-list.spec.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/get-price-list.spec.ts @@ -1,6 +1,3 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory } from "../../../../factories" import { @@ -8,10 +5,9 @@ import { PriceListStatus, PriceListType, } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -25,179 +21,164 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("GET /admin/price-lists/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("GET /admin/price-lists/:id", () => { + let appContainer + let product + let variant + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) - beforeEach(async () => { - await adminSeeder(dbConnection) + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) + variant = product.variants[0] + }) - variant = product.variants[0] - }) + it("should get price list and its money amounts with variants", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + rules: [], + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should get price list and its money amounts with variants", async () => { - const priceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - rules: [], - }) - - const [priceList] = await pricingModuleService.createPriceLists([ - { - title: "test price list", - description: "test", - ends_at: new Date(), - starts_at: new Date(), - status: PriceListStatus.ACTIVE, - type: PriceListType.OVERRIDE, - prices: [ + const [priceList] = await pricingModuleService.createPriceLists([ { - amount: 5000, - currency_code: "usd", - price_set_id: priceSet.id, + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], }, - ], - }, - ]) + ]) - await pricingModuleService.createPriceLists([ - { - title: "test price list 1", - description: "test 1", - ends_at: new Date(), - starts_at: new Date(), - status: PriceListStatus.ACTIVE, - type: PriceListType.OVERRIDE, - prices: [ + await pricingModuleService.createPriceLists([ { - amount: 5000, - currency_code: "usd", - price_set_id: priceSet.id, + title: "test price list 1", + description: "test 1", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], }, - ], - }, - ]) + ]) - const api = useApi() as any + const response = await api.get( + `/admin/price-lists/${priceList.id}`, + adminHeaders + ) - const response = await api.get( - `/admin/price-lists/${priceList.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.price_list).toEqual( - expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - name: "test price list", - description: "test", - type: "override", - status: "active", - starts_at: expect.any(String), - ends_at: expect.any(String), - customer_groups: [], - prices: [ + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( expect.objectContaining({ id: expect.any(String), created_at: expect.any(String), updated_at: expect.any(String), deleted_at: null, - currency_code: "usd", - amount: 5000, - min_quantity: null, - max_quantity: null, - price_list_id: expect.any(String), - region_id: null, - variant: expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - title: expect.any(String), - product_id: expect.any(String), - sku: null, - barcode: null, - ean: null, - upc: null, - variant_rank: 0, - inventory_quantity: 10, - allow_backorder: false, - manage_inventory: true, - hs_code: null, - origin_country: null, - mid_code: null, - material: null, - weight: null, - length: null, - height: null, - width: null, - metadata: null, - }), - variant_id: expect.any(String), - }), - ], + name: "test price list", + description: "test", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: expect.any(String), + customer_groups: [], + prices: [ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 5000, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: null, + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + ], + }) + ) }) - ) - }) - it("should throw an error when price list is not found", async () => { - const api = useApi() as any + it("should throw an error when price list is not found", async () => { + const error = await api + .get(`/admin/price-lists/does-not-exist`, adminHeaders) + .catch((e) => e) - const error = await api - .get(`/admin/price-lists/does-not-exist`, adminHeaders) - .catch((e) => e) - - expect(error.response.status).toBe(404) - expect(error.response.data).toEqual({ - type: "not_found", - message: "Price list with id: does-not-exist was not found", + expect(error.response.status).toBe(404) + expect(error.response.data).toEqual({ + type: "not_found", + message: "Price list with id: does-not-exist was not found", + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/list-price-list-products.spec.ts b/integration-tests/modules/__tests__/price-lists/admin/list-price-list-products.spec.ts index fd77843273..6826bda6fe 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/list-price-list-products.spec.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/list-price-list-products.spec.ts @@ -1,6 +1,3 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory } from "../../../../factories" import { @@ -8,10 +5,9 @@ import { PriceListStatus, PriceListType, } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -25,248 +21,235 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("GET /admin/price-lists/:id/products", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let product2 - let variant - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("GET /admin/price-lists/:id/products", () => { + let appContainer + let product + let product2 + let variant + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) - beforeEach(async () => { - await adminSeeder(dbConnection) + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + title: "uniquely fun product", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - title: "uniquely fun product", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) + variant = product.variants[0] - variant = product.variants[0] + product2 = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant-2", + title: "uniquely fun product 2", + variants: [ + { + options: [ + { option_id: "test-product-option-2", value: "test 2" }, + ], + }, + ], + options: [ + { + id: "test-product-option-2", + title: "Test option 2", + }, + ], + }) + }) - product2 = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant-2", - title: "uniquely fun product 2", - variants: [ - { - options: [{ option_id: "test-product-option-2", value: "test 2" }], - }, - ], - options: [ - { - id: "test-product-option-2", - title: "Test option 2", - }, - ], - }) - }) + it("should list all products in a price list", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + rules: [], + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should list all products in a price list", async () => { - const priceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - rules: [], - }) - - const [priceList] = await pricingModuleService.createPriceLists([ - { - title: "test price list", - description: "test", - ends_at: new Date(), - starts_at: new Date(), - status: PriceListStatus.ACTIVE, - type: PriceListType.OVERRIDE, - prices: [ + const [priceList] = await pricingModuleService.createPriceLists([ { - amount: 5000, - currency_code: "usd", - price_set_id: priceSet.id, + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], }, - ], - }, - ]) + ]) - const api = useApi() as any + let response = await api.get( + `/admin/price-lists/${priceList.id}/products`, + adminHeaders + ) - let response = await api.get( - `/admin/price-lists/${priceList.id}/products`, - adminHeaders - ) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.products).toEqual([ + expect.objectContaining({ + id: expect.any(String), + title: expect.any(String), + handle: expect.any(String), + subtitle: null, + description: null, + is_giftcard: false, + status: "draft", + thumbnail: null, + weight: null, + length: null, + height: null, + width: null, + origin_country: null, + hs_code: null, + mid_code: null, + material: null, + collection_id: null, + collection: null, + type_id: null, + type: null, + discountable: true, + external_id: null, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + metadata: null, + }), + ]) - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.products).toEqual([ - expect.objectContaining({ - id: expect.any(String), - title: expect.any(String), - handle: expect.any(String), - subtitle: null, - description: null, - is_giftcard: false, - status: "draft", - thumbnail: null, - weight: null, - length: null, - height: null, - width: null, - origin_country: null, - hs_code: null, - mid_code: null, - material: null, - collection_id: null, - collection: null, - type_id: null, - type: null, - discountable: true, - external_id: null, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - metadata: null, - }), - ]) + response = await api.get( + `/admin/products?price_list_id[]=${priceList.id}`, + adminHeaders + ) - response = await api.get( - `/admin/products?price_list_id[]=${priceList.id}`, - adminHeaders - ) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.products).toEqual([ + expect.objectContaining({ + id: expect.any(String), + title: expect.any(String), + handle: expect.any(String), + subtitle: null, + description: null, + is_giftcard: false, + status: "draft", + thumbnail: null, + weight: null, + length: null, + height: null, + width: null, + origin_country: null, + hs_code: null, + mid_code: null, + material: null, + collection_id: null, + collection: null, + type_id: null, + type: null, + discountable: true, + external_id: null, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + metadata: null, + }), + ]) + }) - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.products).toEqual([ - expect.objectContaining({ - id: expect.any(String), - title: expect.any(String), - handle: expect.any(String), - subtitle: null, - description: null, - is_giftcard: false, - status: "draft", - thumbnail: null, - weight: null, - length: null, - height: null, - width: null, - origin_country: null, - hs_code: null, - mid_code: null, - material: null, - collection_id: null, - collection: null, - type_id: null, - type: null, - discountable: true, - external_id: null, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - metadata: null, - }), - ]) - }) + it("should list all products constrained by search query in a price list", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + rules: [], + }) - it("should list all products constrained by search query in a price list", async () => { - const priceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - rules: [], - }) - - const [priceList] = await pricingModuleService.createPriceLists([ - { - title: "test price list", - description: "test", - ends_at: new Date(), - starts_at: new Date(), - status: PriceListStatus.ACTIVE, - type: PriceListType.OVERRIDE, - prices: [ + const [priceList] = await pricingModuleService.createPriceLists([ { - amount: 5000, - currency_code: "usd", - price_set_id: priceSet.id, + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], }, - ], - }, - ]) + ]) - const api = useApi() as any + let response = await api.get( + `/admin/price-lists/${priceList.id}/products?q=shouldnotreturnanything`, + adminHeaders + ) - let response = await api.get( - `/admin/price-lists/${priceList.id}/products?q=shouldnotreturnanything`, - adminHeaders - ) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(0) + expect(response.data.products).toEqual([]) - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(0) - expect(response.data.products).toEqual([]) + response = await api.get( + `/admin/price-lists/${priceList.id}/products?q=uniquely`, + adminHeaders + ) - response = await api.get( - `/admin/price-lists/${priceList.id}/products?q=uniquely`, - adminHeaders - ) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.products).toEqual([ + expect.objectContaining({ + id: expect.any(String), + }), + ]) - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.products).toEqual([ - expect.objectContaining({ - id: expect.any(String), - }), - ]) + response = await api.get( + `/admin/price-lists/${priceList.id}/products?q=`, + adminHeaders + ) - response = await api.get( - `/admin/price-lists/${priceList.id}/products?q=`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.products).toEqual([ - expect.objectContaining({ - id: expect.any(String), - }), - ]) - }) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.products).toEqual([ + expect.objectContaining({ + id: expect.any(String), + }), + ]) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/list-price-list.spec.ts b/integration-tests/modules/__tests__/price-lists/admin/list-price-list.spec.ts index e3662864ad..1bc09f203e 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/list-price-list.spec.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/list-price-list.spec.ts @@ -1,6 +1,3 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory } from "../../../../factories" import { @@ -8,10 +5,9 @@ import { PriceListStatus, PriceListType, } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -25,145 +21,132 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("GET /admin/price-lists", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("GET /admin/price-lists", () => { + let appContainer + let product + let variant + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) - beforeEach(async () => { - await adminSeeder(dbConnection) + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) + variant = product.variants[0] + }) - variant = product.variants[0] - }) + it("should get price list and its money amounts with variants", async () => { + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + rules: [], + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should get price list and its money amounts with variants", async () => { - const priceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - rules: [], - }) - - const [priceList] = await pricingModuleService.createPriceLists([ - { - title: "test price list", - description: "test", - ends_at: new Date(), - starts_at: new Date(), - status: PriceListStatus.ACTIVE, - type: PriceListType.OVERRIDE, - prices: [ + const [priceList] = await pricingModuleService.createPriceLists([ { - amount: 5000, - currency_code: "usd", - price_set_id: priceSet.id, + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 5000, + currency_code: "usd", + price_set_id: priceSet.id, + }, + ], }, - ], - }, - ]) + ]) - const api = useApi() as any + const response = await api.get(`/admin/price-lists`, adminHeaders) - const response = await api.get(`/admin/price-lists`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.price_lists).toEqual([ - expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - name: "test price list", - description: "test", - type: "override", - status: "active", - starts_at: expect.any(String), - ends_at: expect.any(String), - customer_groups: [], - prices: [ + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.price_lists).toEqual([ expect.objectContaining({ id: expect.any(String), created_at: expect.any(String), updated_at: expect.any(String), deleted_at: null, - currency_code: "usd", - amount: 5000, - min_quantity: null, - max_quantity: null, - price_list_id: expect.any(String), - region_id: null, - variant: expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - title: expect.any(String), - product_id: expect.any(String), - sku: null, - barcode: null, - ean: null, - upc: null, - variant_rank: 0, - inventory_quantity: 10, - allow_backorder: false, - manage_inventory: true, - hs_code: null, - origin_country: null, - mid_code: null, - material: null, - weight: null, - length: null, - height: null, - width: null, - metadata: null, - }), - variant_id: expect.any(String), + name: "test price list", + description: "test", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: expect.any(String), + customer_groups: [], + prices: [ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 5000, + min_quantity: null, + max_quantity: null, + price_list_id: expect.any(String), + region_id: null, + variant: expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + title: expect.any(String), + product_id: expect.any(String), + sku: null, + barcode: null, + ean: null, + upc: null, + variant_rank: 0, + inventory_quantity: 10, + allow_backorder: false, + manage_inventory: true, + hs_code: null, + origin_country: null, + mid_code: null, + material: null, + weight: null, + length: null, + height: null, + width: null, + metadata: null, + }), + variant_id: expect.any(String), + }), + ], }), - ], - }), - ]) - }) + ]) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/admin/update-price-list.spec.ts b/integration-tests/modules/__tests__/price-lists/admin/update-price-list.spec.ts index 9e9461ee5f..aa02cc7796 100644 --- a/integration-tests/modules/__tests__/price-lists/admin/update-price-list.spec.ts +++ b/integration-tests/modules/__tests__/price-lists/admin/update-price-list.spec.ts @@ -1,6 +1,3 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleCustomerGroupFactory, simpleProductFactory, @@ -12,11 +9,10 @@ import { PriceListStatus, PriceListType, } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -30,251 +26,240 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("POST /admin/price-lists/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let variant2 - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("POST /admin/price-lists/:id", () => { + let appContainer + let product + let variant + let variant2 + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) + await simpleCustomerGroupFactory(dbConnection, { + id: "customer-group-2", + name: "Test Group 2", + }) - beforeEach(async () => { - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - await simpleCustomerGroupFactory(dbConnection, { - id: "customer-group-2", - name: "Test Group 2", - }) + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", + currency_code: "usd", + tax_rate: 0, + }) - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + { + options: [ + { option_id: "test-product-option-2", value: "test 2" }, + ], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + { + id: "test-product-option-2", + title: "Test option 2", + }, + ], + }) - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - { - options: [{ option_id: "test-product-option-2", value: "test 2" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - { - id: "test-product-option-2", - title: "Test option 2", - }, - ], - }) + variant = product.variants[0] + variant2 = product.variants[1] + }) - variant = product.variants[0] - variant2 = product.variants[1] - }) + it("should update price lists successfully with prices", async () => { + const var2PriceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant2.id, + prices: [], + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should update price lists successfully with prices", async () => { - const var2PriceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant2.id, - prices: [], - }) - - const [priceList] = await pricingModuleService.createPriceLists([ - { - title: "test price list", - description: "test", - ends_at: new Date(), - starts_at: new Date(), - status: PriceListStatus.ACTIVE, - type: PriceListType.OVERRIDE, - prices: [ + const [priceList] = await pricingModuleService.createPriceLists([ { - amount: 3000, - currency_code: "usd", - price_set_id: var2PriceSet.id, + title: "test price list", + description: "test", + ends_at: new Date(), + starts_at: new Date(), + status: PriceListStatus.ACTIVE, + type: PriceListType.OVERRIDE, + prices: [ + { + amount: 3000, + currency_code: "usd", + price_set_id: var2PriceSet.id, + }, + ], }, - ], - }, - ]) + ]) - await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, - currency_code: "usd", - }, - ], - }) + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) - const api = useApi() as any - const data = { - name: "new price list name", - description: "new price list description", - customer_groups: [{ id: "customer-group-2" }], - prices: [ - { - variant_id: variant.id, - amount: 5000, - currency_code: "usd", - }, - { - id: priceList?.price_set_money_amounts?.[0].money_amount?.id, - amount: 6000, - currency_code: "usd", - variant_id: variant2.id, - }, - ], - } + const data = { + name: "new price list name", + description: "new price list description", + customer_groups: [{ id: "customer-group-2" }], + prices: [ + { + variant_id: variant.id, + amount: 5000, + currency_code: "usd", + }, + { + id: priceList?.price_set_money_amounts?.[0].money_amount?.id, + amount: 6000, + currency_code: "usd", + variant_id: variant2.id, + }, + ], + } - await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders) + await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders) - const response = await api.get( - `/admin/price-lists/${priceList.id}`, - adminHeaders - ) + const response = await api.get( + `/admin/price-lists/${priceList.id}`, + adminHeaders + ) - expect(response.status).toEqual(200) - expect(response.data.price_list).toEqual( - expect.objectContaining({ - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - name: "new price list name", - description: "new price list description", - type: "override", - status: "active", - starts_at: expect.any(String), - ends_at: expect.any(String), - customer_groups: [ - { - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - name: "Test Group 2", - metadata: null, - }, - ], - prices: expect.arrayContaining([ + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( expect.objectContaining({ id: expect.any(String), created_at: expect.any(String), updated_at: expect.any(String), deleted_at: null, - currency_code: "usd", - amount: 5000, - min_quantity: null, - max_quantity: null, - price_list_id: priceList.id, - region_id: null, - variant: expect.objectContaining({ - id: variant.id, - }), - variant_id: variant.id, - }), + name: "new price list name", + description: "new price list description", + type: "override", + status: "active", + starts_at: expect.any(String), + ends_at: expect.any(String), + customer_groups: [ + { + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "Test Group 2", + metadata: null, + }, + ], + prices: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 5000, + min_quantity: null, + max_quantity: null, + price_list_id: priceList.id, + region_id: null, + variant: expect.objectContaining({ + id: variant.id, + }), + variant_id: variant.id, + }), + expect.objectContaining({ + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + currency_code: "usd", + amount: 6000, + min_quantity: null, + max_quantity: null, + price_list_id: priceList.id, + region_id: null, + variant: expect.objectContaining({ + id: variant2.id, + }), + variant_id: variant2.id, + }), + ]), + }) + ) + }) + + it("should not delete customer groups if customer_groups is not passed as a param", async () => { + await createVariantPriceSet({ + container: appContainer, + variantId: variant2.id, + prices: [], + }) + + const [priceList] = await pricingModuleService.createPriceLists([ + { + title: "test price list", + description: "test", + status: PriceListStatus.DRAFT, + rules: { + customer_group_id: ["customer-group-2"], + }, + prices: [], + }, + ]) + + await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [], + }) + + const data = { + status: PriceListStatus.ACTIVE, + } + + await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders) + + const response = await api.get( + `/admin/price-lists/${priceList.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.price_list).toEqual( expect.objectContaining({ id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - currency_code: "usd", - amount: 6000, - min_quantity: null, - max_quantity: null, - price_list_id: priceList.id, - region_id: null, - variant: expect.objectContaining({ - id: variant2.id, - }), - variant_id: variant2.id, - }), - ]), + customer_groups: [ + { + id: expect.any(String), + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + name: "Test Group 2", + metadata: null, + }, + ], + }) + ) }) - ) - }) - - it("should not delete customer groups if customer_groups is not passed as a param", async () => { - await createVariantPriceSet({ - container: appContainer, - variantId: variant2.id, - prices: [], }) - - const [priceList] = await pricingModuleService.createPriceLists([ - { - title: "test price list", - description: "test", - status: PriceListStatus.DRAFT, - rules: { - customer_group_id: ["customer-group-2"], - }, - prices: [], - }, - ]) - - await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [], - }) - - const api = useApi() as any - const data = { - status: PriceListStatus.ACTIVE, - } - - await api.post(`admin/price-lists/${priceList.id}`, data, adminHeaders) - - const response = await api.get( - `/admin/price-lists/${priceList.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.price_list).toEqual( - expect.objectContaining({ - id: expect.any(String), - customer_groups: [ - { - id: expect.any(String), - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - name: "Test Group 2", - metadata: null, - }, - ], - }) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/price-lists/store/get-product.ts b/integration-tests/modules/__tests__/price-lists/store/get-product.ts index 402b82ae18..c20dbc589b 100644 --- a/integration-tests/modules/__tests__/price-lists/store/get-product.ts +++ b/integration-tests/modules/__tests__/price-lists/store/get-product.ts @@ -1,6 +1,3 @@ -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleCustomerFactory, simpleCustomerGroupFactory, @@ -13,12 +10,10 @@ import { PriceListStatus, PriceListType, } from "@medusajs/types" -import { AxiosInstance } from "axios" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -32,256 +27,239 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("GET /store/products/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant - let priceSetId - let pricingModuleService: IPricingModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("GET /store/products/:id", () => { + let appContainer + let product + let variant + let priceSetId + let pricingModuleService: IPricingModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - pricingModuleService = appContainer.resolve("pricingModuleService") - }) + beforeAll(async () => { + appContainer = getContainer() + pricingModuleService = appContainer.resolve("pricingModuleService") + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) - beforeEach(async () => { - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) - - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - status: "published", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) - - variant = product.variants[0] - - const priceSet = await createVariantPriceSet({ - container: appContainer, - variantId: variant.id, - prices: [ - { - amount: 3000, + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", currency_code: "usd", - }, - { - amount: 4000, - currency_code: "usd", - }, - ], - rules: [], - }) + tax_rate: 0, + }) - priceSetId = priceSet.id - }) + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + status: "published", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + variant = product.variants[0] - it("should get product and its prices from price-list created through the price list workflow", async () => { - const api = useApi()! as AxiosInstance + const priceSet = await createVariantPriceSet({ + container: appContainer, + variantId: variant.id, + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + { + amount: 4000, + currency_code: "usd", + }, + ], + rules: [], + }) - const priceListResponse = await api.post( - `/admin/price-lists`, - { - name: "test price list", - description: "test", - status: PriceListStatus.ACTIVE, - type: PriceListType.SALE, - prices: [ - { - amount: 2500, - currency_code: "usd", - variant_id: variant.id, - }, - ], - }, - adminHeaders - ) - - let response = await api.get( - `/store/products/${product.id}?currency_code=usd` - ) - - expect(response.status).toEqual(200) - expect(response.data.product.variants[0].prices).toHaveLength(2) - expect(response.data.product.variants[0].prices).toEqual([ - expect.objectContaining({ - currency_code: "usd", - amount: 3000, - min_quantity: null, - max_quantity: null, - price_list_id: null, - }), - expect.objectContaining({ - currency_code: "usd", - amount: 2500, - min_quantity: null, - max_quantity: null, - price_list_id: priceListResponse.data.price_list.id, - }), - ]) - expect(response.data.product.variants[0]).toEqual( - expect.objectContaining({ - original_price: 3000, - calculated_price: 2500, - calculated_price_type: "sale", + priceSetId = priceSet.id }) - ) - }) - it("should not list prices from price-list with customer groups if not logged in", async () => { - const api = useApi()! as AxiosInstance - - const { id: customerGroupId } = await simpleCustomerGroupFactory( - dbConnection - ) - - const priceListResponse = await api.post( - `/admin/price-lists`, - { - name: "test price list", - description: "test", - status: PriceListStatus.ACTIVE, - type: PriceListType.SALE, - prices: [ + it("should get product and its prices from price-list created through the price list workflow", async () => { + const priceListResponse = await api.post( + `/admin/price-lists`, { - amount: 2500, - currency_code: "usd", - variant_id: variant.id, + name: "test price list", + description: "test", + status: PriceListStatus.ACTIVE, + type: PriceListType.SALE, + prices: [ + { + amount: 2500, + currency_code: "usd", + variant_id: variant.id, + }, + ], }, - ], - customer_groups: [{ id: customerGroupId }], - }, - adminHeaders - ) + adminHeaders + ) - let response = await api.get( - `/store/products/${product.id}?currency_code=usd` - ) + let response = await api.get( + `/store/products/${product.id}?currency_code=usd` + ) - expect(response.status).toEqual(200) - expect(response.data.product.variants[0].prices).toEqual([ - expect.objectContaining({ - currency_code: "usd", - amount: 3000, - min_quantity: null, - max_quantity: null, - price_list_id: null, - }), - ]) - expect(response.data.product.variants[0]).toEqual( - expect.objectContaining({ - original_price: 3000, - calculated_price: 3000, - calculated_price_type: null, + expect(response.status).toEqual(200) + expect(response.data.product.variants[0].prices).toHaveLength(2) + expect(response.data.product.variants[0].prices).toEqual([ + expect.objectContaining({ + currency_code: "usd", + amount: 3000, + min_quantity: null, + max_quantity: null, + price_list_id: null, + }), + expect.objectContaining({ + currency_code: "usd", + amount: 2500, + min_quantity: null, + max_quantity: null, + price_list_id: priceListResponse.data.price_list.id, + }), + ]) + expect(response.data.product.variants[0]).toEqual( + expect.objectContaining({ + original_price: 3000, + calculated_price: 2500, + calculated_price_type: "sale", + }) + ) }) - ) - }) - it("should list prices from price-list with customer groups", async () => { - const api = useApi()! as AxiosInstance + it("should not list prices from price-list with customer groups if not logged in", async () => { + const { id: customerGroupId } = await simpleCustomerGroupFactory( + dbConnection + ) - await simpleCustomerFactory(dbConnection, { - id: "test-customer-5-pl", - email: "test5@email-pl.com", - first_name: "John", - last_name: "Deere", - password_hash: - "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" - has_account: true, - groups: [{ id: "customer-group-1" }], - }) - - const authResponse = await api.post("/store/auth", { - email: "test5@email-pl.com", - password: "test", - }) - - const [authCookie] = authResponse.headers["set-cookie"][0].split(";") - - const priceListResponse = await api.post( - `/admin/price-lists`, - { - name: "test price list", - description: "test", - status: PriceListStatus.ACTIVE, - type: PriceListType.SALE, - prices: [ + const priceListResponse = await api.post( + `/admin/price-lists`, { - amount: 2500, - currency_code: "usd", - variant_id: variant.id, + name: "test price list", + description: "test", + status: PriceListStatus.ACTIVE, + type: PriceListType.SALE, + prices: [ + { + amount: 2500, + currency_code: "usd", + variant_id: variant.id, + }, + ], + customer_groups: [{ id: customerGroupId }], }, - ], - customer_groups: [{ id: "customer-group-1" }], - }, - adminHeaders - ) + adminHeaders + ) - let response = await api.get( - `/store/products/${product.id}?currency_code=usd`, - { - headers: { - Cookie: authCookie, - }, - } - ) + let response = await api.get( + `/store/products/${product.id}?currency_code=usd` + ) - expect(response.status).toEqual(200) - expect(response.data.product.variants[0].prices).toHaveLength(2) - expect(response.data.product.variants[0].prices).toEqual([ - expect.objectContaining({ - currency_code: "usd", - amount: 3000, - min_quantity: null, - max_quantity: null, - price_list_id: null, - }), - expect.objectContaining({ - currency_code: "usd", - amount: 2500, - min_quantity: null, - max_quantity: null, - price_list_id: priceListResponse.data.price_list.id, - }), - ]) - expect(response.data.product.variants[0]).toEqual( - expect.objectContaining({ - original_price: 3000, - calculated_price: 2500, - calculated_price_type: "sale", + expect(response.status).toEqual(200) + expect(response.data.product.variants[0].prices).toEqual([ + expect.objectContaining({ + currency_code: "usd", + amount: 3000, + min_quantity: null, + max_quantity: null, + price_list_id: null, + }), + ]) + expect(response.data.product.variants[0]).toEqual( + expect.objectContaining({ + original_price: 3000, + calculated_price: 3000, + calculated_price_type: null, + }) + ) }) - ) - }) + + it("should list prices from price-list with customer groups", async () => { + await simpleCustomerFactory(dbConnection, { + id: "test-customer-5-pl", + email: "test5@email-pl.com", + first_name: "John", + last_name: "Deere", + password_hash: + "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" + has_account: true, + groups: [{ id: "customer-group-1" }], + }) + + const authResponse = await api.post("/store/auth", { + email: "test5@email-pl.com", + password: "test", + }) + + const [authCookie] = authResponse.headers["set-cookie"][0].split(";") + + const priceListResponse = await api.post( + `/admin/price-lists`, + { + name: "test price list", + description: "test", + status: PriceListStatus.ACTIVE, + type: PriceListType.SALE, + prices: [ + { + amount: 2500, + currency_code: "usd", + variant_id: variant.id, + }, + ], + customer_groups: [{ id: "customer-group-1" }], + }, + adminHeaders + ) + + let response = await api.get( + `/store/products/${product.id}?currency_code=usd`, + { + headers: { + Cookie: authCookie, + }, + } + ) + + expect(response.status).toEqual(200) + expect(response.data.product.variants[0].prices).toHaveLength(2) + expect(response.data.product.variants[0].prices).toEqual([ + expect.objectContaining({ + currency_code: "usd", + amount: 3000, + min_quantity: null, + max_quantity: null, + price_list_id: null, + }), + expect.objectContaining({ + currency_code: "usd", + amount: 2500, + min_quantity: null, + max_quantity: null, + price_list_id: priceListResponse.data.price_list.id, + }), + ]) + expect(response.data.product.variants[0]).toEqual( + expect.objectContaining({ + original_price: 3000, + calculated_price: 2500, + calculated_price_type: "sale", + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/pricing/get-product.ts b/integration-tests/modules/__tests__/pricing/get-product.ts index 446ea4e078..9bb318505b 100644 --- a/integration-tests/modules/__tests__/pricing/get-product.ts +++ b/integration-tests/modules/__tests__/pricing/get-product.ts @@ -1,14 +1,9 @@ -import { useApi } from "../../../environment-helpers/use-api" -import { initDb, useDb } from "../../../environment-helpers/use-db" import { simpleCartFactory, simpleRegionFactory } from "../../../factories" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import { AxiosInstance } from "axios" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { getContainer } from "../../../environment-helpers/use-container" import adminSeeder from "../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../helpers/create-default-rule-types" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(5000000) @@ -28,109 +23,106 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("Link Modules", () => { - let medusaContainer - let dbConnection - let shutdownServer +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("Link Modules", () => { + let medusaContainer - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - medusaContainer = getContainer() - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createDefaultRuleTypes(medusaContainer) - await adminSeeder(dbConnection) - await simpleRegionFactory(dbConnection, { - id: "region-1", - currency_code: "usd", - }) - }) - - describe("get product price", () => { - let ruleType - let priceSet - let productId - const cartId = "test-cart" - beforeEach(async () => { - const pricingModuleService = medusaContainer.resolve( - ModuleRegistrationName.PRICING - ) - const api = useApi()! as AxiosInstance - - await simpleCartFactory(dbConnection, { id: cartId, region: "region-1" }) - - const payload = { - title: "Test", - description: "test-product-description", - images: ["test-image.png", "test-image-2.png"], - variants: [ - { - title: "Test variant", - prices: [], - options: [], - }, - ], - } - - const response = await api.post("/admin/products", payload, adminHeaders) - - productId = response.data.product.id - const variant = response.data.product.variants[0] - - ruleType = await pricingModuleService.createRuleTypes([ - { name: "region_id", rule_attribute: "region_id" }, - ]) - - priceSet = await pricingModuleService.create({ - rules: [{ rule_attribute: "region_id" }], - prices: [ - { - amount: 1000, - currency_code: "usd", - rules: { region_id: "region-1" }, - }, - { - amount: 900, - currency_code: "usd", - rules: { region_id: "region-2" }, - }, - ], + beforeAll(async () => { + medusaContainer = getContainer() }) - - const remoteLink = medusaContainer.resolve("remoteLink") as any - - await remoteLink.create({ - productService: { - variant_id: variant.id, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }) - }) - - it("Should get prices declared in pricing module", async () => { - const api = useApi()! as AxiosInstance - - const response = await api.get( - `/store/products/${productId}?cart_id=${cartId}` - ) - - expect(response.data.product.variants[0].prices).toEqual([ - expect.objectContaining({ - amount: 1000, + beforeEach(async () => { + await createDefaultRuleTypes(medusaContainer) + await adminSeeder(dbConnection) + await simpleRegionFactory(dbConnection, { + id: "region-1", currency_code: "usd", - }), - ]) + }) + }) + + describe("get product price", () => { + let ruleType + let priceSet + let productId + const cartId = "test-cart" + beforeEach(async () => { + const pricingModuleService = medusaContainer.resolve( + ModuleRegistrationName.PRICING + ) + + await simpleCartFactory(dbConnection, { + id: cartId, + region: "region-1", + }) + + const payload = { + title: "Test", + description: "test-product-description", + images: ["test-image.png", "test-image-2.png"], + variants: [ + { + title: "Test variant", + prices: [], + options: [], + }, + ], + } + + const response = await api.post( + "/admin/products", + payload, + adminHeaders + ) + + productId = response.data.product.id + const variant = response.data.product.variants[0] + + ruleType = await pricingModuleService.createRuleTypes([ + { name: "region_id", rule_attribute: "region_id" }, + ]) + + priceSet = await pricingModuleService.create({ + rules: [{ rule_attribute: "region_id" }], + prices: [ + { + amount: 1000, + currency_code: "usd", + rules: { region_id: "region-1" }, + }, + { + amount: 900, + currency_code: "usd", + rules: { region_id: "region-2" }, + }, + ], + }) + + const remoteLink = medusaContainer.resolve("remoteLink") as any + + await remoteLink.create({ + productService: { + variant_id: variant.id, + }, + pricingService: { + price_set_id: priceSet.id, + }, + }) + }) + + it("Should get prices declared in pricing module", async () => { + const response = await api.get( + `/store/products/${productId}?cart_id=${cartId}` + ) + + expect(response.data.product.variants[0].prices).toEqual([ + expect.objectContaining({ + amount: 1000, + currency_code: "usd", + }), + ]) + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/product/admin/create-product-variant.spec.ts b/integration-tests/modules/__tests__/product/admin/create-product-variant.spec.ts index d26859faad..2cd1a4dbe8 100644 --- a/integration-tests/modules/__tests__/product/admin/create-product-variant.spec.ts +++ b/integration-tests/modules/__tests__/product/admin/create-product-variant.spec.ts @@ -1,17 +1,12 @@ import { PricingModuleService } from "@medusajs/pricing" import { ProductModuleService } from "@medusajs/product" -import { AxiosInstance } from "axios" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { simpleProductFactory, simpleRegionFactory, } from "../../../../factories" import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -25,180 +20,171 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe.skip("POST /admin/products/:id/variants", () => { - let dbConnection - let appContainer - let shutdownServer - let product - let variant +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe.skip("POST /admin/products/:id/variants", () => { + let appContainer + let product + let variant - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - }) + beforeAll(async () => { + appContainer = getContainer() + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await adminSeeder(dbConnection) + await createDefaultRuleTypes(appContainer) - beforeEach(async () => { - await adminSeeder(dbConnection) - await createDefaultRuleTypes(appContainer) - - await simpleRegionFactory(dbConnection, { - id: "test-region", - name: "Test Region", - currency_code: "usd", - tax_rate: 0, - }) - - product = await simpleProductFactory(dbConnection, { - id: "test-product-with-variant", - variants: [ - { - options: [{ option_id: "test-product-option-1", value: "test" }], - }, - ], - options: [ - { - id: "test-product-option-1", - title: "Test option 1", - }, - ], - }) - - variant = product.variants[0] - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should create a product variant with its price sets and prices through the workflow", async () => { - const api = useApi()! as AxiosInstance - const data = { - title: "test variant create", - prices: [ - { - amount: 66600, - region_id: "test-region", - }, - { - amount: 55500, + await simpleRegionFactory(dbConnection, { + id: "test-region", + name: "Test Region", currency_code: "usd", - region_id: null, - }, - ], - material: "boo", - mid_code: "234asdfadsf", - hs_code: "asdfasdf234", - origin_country: "DE", - sku: "asdf", - ean: "234", - upc: "234", - barcode: "asdf", - inventory_quantity: 234, - manage_inventory: true, - allow_backorder: true, - weight: 234, - width: 234, - height: 234, - length: 234, - metadata: { asdf: "asdf" }, - options: [{ option_id: "test-product-option-1", value: "test option" }], - } + tax_rate: 0, + }) - let response = await api.post( - `/admin/products/${product.id}/variants`, - data, - adminHeaders - ) + product = await simpleProductFactory(dbConnection, { + id: "test-product-with-variant", + variants: [ + { + options: [{ option_id: "test-product-option-1", value: "test" }], + }, + ], + options: [ + { + id: "test-product-option-1", + title: "Test option 1", + }, + ], + }) - expect(response.status).toEqual(200) - expect(response.data.product).toEqual( - expect.objectContaining({ - id: expect.any(String), - variants: expect.arrayContaining([ + variant = product.variants[0] + }) + + it("should create a product variant with its price sets and prices through the workflow", async () => { + const data = { + title: "test variant create", + prices: [ + { + amount: 66600, + region_id: "test-region", + }, + { + amount: 55500, + currency_code: "usd", + region_id: null, + }, + ], + material: "boo", + mid_code: "234asdfadsf", + hs_code: "asdfasdf234", + origin_country: "DE", + sku: "asdf", + ean: "234", + upc: "234", + barcode: "asdf", + inventory_quantity: 234, + manage_inventory: true, + allow_backorder: true, + weight: 234, + width: 234, + height: 234, + length: 234, + metadata: { asdf: "asdf" }, + options: [ + { option_id: "test-product-option-1", value: "test option" }, + ], + } + + let response = await api.post( + `/admin/products/${product.id}/variants`, + data, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.product).toEqual( expect.objectContaining({ id: expect.any(String), - title: "test variant create", - prices: expect.arrayContaining([ + variants: expect.arrayContaining([ expect.objectContaining({ - amount: 66600, - currency_code: "usd", - region_id: "test-region", - }), - expect.objectContaining({ - amount: 55500, - currency_code: "usd", + id: expect.any(String), + title: "test variant create", + prices: expect.arrayContaining([ + expect.objectContaining({ + amount: 66600, + currency_code: "usd", + region_id: "test-region", + }), + expect.objectContaining({ + amount: 55500, + currency_code: "usd", + }), + ]), }), ]), - }), - ]), - }) - ) - }) - - it("should compensate creating product variants when error throws in future step", async () => { - jest - .spyOn(PricingModuleService.prototype, "create") - .mockImplementation(() => { - throw new Error("Random Error") + }) + ) }) - const productSpy = jest.spyOn( - ProductModuleService.prototype, - "deleteVariants" - ) + it("should compensate creating product variants when error throws in future step", async () => { + jest + .spyOn(PricingModuleService.prototype, "create") + .mockImplementation(() => { + throw new Error("Random Error") + }) - const api = useApi()! as AxiosInstance - const data = { - title: "test variant create", - prices: [ - { - amount: 66600, - region_id: "test-region", - }, - { - amount: 55500, - currency_code: "usd", - region_id: null, - }, - ], - material: "boo", - mid_code: "234asdfadsf", - hs_code: "asdfasdf234", - origin_country: "DE", - sku: "asdf", - ean: "234", - upc: "234", - barcode: "asdf", - inventory_quantity: 234, - manage_inventory: true, - allow_backorder: true, - weight: 234, - width: 234, - height: 234, - length: 234, - metadata: { asdf: "asdf" }, - options: [{ option_id: "test-product-option-1", value: "test option" }], - } + const productSpy = jest.spyOn( + ProductModuleService.prototype, + "deleteVariants" + ) - await api - .post(`/admin/products/${product.id}/variants`, data, adminHeaders) - .catch((e) => e) + const data = { + title: "test variant create", + prices: [ + { + amount: 66600, + region_id: "test-region", + }, + { + amount: 55500, + currency_code: "usd", + region_id: null, + }, + ], + material: "boo", + mid_code: "234asdfadsf", + hs_code: "asdfasdf234", + origin_country: "DE", + sku: "asdf", + ean: "234", + upc: "234", + barcode: "asdf", + inventory_quantity: 234, + manage_inventory: true, + allow_backorder: true, + weight: 234, + width: 234, + height: 234, + length: 234, + metadata: { asdf: "asdf" }, + options: [ + { option_id: "test-product-option-1", value: "test option" }, + ], + } - expect(productSpy).toBeCalledWith([expect.any(String)]) + await api + .post(`/admin/products/${product.id}/variants`, data, adminHeaders) + .catch((e) => e) - const getProductResponse = await api.get( - `/admin/products/${product.id}`, - adminHeaders - ) - expect(getProductResponse.data.product.variants).toHaveLength(1) - }) + expect(productSpy).toBeCalledWith([expect.any(String)]) + + const getProductResponse = await api.get( + `/admin/products/${product.id}`, + adminHeaders + ) + expect(getProductResponse.data.product.variants).toHaveLength(1) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/product/admin/create-product.spec.ts b/integration-tests/modules/__tests__/product/admin/create-product.spec.ts index 94e0290603..a811e90795 100644 --- a/integration-tests/modules/__tests__/product/admin/create-product.spec.ts +++ b/integration-tests/modules/__tests__/product/admin/create-product.spec.ts @@ -1,18 +1,5 @@ -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { initDb, useDb } from "../../../../environment-helpers/use-db" - -import productSeeder from "../../../../helpers/product-seeder" - -import { AxiosInstance } from "axios" -import { getContainer } from "../../../../environment-helpers/use-container" -import { - simpleProductFactory, - simpleSalesChannelFactory, -} from "../../../../factories" -import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createAdminUser } from "../../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils/dist" jest.setTimeout(50000) @@ -26,469 +13,448 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } -describe("/admin/products", () => { - let dbConnection - let shutdownServer - let medusaContainer +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("/admin/products", () => { + let medusaContainer - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env }) - shutdownServer = await startBootstrapApp({ cwd, env }) - medusaContainer = getContainer() - }) + beforeAll(async () => { + medusaContainer = getContainer() + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, medusaContainer) - describe("POST /admin/products", () => { - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) + // await productSeeder(dbConnection) + // await createDefaultRuleTypes(medusaContainer) + // await simpleSalesChannelFactory(dbConnection, { + // name: "Default channel", + // id: "default-channel", + // is_default: true, + // }) + }) - // await productSeeder(dbConnection) - // await createDefaultRuleTypes(medusaContainer) - // await simpleSalesChannelFactory(dbConnection, { - // name: "Default channel", - // id: "default-channel", - // is_default: true, - // }) - }) + describe("POST /admin/products", () => { + it("should create a product", async () => { + const payload = { + title: "Test", + description: "test-product-description", + // type: { value: "test-type" }, + images: ["test-image.png", "test-image-2.png"], + // collection_id: "test-collection", + // tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant", + inventory_quantity: 10, + // prices: [ + // { + // currency_code: "usd", + // amount: 100, + // }, + // { + // currency_code: "eur", + // amount: 45, + // }, + // { + // currency_code: "dkk", + // amount: 30, + // }, + // ], + // options: [{ value: "large" }, { value: "green" }], + }, + ], + } - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api + .post("/admin/products", payload, adminHeaders) + .catch((err) => { + console.log(err) + }) - it("should create a product", async () => { - const api = useApi()! as AxiosInstance - - const payload = { - title: "Test", - description: "test-product-description", - // type: { value: "test-type" }, - images: ["test-image.png", "test-image-2.png"], - // collection_id: "test-collection", - // tags: [{ value: "123" }, { value: "456" }], - options: [{ title: "size" }, { title: "color" }], - variants: [ - { - title: "Test variant", - inventory_quantity: 10, - // prices: [ - // { - // currency_code: "usd", - // amount: 100, - // }, - // { - // currency_code: "eur", - // amount: 45, - // }, - // { - // currency_code: "dkk", - // amount: 30, - // }, - // ], - // options: [{ value: "large" }, { value: "green" }], - }, - ], - } - - const response = await api - .post("/admin/products", payload, adminHeaders) - .catch((err) => { - console.log(err) - }) - - expect(response?.status).toEqual(200) - expect(response?.data.product).toEqual( - expect.objectContaining({ - id: expect.stringMatching(/^prod_*/), - title: "Test", - discountable: true, - is_giftcard: false, - handle: "test", - status: "draft", - // profile_id: expect.stringMatching(/^sp_*/), - thumbnail: "test-image.png", - created_at: expect.any(String), - updated_at: expect.any(String), - }) - ) - - expect(response?.data.product.images).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(String), - url: "test-image.png", - created_at: expect.any(String), - updated_at: expect.any(String), - }), - expect.objectContaining({ - id: expect.any(String), - url: "test-image-2.png", - created_at: expect.any(String), - updated_at: expect.any(String), - }), - ]) - ) - - console.log(response?.data.product) - - expect(response?.data.product.variants).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: expect.stringMatching(/^variant_*/), - title: "Test variant", - // product_id: expect.stringMatching(/^prod_*/), - updated_at: expect.any(String), - created_at: expect.any(String), - // prices: expect.arrayContaining([ - // expect.objectContaining({ - // id: expect.stringMatching(/^ma_*/), - // currency_code: "usd", - // amount: 100, - // // TODO: enable this in the Pricing Module PR - // // created_at: expect.any(String), - // // updated_at: expect.any(String), - // // variant_id: expect.stringMatching(/^variant_*/), - // }), - // expect.objectContaining({ - // id: expect.stringMatching(/^ma_*/), - // currency_code: "eur", - // amount: 45, - // // TODO: enable this in the Pricing Module PR - // // created_at: expect.any(String), - // // updated_at: expect.any(String), - // // variant_id: expect.stringMatching(/^variant_*/), - // }), - // expect.objectContaining({ - // id: expect.stringMatching(/^ma_*/), - // currency_code: "dkk", - // amount: 30, - // // TODO: enable this in the Pricing Module PR - // // created_at: expect.any(String), - // // updated_at: expect.any(String), - // // variant_id: expect.stringMatching(/^variant_*/), - // }), - // ]), - // options: expect.arrayContaining([ - // expect.objectContaining({ - // value: "large", - // created_at: expect.any(String), - // updated_at: expect.any(String), - // variant_id: expect.stringMatching(/^variant_*/), - // option_id: expect.stringMatching(/^opt_*/), - // id: expect.stringMatching(/^optval_*/), - // }), - // expect.objectContaining({ - // value: "green", - // created_at: expect.any(String), - // updated_at: expect.any(String), - // variant_id: expect.stringMatching(/^variant_*/), - // option_id: expect.stringMatching(/^opt_*/), - // id: expect.stringMatching(/^optval_*/), - // }), - // ]), - }), - ]) - ) - - expect(response?.data.product.options).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: expect.stringMatching(/^opt_*/), - // product_id: expect.stringMatching(/^prod_*/), - title: "size", - created_at: expect.any(String), - updated_at: expect.any(String), - }), - expect.objectContaining({ - id: expect.stringMatching(/^opt_*/), - // product_id: expect.stringMatching(/^prod_*/), - title: "color", - created_at: expect.any(String), - updated_at: expect.any(String), - }), - ]) - ) - - // tags: expect.arrayContaining([ - // expect.objectContaining({ - // id: expect.any(String), - // value: "123", - // created_at: expect.any(String), - // updated_at: expect.any(String), - // }), - // expect.objectContaining({ - // id: expect.any(String), - // value: "456", - // created_at: expect.any(String), - // updated_at: expect.any(String), - // }), - // ]), - // type: expect.objectContaining({ - // value: "test-type", - // created_at: expect.any(String), - // updated_at: expect.any(String), - // }), - // collection: expect.objectContaining({ - // id: "test-collection", - // title: "Test collection", - // created_at: expect.any(String), - // updated_at: expect.any(String), - // }), - }) - - it("should create a product that is not discountable", async () => { - const api = useApi()! as AxiosInstance - - const payload = { - title: "Test", - discountable: false, - description: "test-product-description", - // type: { value: "test-type" }, - images: ["test-image.png", "test-image-2.png"], - // collection_id: "test-collection", - // tags: [{ value: "123" }, { value: "456" }], - options: [{ title: "size" }, { title: "color" }], - variants: [ - { - title: "Test variant", - inventory_quantity: 10, - // prices: [{ currency_code: "usd", amount: 100 }], - // options: [{ value: "large" }, { value: "green" }], - }, - ], - } - - const response = await api - .post("/admin/products", payload, adminHeaders) - .catch((err) => { - console.log(err) - }) - - expect(response?.status).toEqual(200) - expect(response?.data.product).toEqual( - expect.objectContaining({ - discountable: false, - }) - ) - }) - - it("should sets the variant ranks when creating a product", async () => { - const api = useApi()! as AxiosInstance - - const payload = { - title: "Test product - 1", - description: "test-product-description 1", - // type: { value: "test-type 1" }, - images: ["test-image.png", "test-image-2.png"], - // collection_id: "test-collection", - // tags: [{ value: "123" }, { value: "456" }], - options: [{ title: "size" }, { title: "color" }], - variants: [ - { - title: "Test variant 1", - inventory_quantity: 10, - // prices: [{ currency_code: "usd", amount: 100 }], - // options: [{ value: "large" }, { value: "green" }], - }, - { - title: "Test variant 2", - inventory_quantity: 10, - // prices: [{ currency_code: "usd", amount: 100 }], - // options: [{ value: "large" }, { value: "green" }], - }, - ], - } - - const creationResponse = await api - .post("/admin/products", payload, adminHeaders) - .catch((err) => { - console.log(err) - }) - - expect(creationResponse?.status).toEqual(200) - - const productId = creationResponse?.data.product.id - - const response = await api - .get( - `/admin/products/${productId}?fields=title,variants.title`, - adminHeaders - ) - .catch((err) => { - console.log(err) - }) - - expect(response?.data.product).toEqual( - expect.objectContaining({ - title: "Test product - 1", - variants: [ + expect(response?.status).toEqual(200) + expect(response?.data.product).toEqual( expect.objectContaining({ - title: "Test variant 1", - }), + id: expect.stringMatching(/^prod_*/), + title: "Test", + discountable: true, + is_giftcard: false, + handle: "test", + status: "draft", + // profile_id: expect.stringMatching(/^sp_*/), + thumbnail: "test-image.png", + created_at: expect.any(String), + updated_at: expect.any(String), + }) + ) + + expect(response?.data.product.images).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + url: "test-image.png", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + expect.objectContaining({ + id: expect.any(String), + url: "test-image-2.png", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + ]) + ) + + console.log(response?.data.product) + + expect(response?.data.product.variants).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: expect.stringMatching(/^variant_*/), + title: "Test variant", + // product_id: expect.stringMatching(/^prod_*/), + updated_at: expect.any(String), + created_at: expect.any(String), + // prices: expect.arrayContaining([ + // expect.objectContaining({ + // id: expect.stringMatching(/^ma_*/), + // currency_code: "usd", + // amount: 100, + // // TODO: enable this in the Pricing Module PR + // // created_at: expect.any(String), + // // updated_at: expect.any(String), + // // variant_id: expect.stringMatching(/^variant_*/), + // }), + // expect.objectContaining({ + // id: expect.stringMatching(/^ma_*/), + // currency_code: "eur", + // amount: 45, + // // TODO: enable this in the Pricing Module PR + // // created_at: expect.any(String), + // // updated_at: expect.any(String), + // // variant_id: expect.stringMatching(/^variant_*/), + // }), + // expect.objectContaining({ + // id: expect.stringMatching(/^ma_*/), + // currency_code: "dkk", + // amount: 30, + // // TODO: enable this in the Pricing Module PR + // // created_at: expect.any(String), + // // updated_at: expect.any(String), + // // variant_id: expect.stringMatching(/^variant_*/), + // }), + // ]), + // options: expect.arrayContaining([ + // expect.objectContaining({ + // value: "large", + // created_at: expect.any(String), + // updated_at: expect.any(String), + // variant_id: expect.stringMatching(/^variant_*/), + // option_id: expect.stringMatching(/^opt_*/), + // id: expect.stringMatching(/^optval_*/), + // }), + // expect.objectContaining({ + // value: "green", + // created_at: expect.any(String), + // updated_at: expect.any(String), + // variant_id: expect.stringMatching(/^variant_*/), + // option_id: expect.stringMatching(/^opt_*/), + // id: expect.stringMatching(/^optval_*/), + // }), + // ]), + }), + ]) + ) + + expect(response?.data.product.options).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: expect.stringMatching(/^opt_*/), + // product_id: expect.stringMatching(/^prod_*/), + title: "size", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + expect.objectContaining({ + id: expect.stringMatching(/^opt_*/), + // product_id: expect.stringMatching(/^prod_*/), + title: "color", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + ]) + ) + + // tags: expect.arrayContaining([ + // expect.objectContaining({ + // id: expect.any(String), + // value: "123", + // created_at: expect.any(String), + // updated_at: expect.any(String), + // }), + // expect.objectContaining({ + // id: expect.any(String), + // value: "456", + // created_at: expect.any(String), + // updated_at: expect.any(String), + // }), + // ]), + // type: expect.objectContaining({ + // value: "test-type", + // created_at: expect.any(String), + // updated_at: expect.any(String), + // }), + // collection: expect.objectContaining({ + // id: "test-collection", + // title: "Test collection", + // created_at: expect.any(String), + // updated_at: expect.any(String), + // }), + }) + + it("should create a product that is not discountable", async () => { + const payload = { + title: "Test", + discountable: false, + description: "test-product-description", + // type: { value: "test-type" }, + images: ["test-image.png", "test-image-2.png"], + // collection_id: "test-collection", + // tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant", + inventory_quantity: 10, + // prices: [{ currency_code: "usd", amount: 100 }], + // options: [{ value: "large" }, { value: "green" }], + }, + ], + } + + const response = await api + .post("/admin/products", payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(response?.status).toEqual(200) + expect(response?.data.product).toEqual( expect.objectContaining({ - title: "Test variant 2", - }), - ], - }) - ) - }) - - it("should create a giftcard", async () => { - const api = useApi()! as AxiosInstance - - const payload = { - title: "Test Giftcard", - is_giftcard: true, - description: "test-giftcard-description", - options: [{ title: "Denominations" }], - variants: [ - { - title: "Test variant", - // prices: [{ currency_code: "usd", amount: 100 }], - // options: [{ value: "100" }], - }, - ], - } - - const response = await api - .post("/admin/products", payload, adminHeaders) - .catch((err) => { - console.log(err) + discountable: false, + }) + ) }) - expect(response?.status).toEqual(200) + it("should sets the variant ranks when creating a product", async () => { + const payload = { + title: "Test product - 1", + description: "test-product-description 1", + // type: { value: "test-type 1" }, + images: ["test-image.png", "test-image-2.png"], + // collection_id: "test-collection", + // tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant 1", + inventory_quantity: 10, + // prices: [{ currency_code: "usd", amount: 100 }], + // options: [{ value: "large" }, { value: "green" }], + }, + { + title: "Test variant 2", + inventory_quantity: 10, + // prices: [{ currency_code: "usd", amount: 100 }], + // options: [{ value: "large" }, { value: "green" }], + }, + ], + } - expect(response?.data.product).toEqual( - expect.objectContaining({ - title: "Test Giftcard", - discountable: false, + const creationResponse = await api + .post("/admin/products", payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(creationResponse?.status).toEqual(200) + + const productId = creationResponse?.data.product.id + + const response = await api + .get( + `/admin/products/${productId}?fields=title,variants.title`, + adminHeaders + ) + .catch((err) => { + console.log(err) + }) + + expect(response?.data.product).toEqual( + expect.objectContaining({ + title: "Test product - 1", + variants: [ + expect.objectContaining({ + title: "Test variant 1", + }), + expect.objectContaining({ + title: "Test variant 2", + }), + ], + }) + ) }) - ) - }) - it("should create variants with inventory items", async () => { - const api = useApi()! as AxiosInstance + it("should create a giftcard", async () => { + const payload = { + title: "Test Giftcard", + is_giftcard: true, + description: "test-giftcard-description", + options: [{ title: "Denominations" }], + variants: [ + { + title: "Test variant", + // prices: [{ currency_code: "usd", amount: 100 }], + // options: [{ value: "100" }], + }, + ], + } - const response = await api.post( - `/admin/products`, - { - title: "Test product - 1", - description: "test-product-description 1", - // type: { value: "test-type 1" }, - images: ["test-image.png", "test-image-2.png"], - // collection_id: "test-collection", - // tags: [{ value: "123" }, { value: "456" }], - options: [{ title: "size" }, { title: "color" }], - variants: [ + const response = await api + .post("/admin/products", payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(response?.status).toEqual(200) + + expect(response?.data.product).toEqual( + expect.objectContaining({ + title: "Test Giftcard", + discountable: false, + }) + ) + }) + + it("should create variants with inventory items", async () => { + const response = await api.post( + `/admin/products`, { - title: "Test variant 1", - inventory_quantity: 10, - // prices: [{ currency_code: "usd", amount: 100 }], - // options: [{ value: "large" }, { value: "green" }], + title: "Test product - 1", + description: "test-product-description 1", + // type: { value: "test-type 1" }, + images: ["test-image.png", "test-image-2.png"], + // collection_id: "test-collection", + // tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant 1", + inventory_quantity: 10, + // prices: [{ currency_code: "usd", amount: 100 }], + // options: [{ value: "large" }, { value: "green" }], + }, + { + title: "Test variant 2", + inventory_quantity: 10, + // prices: [{ currency_code: "usd", amount: 100 }], + // options: [{ value: "large" }, { value: "green" }], + }, + ], }, - { - title: "Test variant 2", - inventory_quantity: 10, - // prices: [{ currency_code: "usd", amount: 100 }], - // options: [{ value: "large" }, { value: "green" }], - }, - ], - }, - adminHeaders - ) + adminHeaders + ) - expect(response.status).toEqual(200) + expect(response.status).toEqual(200) - // const variantIds = response.data.product.variants.map( - // (v: { id: string }) => v.id - // ) + // const variantIds = response.data.product.variants.map( + // (v: { id: string }) => v.id + // ) - // const variantInventoryService = medusaContainer.resolve( - // "productVariantInventoryService" - // ) - // const inventory = await variantInventoryService.listByVariant(variantIds) + // const variantInventoryService = medusaContainer.resolve( + // "productVariantInventoryService" + // ) + // const inventory = await variantInventoryService.listByVariant(variantIds) - // expect(inventory).toHaveLength(2) - // expect(inventory).toContainEqual( - // expect.objectContaining({ - // variant_id: variantIds[0], - // required_quantity: 1, - // }) - // ) - // expect(inventory).toContainEqual( - // expect.objectContaining({ - // variant_id: variantIds[1], - // required_quantity: 1, - // }) - // ) + // expect(inventory).toHaveLength(2) + // expect(inventory).toContainEqual( + // expect.objectContaining({ + // variant_id: variantIds[0], + // required_quantity: 1, + // }) + // ) + // expect(inventory).toContainEqual( + // expect.objectContaining({ + // variant_id: variantIds[1], + // required_quantity: 1, + // }) + // ) + }) + + // it("should create prices with region_id and currency_code context", async () => { + // const api = useApi()! as AxiosInstance + + // const data = { + // title: "test product", + // options: [{ title: "test-option" }], + // variants: [ + // { + // title: "test variant", + // prices: [ + // { + // amount: 66600, + // region_id: "test-region", + // }, + // { + // amount: 55500, + // currency_code: "usd", + // }, + // ], + // options: [{ value: "test-option" }], + // }, + // ], + // } + + // let response = await api.post( + // "/admin/products?relations=variants.prices", + // data, + // adminHeaders + // ) + + // expect(response.status).toEqual(200) + // expect(response.data).toEqual({ + // product: expect.objectContaining({ + // id: expect.any(String), + // title: "test product", + // variants: expect.arrayContaining([ + // expect.objectContaining({ + // id: expect.any(String), + // title: "test variant", + // prices: expect.arrayContaining([ + // expect.objectContaining({ + // amount: 66600, + // currency_code: "usd", + // }), + // expect.objectContaining({ + // amount: 55500, + // currency_code: "usd", + // }), + // ]), + // }), + // ]), + // }), + // }) + + // const pricingModuleService: IPricingModuleService = appContainer.resolve( + // "pricingModuleService" + // ) + + // const [_, count] = await pricingModuleService.listAndCount() + // expect(count).toEqual(1) + // }) + }) }) - - // it("should create prices with region_id and currency_code context", async () => { - // const api = useApi()! as AxiosInstance - - // const data = { - // title: "test product", - // options: [{ title: "test-option" }], - // variants: [ - // { - // title: "test variant", - // prices: [ - // { - // amount: 66600, - // region_id: "test-region", - // }, - // { - // amount: 55500, - // currency_code: "usd", - // }, - // ], - // options: [{ value: "test-option" }], - // }, - // ], - // } - - // let response = await api.post( - // "/admin/products?relations=variants.prices", - // data, - // adminHeaders - // ) - - // expect(response.status).toEqual(200) - // expect(response.data).toEqual({ - // product: expect.objectContaining({ - // id: expect.any(String), - // title: "test product", - // variants: expect.arrayContaining([ - // expect.objectContaining({ - // id: expect.any(String), - // title: "test variant", - // prices: expect.arrayContaining([ - // expect.objectContaining({ - // amount: 66600, - // currency_code: "usd", - // }), - // expect.objectContaining({ - // amount: 55500, - // currency_code: "usd", - // }), - // ]), - // }), - // ]), - // }), - // }) - - // const pricingModuleService: IPricingModuleService = appContainer.resolve( - // "pricingModuleService" - // ) - - // const [_, count] = await pricingModuleService.listAndCount() - // expect(count).toEqual(1) - // }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/product/admin/export-products.spec.ts b/integration-tests/modules/__tests__/product/admin/export-products.spec.ts index f47a54a94f..7080ea0c3e 100644 --- a/integration-tests/modules/__tests__/product/admin/export-products.spec.ts +++ b/integration-tests/modules/__tests__/product/admin/export-products.spec.ts @@ -24,6 +24,10 @@ const env: Record = { jest.setTimeout(180000) +// TODO SEE to use new test runner medusaIntegrationTestRunner({ +// env, +// testSuite: ({ dbConnection, getContainer, api }) => {}) + describe.skip("Batch job of product-export type", () => { let medusaProcess let dbConnection diff --git a/integration-tests/modules/__tests__/product/admin/import-products.spec.ts b/integration-tests/modules/__tests__/product/admin/import-products.spec.ts index 26b81fcce3..cba5e13a9d 100644 --- a/integration-tests/modules/__tests__/product/admin/import-products.spec.ts +++ b/integration-tests/modules/__tests__/product/admin/import-products.spec.ts @@ -56,6 +56,10 @@ const env: Record = { MEDUSA_FF_MEDUSA_V2: true, } +// TODO SEE to use new test runner medusaIntegrationTestRunner({ +// env, +// testSuite: ({ dbConnection, getContainer, api }) => {}) + describe.skip("Product import batch job", () => { let dbConnection let shutdownServer diff --git a/integration-tests/modules/__tests__/product/admin/index.ts b/integration-tests/modules/__tests__/product/admin/index.ts new file mode 100644 index 0000000000..bf91a6257c --- /dev/null +++ b/integration-tests/modules/__tests__/product/admin/index.ts @@ -0,0 +1,659 @@ +import path from "path" +import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" +import { useApi } from "../../../../environment-helpers/use-api" +import { initDb, useDb } from "../../../../environment-helpers/use-db" + +import adminSeeder from "../../../../helpers/admin-seeder" +import productSeeder from "../../../../helpers/product-seeder" + +import { Modules, ModulesDefinition } from "@medusajs/modules-sdk" +import { MedusaV2Flag } from "@medusajs/utils" +import { AxiosInstance } from "axios" +import { getContainer } from "../../../../environment-helpers/use-container" +import { + simpleProductFactory, + simpleSalesChannelFactory, +} from "../../../../factories" +import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" + +jest.setTimeout(50000) + +const adminHeaders = { + headers: { + "x-medusa-access-token": "test_token", + }, +} + +const env = { + MEDUSA_FF_MEDUSA_V2: true, +} + +// TODO SEE to use new test runner medusaIntegrationTestRunner({ +// env, +// testSuite: ({ dbConnection, getContainer, api }) => {}) + +describe.skip("/admin/products", () => { + let dbConnection + let shutdownServer + let medusaContainer + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) + dbConnection = await initDb({ cwd, env }) + shutdownServer = await startBootstrapApp({ cwd, env }) + medusaContainer = getContainer() + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + it("Should have loaded the product module", function () { + const productRegistrationName = + ModulesDefinition[Modules.PRODUCT].registrationName + expect( + medusaContainer.hasRegistration(productRegistrationName) + ).toBeTruthy() + }) + + it("Should have enabled workflows feature flag", function () { + const flagRouter = medusaContainer.resolve("featureFlagRouter") + + const workflowsFlag = flagRouter.isFeatureEnabled(MedusaV2Flag.key) + + expect(workflowsFlag).toBe(true) + }) + + describe("POST /admin/products", () => { + beforeEach(async () => { + await productSeeder(dbConnection) + await adminSeeder(dbConnection) + await createDefaultRuleTypes(medusaContainer) + + await simpleSalesChannelFactory(dbConnection, { + name: "Default channel", + id: "default-channel", + is_default: true, + }) + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should create a product", async () => { + const api = useApi()! as AxiosInstance + + const payload = { + title: "Test", + description: "test-product-description", + type: { value: "test-type" }, + images: ["test-image.png", "test-image-2.png"], + collection_id: "test-collection", + tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant", + inventory_quantity: 10, + prices: [ + { + currency_code: "usd", + amount: 100, + }, + { + currency_code: "eur", + amount: 45, + }, + { + currency_code: "dkk", + amount: 30, + }, + ], + options: [{ value: "large" }, { value: "green" }], + }, + ], + } + + const response = await api + .post("/admin/products", payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(response?.status).toEqual(200) + expect(response?.data.product).toEqual( + expect.objectContaining({ + id: expect.stringMatching(/^prod_*/), + title: "Test", + discountable: true, + is_giftcard: false, + handle: "test", + status: "draft", + created_at: expect.any(String), + updated_at: expect.any(String), + profile_id: expect.stringMatching(/^sp_*/), + images: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + url: "test-image.png", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + expect.objectContaining({ + id: expect.any(String), + url: "test-image-2.png", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + ]), + thumbnail: "test-image.png", + tags: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + value: "123", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + expect.objectContaining({ + id: expect.any(String), + value: "456", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + ]), + type: expect.objectContaining({ + value: "test-type", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + collection: expect.objectContaining({ + id: "test-collection", + title: "Test collection", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + options: expect.arrayContaining([ + expect.objectContaining({ + id: expect.stringMatching(/^opt_*/), + product_id: expect.stringMatching(/^prod_*/), + title: "size", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + expect.objectContaining({ + id: expect.stringMatching(/^opt_*/), + product_id: expect.stringMatching(/^prod_*/), + title: "color", + created_at: expect.any(String), + updated_at: expect.any(String), + }), + ]), + variants: expect.arrayContaining([ + expect.objectContaining({ + id: expect.stringMatching(/^variant_*/), + product_id: expect.stringMatching(/^prod_*/), + updated_at: expect.any(String), + created_at: expect.any(String), + title: "Test variant", + prices: expect.arrayContaining([ + expect.objectContaining({ + id: expect.stringMatching(/^ma_*/), + currency_code: "usd", + amount: 100, + // TODO: enable this in the Pricing Module PR + // created_at: expect.any(String), + // updated_at: expect.any(String), + // variant_id: expect.stringMatching(/^variant_*/), + }), + expect.objectContaining({ + id: expect.stringMatching(/^ma_*/), + currency_code: "eur", + amount: 45, + // TODO: enable this in the Pricing Module PR + // created_at: expect.any(String), + // updated_at: expect.any(String), + // variant_id: expect.stringMatching(/^variant_*/), + }), + expect.objectContaining({ + id: expect.stringMatching(/^ma_*/), + currency_code: "dkk", + amount: 30, + // TODO: enable this in the Pricing Module PR + // created_at: expect.any(String), + // updated_at: expect.any(String), + // variant_id: expect.stringMatching(/^variant_*/), + }), + ]), + options: expect.arrayContaining([ + expect.objectContaining({ + value: "large", + created_at: expect.any(String), + updated_at: expect.any(String), + variant_id: expect.stringMatching(/^variant_*/), + option_id: expect.stringMatching(/^opt_*/), + id: expect.stringMatching(/^optval_*/), + }), + expect.objectContaining({ + value: "green", + created_at: expect.any(String), + updated_at: expect.any(String), + variant_id: expect.stringMatching(/^variant_*/), + option_id: expect.stringMatching(/^opt_*/), + id: expect.stringMatching(/^optval_*/), + }), + ]), + }), + ]), + }) + ) + }) + + it("should create a product that is not discountable", async () => { + const api = useApi()! as AxiosInstance + + const payload = { + title: "Test", + discountable: false, + description: "test-product-description", + type: { value: "test-type" }, + images: ["test-image.png", "test-image-2.png"], + collection_id: "test-collection", + tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant", + inventory_quantity: 10, + prices: [{ currency_code: "usd", amount: 100 }], + options: [{ value: "large" }, { value: "green" }], + }, + ], + } + + const response = await api + .post("/admin/products", payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(response?.status).toEqual(200) + expect(response?.data.product).toEqual( + expect.objectContaining({ + discountable: false, + }) + ) + }) + + it("should sets the variant ranks when creating a product", async () => { + const api = useApi()! as AxiosInstance + + const payload = { + title: "Test product - 1", + description: "test-product-description 1", + type: { value: "test-type 1" }, + images: ["test-image.png", "test-image-2.png"], + collection_id: "test-collection", + tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant 1", + inventory_quantity: 10, + prices: [{ currency_code: "usd", amount: 100 }], + options: [{ value: "large" }, { value: "green" }], + }, + { + title: "Test variant 2", + inventory_quantity: 10, + prices: [{ currency_code: "usd", amount: 100 }], + options: [{ value: "large" }, { value: "green" }], + }, + ], + } + + const creationResponse = await api + .post("/admin/products", payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(creationResponse?.status).toEqual(200) + + const productId = creationResponse?.data.product.id + + const response = await api + .get(`/admin/products/${productId}`, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(response?.data.product).toEqual( + expect.objectContaining({ + title: "Test product - 1", + variants: [ + expect.objectContaining({ + title: "Test variant 1", + }), + expect.objectContaining({ + title: "Test variant 2", + }), + ], + }) + ) + }) + + it("should create a giftcard", async () => { + const api = useApi()! as AxiosInstance + + const payload = { + title: "Test Giftcard", + is_giftcard: true, + description: "test-giftcard-description", + options: [{ title: "Denominations" }], + variants: [ + { + title: "Test variant", + prices: [{ currency_code: "usd", amount: 100 }], + options: [{ value: "100" }], + }, + ], + } + + const response = await api + .post("/admin/products", payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(response?.status).toEqual(200) + + expect(response?.data.product).toEqual( + expect.objectContaining({ + title: "Test Giftcard", + discountable: false, + }) + ) + }) + + it("should create variants with inventory items", async () => { + const api = useApi()! as AxiosInstance + + const response = await api.post( + `/admin/products`, + { + title: "Test product - 1", + description: "test-product-description 1", + type: { value: "test-type 1" }, + images: ["test-image.png", "test-image-2.png"], + collection_id: "test-collection", + tags: [{ value: "123" }, { value: "456" }], + options: [{ title: "size" }, { title: "color" }], + variants: [ + { + title: "Test variant 1", + inventory_quantity: 10, + prices: [{ currency_code: "usd", amount: 100 }], + options: [{ value: "large" }, { value: "green" }], + }, + { + title: "Test variant 2", + inventory_quantity: 10, + prices: [{ currency_code: "usd", amount: 100 }], + options: [{ value: "large" }, { value: "green" }], + }, + ], + }, + { headers: { "x-medusa-access-token": "test_token" } } + ) + + expect(response.status).toEqual(200) + + const variantIds = response.data.product.variants.map( + (v: { id: string }) => v.id + ) + + const variantInventoryService = medusaContainer.resolve( + "productVariantInventoryService" + ) + const inventory = await variantInventoryService.listByVariant(variantIds) + + expect(inventory).toHaveLength(2) + expect(inventory).toContainEqual( + expect.objectContaining({ + variant_id: variantIds[0], + required_quantity: 1, + }) + ) + expect(inventory).toContainEqual( + expect.objectContaining({ + variant_id: variantIds[1], + required_quantity: 1, + }) + ) + }) + }) + + describe("POST /admin/products/:id", () => { + const toUpdateWithSalesChannels = "to-update-with-sales-channels" + const toUpdateWithVariants = "to-update-with-variants" + const toUpdate = "to-update" + + beforeEach(async () => { + await productSeeder(dbConnection) + await adminSeeder(dbConnection) + await createDefaultRuleTypes(medusaContainer) + + await simpleSalesChannelFactory(dbConnection, { + name: "Default channel", + id: "default-channel", + is_default: true, + }) + + await simpleSalesChannelFactory(dbConnection, { + name: "Channel 3", + id: "channel-3", + is_default: true, + }) + + await simpleProductFactory(dbConnection, { + title: "To update product", + id: toUpdate, + }) + + await simpleProductFactory(dbConnection, { + title: "To update product with channels", + id: toUpdateWithSalesChannels, + sales_channels: [ + { name: "channel 1", id: "channel-1" }, + { name: "channel 2", id: "channel-2" }, + ], + }) + + await simpleSalesChannelFactory(dbConnection, { + name: "To be added", + id: "to-be-added", + }) + + await simpleProductFactory(dbConnection, { + title: "To update product with variants", + id: toUpdateWithVariants, + variants: [ + { + id: "variant-1", + title: "Variant 1", + }, + { + id: "variant-2", + title: "Variant 2", + }, + ], + }) + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should do a basic product update", async () => { + const api = useApi()! as AxiosInstance + + const payload = { + title: "New title", + description: "test-product-description", + } + + const response = await api + .post(`/admin/products/${toUpdate}`, payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(response?.status).toEqual(200) + expect(response?.data.product).toEqual( + expect.objectContaining({ + id: toUpdate, + title: "New title", + description: "test-product-description", + }) + ) + }) + + it("should update product and also update a variant and create a variant", async () => { + const api = useApi()! as AxiosInstance + + const payload = { + title: "New title", + description: "test-product-description", + variants: [ + { + id: "variant-1", + title: "Variant 1 updated", + }, + { + title: "Variant 3", + }, + ], + } + + const response = await api + .post(`/admin/products/${toUpdateWithVariants}`, payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + expect(response?.status).toEqual(200) + expect(response?.data.product).toEqual( + expect.objectContaining({ + id: toUpdateWithVariants, + title: "New title", + description: "test-product-description", + variants: expect.arrayContaining([ + expect.objectContaining({ + id: "variant-1", + title: "Variant 1 updated", + }), + expect.objectContaining({ + title: "Variant 3", + }), + ]), + }) + ) + }) + + it("should update product's sales channels", async () => { + const api = useApi()! as AxiosInstance + + const payload = { + title: "New title", + description: "test-product-description", + sales_channels: [{ id: "channel-2" }, { id: "channel-3" }], + } + + const response = await api + .post( + `/admin/products/${toUpdateWithSalesChannels}?expand=sales_channels`, + payload, + adminHeaders + ) + .catch((err) => { + console.log(err) + }) + + expect(response?.status).toEqual(200) + expect(response?.data.product).toEqual( + expect.objectContaining({ + id: toUpdateWithSalesChannels, + sales_channels: [ + expect.objectContaining({ id: "channel-2" }), + expect.objectContaining({ id: "channel-3" }), + ], + }) + ) + }) + + it("should update inventory when variants are updated", async () => { + const api = useApi()! as AxiosInstance + + const variantInventoryService = medusaContainer.resolve( + "productVariantInventoryService" + ) + + const payload = { + title: "New title", + description: "test-product-description", + variants: [ + { + id: "variant-1", + title: "Variant 1 updated", + }, + { + title: "Variant 3", + }, + ], + } + + const response = await api + .post(`/admin/products/${toUpdateWithVariants}`, payload, adminHeaders) + .catch((err) => { + console.log(err) + }) + + let inventory = await variantInventoryService.listInventoryItemsByVariant( + "variant-2" + ) + + expect(response?.status).toEqual(200) + expect(response?.data.product).toEqual( + expect.objectContaining({ + id: toUpdateWithVariants, + title: "New title", + description: "test-product-description", + variants: expect.arrayContaining([ + expect.objectContaining({ + id: "variant-1", + title: "Variant 1 updated", + }), + expect.objectContaining({ + title: "Variant 3", + }), + ]), + }) + ) + + expect(inventory).toEqual([]) // no inventory items for removed variant + + inventory = await variantInventoryService.listInventoryItemsByVariant( + response?.data.product.variants.find((v) => v.title === "Variant 3").id + ) + + expect(inventory).toEqual([ + expect.objectContaining({ id: expect.any(String) }), + ]) + }) + }) +}) diff --git a/integration-tests/modules/__tests__/product/admin/update-product-variant.spec.ts b/integration-tests/modules/__tests__/product/admin/update-product-variant.spec.ts index 755df923ef..70827bb4ce 100644 --- a/integration-tests/modules/__tests__/product/admin/update-product-variant.spec.ts +++ b/integration-tests/modules/__tests__/product/admin/update-product-variant.spec.ts @@ -1,17 +1,16 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { - simpleProductFactory, - simpleRegionFactory, -} from "../../../../factories" +import {initDb, useDb} from "../../../../environment-helpers/use-db" +import {simpleProductFactory, simpleRegionFactory,} from "../../../../factories" -import { AxiosInstance } from "axios" +import {AxiosInstance} from "axios" import adminSeeder from "../../../../helpers/admin-seeder" -import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" -import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" -import { getContainer } from "../../../../environment-helpers/use-container" +import { + createDefaultRuleTypes +} from "../../../helpers/create-default-rule-types" +import {createVariantPriceSet} from "../../../helpers/create-variant-price-set" +import {getContainer} from "../../../../environment-helpers/use-container" import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import {startBootstrapApp} from "../../../../environment-helpers/bootstrap-app" +import {useApi} from "../../../../environment-helpers/use-api" jest.setTimeout(50000) @@ -25,6 +24,10 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } +// TODO SEE to use new test runner medusaIntegrationTestRunner({ +// env, +// testSuite: ({ dbConnection, getContainer, api }) => {}) + describe.skip("POST /admin/products/:id/variants/:id", () => { let dbConnection let appContainer diff --git a/integration-tests/modules/__tests__/product/admin/update-product.spec.ts b/integration-tests/modules/__tests__/product/admin/update-product.spec.ts index 841dac93b8..8d86155a13 100644 --- a/integration-tests/modules/__tests__/product/admin/update-product.spec.ts +++ b/integration-tests/modules/__tests__/product/admin/update-product.spec.ts @@ -23,6 +23,10 @@ const env = { MEDUSA_FF_MEDUSA_V2: true, } +// TODO SEE to use new test runner medusaIntegrationTestRunner({ +// env, +// testSuite: ({ dbConnection, getContainer, api }) => {}) + describe.skip("POST /admin/products/:id", () => { let dbConnection let appContainer diff --git a/integration-tests/modules/__tests__/promotion/admin/create-campaign.spec.ts b/integration-tests/modules/__tests__/promotion/admin/create-campaign.spec.ts index e1ce4200e0..dd6ce50958 100644 --- a/integration-tests/modules/__tests__/promotion/admin/create-campaign.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/create-campaign.spec.ts @@ -1,12 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { IPromotionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -15,184 +10,169 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/campaigns", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/campaigns", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should throw an error if required params are not passed", async () => { - const api = useApi() as any - const { response } = await api - .post(`/admin/campaigns`, {}, adminHeaders) - .catch((e) => e) - - expect(response.status).toEqual(400) - expect(response.data.message).toEqual( - "name must be a string, name should not be empty" - ) - }) - - it("should create a campaign successfully", async () => { - const createdPromotion = await promotionModuleService.create({ - code: "TEST", - type: "standard", - }) - - const api = useApi() as any - const response = await api.post( - `/admin/campaigns`, - { - name: "test", - campaign_identifier: "test", - starts_at: new Date("01/01/2024").toISOString(), - ends_at: new Date("01/01/2029").toISOString(), - promotions: [{ id: createdPromotion.id }], - budget: { - limit: 1000, - type: "usage", - }, - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.campaign).toEqual( - expect.objectContaining({ - id: expect.any(String), - name: "test", - campaign_identifier: "test", - starts_at: expect.any(String), - ends_at: expect.any(String), - budget: expect.objectContaining({ - limit: 1000, - type: "usage", - }), - promotions: [ - expect.objectContaining({ - id: createdPromotion.id, - }), - ], + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) }) - ) - }) - it("should create 3 campaigns in parallel and have the context passed as argument when calling createCampaigns with different transactionId", async () => { - const parallelPromotion = await promotionModuleService.create({ - code: "PARALLEL", - type: "standard", - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - const spyCreateCampaigns = jest.spyOn( - promotionModuleService.constructor.prototype, - "createCampaigns" - ) + it("should throw an error if required params are not passed", async () => { + const { response } = await api + .post(`/admin/campaigns`, {}, adminHeaders) + .catch((e) => e) - const api = useApi() as any + expect(response.status).toEqual(400) + expect(response.data.message).toEqual( + "name must be a string, name should not be empty" + ) + }) - const a = async () => { - return await api.post( - `/admin/campaigns`, - { - name: "camp_1", - campaign_identifier: "camp_1", - starts_at: new Date("01/01/2024").toISOString(), - ends_at: new Date("01/02/2024").toISOString(), - promotions: [{ id: parallelPromotion.id }], - budget: { - limit: 1000, - type: "usage", + it("should create a campaign successfully", async () => { + const createdPromotion = await promotionModuleService.create({ + code: "TEST", + type: "standard", + }) + + const response = await api.post( + `/admin/campaigns`, + { + name: "test", + campaign_identifier: "test", + starts_at: new Date("01/01/2024").toISOString(), + ends_at: new Date("01/01/2029").toISOString(), + promotions: [{ id: createdPromotion.id }], + budget: { + limit: 1000, + type: "usage", + }, }, - }, - adminHeaders - ) - } + adminHeaders + ) - const b = async () => { - return await api.post( - `/admin/campaigns`, - { - name: "camp_2", - campaign_identifier: "camp_2", - starts_at: new Date("01/02/2024").toISOString(), - ends_at: new Date("01/03/2029").toISOString(), - promotions: [{ id: parallelPromotion.id }], - budget: { - limit: 500, - type: "usage", - }, - }, - adminHeaders - ) - } + expect(response.status).toEqual(200) + expect(response.data.campaign).toEqual( + expect.objectContaining({ + id: expect.any(String), + name: "test", + campaign_identifier: "test", + starts_at: expect.any(String), + ends_at: expect.any(String), + budget: expect.objectContaining({ + limit: 1000, + type: "usage", + }), + promotions: [ + expect.objectContaining({ + id: createdPromotion.id, + }), + ], + }) + ) + }) - const c = async () => { - return await api.post( - `/admin/campaigns`, - { - name: "camp_3", - campaign_identifier: "camp_3", - starts_at: new Date("01/03/2024").toISOString(), - ends_at: new Date("01/04/2029").toISOString(), - promotions: [{ id: parallelPromotion.id }], - budget: { - limit: 250, - type: "usage", - }, - }, - { - headers: { - ...adminHeaders.headers, - "x-request-id": "my-custom-request-id", - }, + it("should create 3 campaigns in parallel and have the context passed as argument when calling createCampaigns with different transactionId", async () => { + const parallelPromotion = await promotionModuleService.create({ + code: "PARALLEL", + type: "standard", + }) + + const spyCreateCampaigns = jest.spyOn( + promotionModuleService.constructor.prototype, + "createCampaigns" + ) + + const a = async () => { + return await api.post( + `/admin/campaigns`, + { + name: "camp_1", + campaign_identifier: "camp_1", + starts_at: new Date("01/01/2024").toISOString(), + ends_at: new Date("01/02/2024").toISOString(), + promotions: [{ id: parallelPromotion.id }], + budget: { + limit: 1000, + type: "usage", + }, + }, + adminHeaders + ) } - ) - } - await Promise.all([a(), b(), c()]) + const b = async () => { + return await api.post( + `/admin/campaigns`, + { + name: "camp_2", + campaign_identifier: "camp_2", + starts_at: new Date("01/02/2024").toISOString(), + ends_at: new Date("01/03/2029").toISOString(), + promotions: [{ id: parallelPromotion.id }], + budget: { + limit: 500, + type: "usage", + }, + }, + adminHeaders + ) + } - expect(spyCreateCampaigns).toHaveBeenCalledTimes(3) - expect(spyCreateCampaigns.mock.calls[0][1].__type).toBe("MedusaContext") + const c = async () => { + return await api.post( + `/admin/campaigns`, + { + name: "camp_3", + campaign_identifier: "camp_3", + starts_at: new Date("01/03/2024").toISOString(), + ends_at: new Date("01/04/2029").toISOString(), + promotions: [{ id: parallelPromotion.id }], + budget: { + limit: 250, + type: "usage", + }, + }, + { + headers: { + ...adminHeaders.headers, + "x-request-id": "my-custom-request-id", + }, + } + ) + } - const distinctTransactionId = [ - ...new Set( - spyCreateCampaigns.mock.calls.map((call) => call[1].transactionId) - ), - ] - expect(distinctTransactionId).toHaveLength(3) + await Promise.all([a(), b(), c()]) - const distinctRequestId = [ - ...new Set( - spyCreateCampaigns.mock.calls.map((call) => call[1].requestId) - ), - ] + expect(spyCreateCampaigns).toHaveBeenCalledTimes(3) + expect(spyCreateCampaigns.mock.calls[0][1].__type).toBe("MedusaContext") - expect(distinctRequestId).toHaveLength(3) - expect(distinctRequestId).toContain("my-custom-request-id") - }) + const distinctTransactionId = [ + ...new Set( + spyCreateCampaigns.mock.calls.map((call) => call[1].transactionId) + ), + ] + expect(distinctTransactionId).toHaveLength(3) + + const distinctRequestId = [ + ...new Set( + spyCreateCampaigns.mock.calls.map((call) => call[1].requestId) + ), + ] + + expect(distinctRequestId).toHaveLength(3) + expect(distinctRequestId).toContain("my-custom-request-id") + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/create-promotion.spec.ts b/integration-tests/modules/__tests__/promotion/admin/create-promotion.spec.ts index b105e08c9f..e3c01b4d18 100644 --- a/integration-tests/modules/__tests__/promotion/admin/create-promotion.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/create-promotion.spec.ts @@ -1,13 +1,8 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { IPromotionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { PromotionType } from "@medusajs/utils" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,158 +11,71 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/promotions", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/promotions", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should throw an error if required params are not passed", async () => { - const api = useApi() as any - const { response } = await api - .post( - `/admin/promotions`, - { - type: PromotionType.STANDARD, - }, - adminHeaders - ) - .catch((e) => e) - - expect(response.status).toEqual(400) - expect(response.data.message).toEqual( - "code must be a string, code should not be empty, application_method should not be empty" - ) - }) - - it("should create a standard promotion successfully", async () => { - const api = useApi() as any - const response = await api.post( - `/admin/promotions`, - { - code: "TEST", - type: PromotionType.STANDARD, - is_automatic: true, - campaign: { - name: "test", - campaign_identifier: "test-1", - budget: { - type: "usage", - limit: 100, - }, - }, - application_method: { - target_type: "items", - type: "fixed", - allocation: "each", - value: "100", - max_quantity: 100, - target_rules: [ - { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], - }, - ], - }, - rules: [ - { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], - }, - ], - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.promotion).toEqual( - expect.objectContaining({ - id: expect.any(String), - code: "TEST", - type: "standard", - is_automatic: true, - campaign: expect.objectContaining({ - name: "test", - campaign_identifier: "test-1", - budget: expect.objectContaining({ - type: "usage", - limit: 100, - }), - }), - application_method: expect.objectContaining({ - value: 100, - max_quantity: 100, - type: "fixed", - target_type: "items", - allocation: "each", - target_rules: [ - expect.objectContaining({ - operator: "eq", - attribute: "test.test", - values: expect.arrayContaining([ - expect.objectContaining({ value: "test1" }), - expect.objectContaining({ value: "test2" }), - ]), - }), - ], - }), - rules: [ - expect.objectContaining({ - operator: "eq", - attribute: "test.test", - values: expect.arrayContaining([ - expect.objectContaining({ value: "test1" }), - expect.objectContaining({ value: "test2" }), - ]), - }), - ], + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) }) - ) - }) - it("should throw an error if buy_rules params are not passed", async () => { - const api = useApi() as any - const { response } = await api - .post( - `/admin/promotions`, - { - code: "TEST", - type: PromotionType.BUYGET, - is_automatic: true, - application_method: { - target_type: "items", - type: "fixed", - allocation: "each", - value: "100", - max_quantity: 100, - target_rules: [ + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should throw an error if required params are not passed", async () => { + const { response } = await api + .post( + `/admin/promotions`, + { + type: PromotionType.STANDARD, + }, + adminHeaders + ) + .catch((e) => e) + + expect(response.status).toEqual(400) + expect(response.data.message).toEqual( + "code must be a string, code should not be empty, application_method should not be empty" + ) + }) + + it("should create a standard promotion successfully", async () => { + const response = await api.post( + `/admin/promotions`, + { + code: "TEST", + type: PromotionType.STANDARD, + is_automatic: true, + campaign: { + name: "test", + campaign_identifier: "test-1", + budget: { + type: "usage", + limit: 100, + }, + }, + application_method: { + target_type: "items", + type: "fixed", + allocation: "each", + value: "100", + max_quantity: 100, + target_rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], + }, + rules: [ { attribute: "test.test", operator: "eq", @@ -175,40 +83,174 @@ describe("POST /admin/promotions", () => { }, ], }, - rules: [ + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.promotion).toEqual( + expect.objectContaining({ + id: expect.any(String), + code: "TEST", + type: "standard", + is_automatic: true, + campaign: expect.objectContaining({ + name: "test", + campaign_identifier: "test-1", + budget: expect.objectContaining({ + type: "usage", + limit: 100, + }), + }), + application_method: expect.objectContaining({ + value: 100, + max_quantity: 100, + type: "fixed", + target_type: "items", + allocation: "each", + target_rules: [ + expect.objectContaining({ + operator: "eq", + attribute: "test.test", + values: expect.arrayContaining([ + expect.objectContaining({ value: "test1" }), + expect.objectContaining({ value: "test2" }), + ]), + }), + ], + }), + rules: [ + expect.objectContaining({ + operator: "eq", + attribute: "test.test", + values: expect.arrayContaining([ + expect.objectContaining({ value: "test1" }), + expect.objectContaining({ value: "test2" }), + ]), + }), + ], + }) + ) + }) + + it("should throw an error if buy_rules params are not passed", async () => { + const { response } = await api + .post( + `/admin/promotions`, { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], + code: "TEST", + type: PromotionType.BUYGET, + is_automatic: true, + application_method: { + target_type: "items", + type: "fixed", + allocation: "each", + value: "100", + max_quantity: 100, + target_rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], + }, + rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], }, - ], - }, - adminHeaders - ) - .catch((e) => e) + adminHeaders + ) + .catch((e) => e) - expect(response.status).toEqual(400) - expect(response.data.message).toEqual( - "Buy rules are required for buyget promotion type" - ) - }) + expect(response.status).toEqual(400) + expect(response.data.message).toEqual( + "Buy rules are required for buyget promotion type" + ) + }) - it("should throw an error if buy_rules params are not passed", async () => { - const api = useApi() as any - const { response } = await api - .post( - `/admin/promotions`, - { - code: "TEST", - type: PromotionType.BUYGET, - is_automatic: true, - application_method: { - target_type: "items", - type: "fixed", - allocation: "each", - value: "100", - max_quantity: 100, - buy_rules: [ + it("should throw an error if buy_rules params are not passed", async () => { + const { response } = await api + .post( + `/admin/promotions`, + { + code: "TEST", + type: PromotionType.BUYGET, + is_automatic: true, + application_method: { + target_type: "items", + type: "fixed", + allocation: "each", + value: "100", + max_quantity: 100, + buy_rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], + }, + rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], + }, + adminHeaders + ) + .catch((e) => e) + + expect(response.status).toEqual(400) + expect(response.data.message).toEqual( + "Target rules are required for buyget promotion type" + ) + }) + + it("should create a buyget promotion successfully", async () => { + const response = await api.post( + `/admin/promotions`, + { + code: "TEST", + type: PromotionType.BUYGET, + is_automatic: true, + campaign: { + name: "test", + campaign_identifier: "test-1", + budget: { + type: "usage", + limit: 100, + }, + }, + application_method: { + target_type: "items", + type: "fixed", + allocation: "each", + value: "100", + max_quantity: 100, + apply_to_quantity: 1, + buy_rules_min_quantity: 1, + target_rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], + buy_rules: [ + { + attribute: "test.test", + operator: "eq", + values: ["test1", "test2"], + }, + ], + }, + rules: [ { attribute: "test.test", operator: "eq", @@ -216,129 +258,66 @@ describe("POST /admin/promotions", () => { }, ], }, - rules: [ - { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], - }, - ], - }, - adminHeaders - ) - .catch((e) => e) + adminHeaders + ) - expect(response.status).toEqual(400) - expect(response.data.message).toEqual( - "Target rules are required for buyget promotion type" - ) - }) - - it("should create a buyget promotion successfully", async () => { - const api = useApi() as any - const response = await api.post( - `/admin/promotions`, - { - code: "TEST", - type: PromotionType.BUYGET, - is_automatic: true, - campaign: { - name: "test", - campaign_identifier: "test-1", - budget: { - type: "usage", - limit: 100, - }, - }, - application_method: { - target_type: "items", - type: "fixed", - allocation: "each", - value: "100", - max_quantity: 100, - apply_to_quantity: 1, - buy_rules_min_quantity: 1, - target_rules: [ - { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], - }, - ], - buy_rules: [ - { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], - }, - ], - }, - rules: [ - { - attribute: "test.test", - operator: "eq", - values: ["test1", "test2"], - }, - ], - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.promotion).toEqual( - expect.objectContaining({ - id: expect.any(String), - code: "TEST", - type: "buyget", - is_automatic: true, - campaign: expect.objectContaining({ - name: "test", - campaign_identifier: "test-1", - budget: expect.objectContaining({ - type: "usage", - limit: 100, - }), - }), - application_method: expect.objectContaining({ - value: 100, - max_quantity: 100, - type: "fixed", - target_type: "items", - allocation: "each", - apply_to_quantity: 1, - buy_rules_min_quantity: 1, - target_rules: [ - expect.objectContaining({ - operator: "eq", - attribute: "test.test", - values: expect.arrayContaining([ - expect.objectContaining({ value: "test1" }), - expect.objectContaining({ value: "test2" }), - ]), - }), - ], - buy_rules: [ - expect.objectContaining({ - operator: "eq", - attribute: "test.test", - values: expect.arrayContaining([ - expect.objectContaining({ value: "test1" }), - expect.objectContaining({ value: "test2" }), - ]), - }), - ], - }), - rules: [ + expect(response.status).toEqual(200) + expect(response.data.promotion).toEqual( expect.objectContaining({ - operator: "eq", - attribute: "test.test", - values: expect.arrayContaining([ - expect.objectContaining({ value: "test1" }), - expect.objectContaining({ value: "test2" }), - ]), - }), - ], + id: expect.any(String), + code: "TEST", + type: "buyget", + is_automatic: true, + campaign: expect.objectContaining({ + name: "test", + campaign_identifier: "test-1", + budget: expect.objectContaining({ + type: "usage", + limit: 100, + }), + }), + application_method: expect.objectContaining({ + value: 100, + max_quantity: 100, + type: "fixed", + target_type: "items", + allocation: "each", + apply_to_quantity: 1, + buy_rules_min_quantity: 1, + target_rules: [ + expect.objectContaining({ + operator: "eq", + attribute: "test.test", + values: expect.arrayContaining([ + expect.objectContaining({ value: "test1" }), + expect.objectContaining({ value: "test2" }), + ]), + }), + ], + buy_rules: [ + expect.objectContaining({ + operator: "eq", + attribute: "test.test", + values: expect.arrayContaining([ + expect.objectContaining({ value: "test1" }), + expect.objectContaining({ value: "test2" }), + ]), + }), + ], + }), + rules: [ + expect.objectContaining({ + operator: "eq", + attribute: "test.test", + values: expect.arrayContaining([ + expect.objectContaining({ value: "test1" }), + expect.objectContaining({ value: "test2" }), + ]), + }), + ], + }) + ) }) - ) - }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/delete-campaign.spec.ts b/integration-tests/modules/__tests__/promotion/admin/delete-campaign.spec.ts index 055b223b58..ab701aecce 100644 --- a/integration-tests/modules/__tests__/promotion/admin/delete-campaign.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/delete-campaign.spec.ts @@ -1,12 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { IPromotionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -15,59 +10,47 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("DELETE /admin/campaigns/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /admin/campaigns/:id", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should delete campaign successfully", async () => { + const [createdCampaign] = await promotionModuleService.createCampaigns([ + { + name: "test", + campaign_identifier: "test", + starts_at: new Date("01/01/2024"), + ends_at: new Date("01/01/2025"), + }, + ]) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const deleteRes = await api.delete( + `/admin/campaigns/${createdCampaign.id}`, + adminHeaders + ) - it("should delete campaign successfully", async () => { - const [createdCampaign] = await promotionModuleService.createCampaigns([ - { - name: "test", - campaign_identifier: "test", - starts_at: new Date("01/01/2024"), - ends_at: new Date("01/01/2025"), - }, - ]) + expect(deleteRes.status).toEqual(200) - const api = useApi() as any - const deleteRes = await api.delete( - `/admin/campaigns/${createdCampaign.id}`, - adminHeaders - ) + const campaigns = await promotionModuleService.listCampaigns({ + id: [createdCampaign.id], + }) - expect(deleteRes.status).toEqual(200) - - const campaigns = await promotionModuleService.listCampaigns({ - id: [createdCampaign.id], + expect(campaigns.length).toEqual(0) + }) }) - - expect(campaigns.length).toEqual(0) - }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/delete-promotion.spec.ts b/integration-tests/modules/__tests__/promotion/admin/delete-promotion.spec.ts index 882ea3c3f7..24b2a3c8ba 100644 --- a/integration-tests/modules/__tests__/promotion/admin/delete-promotion.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/delete-promotion.spec.ts @@ -1,12 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { IPromotionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -15,60 +10,48 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("DELETE /admin/promotions/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /admin/promotions/:id", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should delete promotion successfully", async () => { + const createdPromotion = await promotionModuleService.create({ + code: "TEST", + type: "standard", + application_method: { + type: "fixed", + target_type: "order", + value: "100", + }, + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const deleteRes = await api.delete( + `/admin/promotions/${createdPromotion.id}`, + adminHeaders + ) - it("should delete promotion successfully", async () => { - const createdPromotion = await promotionModuleService.create({ - code: "TEST", - type: "standard", - application_method: { - type: "fixed", - target_type: "order", - value: "100", - }, + expect(deleteRes.status).toEqual(200) + + const promotions = await promotionModuleService.list({ + id: [createdPromotion.id], + }) + + expect(promotions.length).toEqual(0) + }) }) - - const api = useApi() as any - const deleteRes = await api.delete( - `/admin/promotions/${createdPromotion.id}`, - adminHeaders - ) - - expect(deleteRes.status).toEqual(200) - - const promotions = await promotionModuleService.list({ - id: [createdPromotion.id], - }) - - expect(promotions.length).toEqual(0) - }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/list-campaigns.spec.ts b/integration-tests/modules/__tests__/promotion/admin/list-campaigns.spec.ts index 61501f6984..06a69b75ab 100644 --- a/integration-tests/modules/__tests__/promotion/admin/list-campaigns.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/list-campaigns.spec.ts @@ -1,13 +1,8 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IPromotionModuleService } from "@medusajs/types" import { CampaignBudgetType } from "@medusajs/utils" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" import { createAdminUser } from "../../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -47,140 +42,127 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/campaigns", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/campaigns", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + await promotionModuleService.createCampaigns(campaignsData) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - await promotionModuleService.createCampaigns(campaignsData) - }) + it("should get all campaigns and its count", async () => { + const response = await api.get(`/admin/campaigns`, adminHeaders) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(2) + expect(response.data.campaigns).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + name: "campaign 1", + description: "test description", + currency: "USD", + campaign_identifier: "test-1", + starts_at: expect.any(String), + ends_at: expect.any(String), + budget: { + id: expect.any(String), + campaign: expect.any(Object), + type: "spend", + limit: 1000, + used: 0, + raw_limit: { + precision: 20, + value: "1000", + }, + raw_used: { + precision: 20, + value: "0", + }, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }), + expect.objectContaining({ + id: expect.any(String), + name: "campaign 2", + description: "test description", + currency: "USD", + campaign_identifier: "test-2", + starts_at: expect.any(String), + ends_at: expect.any(String), + budget: { + id: expect.any(String), + campaign: expect.any(Object), + type: "usage", + limit: 1000, + used: 0, + raw_limit: { + precision: 20, + value: "1000", + }, + raw_used: { + precision: 20, + value: "0", + }, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }), + ]) + ) + }) - it("should get all campaigns and its count", async () => { - const api = useApi() as any - const response = await api.get(`/admin/campaigns`, adminHeaders) + it("should get all campaigns and its count filtered", async () => { + const response = await api.get( + `/admin/campaigns?fields=name,created_at,budget.id`, + adminHeaders + ) - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(2) - expect(response.data.campaigns).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(String), - name: "campaign 1", - description: "test description", - currency: "USD", - campaign_identifier: "test-1", - starts_at: expect.any(String), - ends_at: expect.any(String), - budget: { - id: expect.any(String), - campaign: expect.any(Object), - type: "spend", - limit: 1000, - used: 0, - raw_limit: { - precision: 20, - value: "1000", + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(2) + expect(response.data.campaigns).toEqual( + expect.arrayContaining([ + { + id: expect.any(String), + name: "campaign 1", + created_at: expect.any(String), + budget: { + id: expect.any(String), + campaign: expect.any(Object), + }, }, - raw_used: { - precision: 20, - value: "0", + { + id: expect.any(String), + name: "campaign 2", + created_at: expect.any(String), + budget: { + id: expect.any(String), + campaign: expect.any(Object), + }, }, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }), - expect.objectContaining({ - id: expect.any(String), - name: "campaign 2", - description: "test description", - currency: "USD", - campaign_identifier: "test-2", - starts_at: expect.any(String), - ends_at: expect.any(String), - budget: { - id: expect.any(String), - campaign: expect.any(Object), - type: "usage", - limit: 1000, - used: 0, - raw_limit: { - precision: 20, - value: "1000", - }, - raw_used: { - precision: 20, - value: "0", - }, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }), - ]) - ) - }) - - it("should get all campaigns and its count filtered", async () => { - const api = useApi() as any - const response = await api.get( - `/admin/campaigns?fields=name,created_at,budget.id`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(2) - expect(response.data.campaigns).toEqual( - expect.arrayContaining([ - { - id: expect.any(String), - name: "campaign 1", - created_at: expect.any(String), - budget: { - id: expect.any(String), - campaign: expect.any(Object), - }, - }, - { - id: expect.any(String), - name: "campaign 2", - created_at: expect.any(String), - budget: { - id: expect.any(String), - campaign: expect.any(Object), - }, - }, - ]) - ) - }) + ]) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/list-promotions.spec.ts b/integration-tests/modules/__tests__/promotion/admin/list-promotions.spec.ts index 6c2ac133ff..baab7091e0 100644 --- a/integration-tests/modules/__tests__/promotion/admin/list-promotions.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/list-promotions.spec.ts @@ -1,13 +1,8 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { IPromotionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { PromotionType } from "@medusajs/utils" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,110 +11,97 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/promotions", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/promotions", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should get all promotions and its count", async () => { + await promotionModuleService.create([ + { + code: "TEST", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "order", + value: "100", + }, + }, + ]) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.get(`/admin/promotions`, adminHeaders) - it("should get all promotions and its count", async () => { - await promotionModuleService.create([ - { - code: "TEST", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "order", - value: "100", - }, - }, - ]) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.promotions).toEqual([ + expect.objectContaining({ + id: expect.any(String), + code: "TEST", + campaign: null, + is_automatic: false, + type: "standard", + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + application_method: expect.objectContaining({ + id: expect.any(String), + value: 100, + type: "fixed", + target_type: "order", + allocation: null, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }), + }), + ]) + }) - const api = useApi() as any - const response = await api.get(`/admin/promotions`, adminHeaders) + it("should get all promotions and its count filtered", async () => { + const [createdPromotion] = await promotionModuleService.create([ + { + code: "TEST", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "order", + value: "100", + }, + }, + ]) - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.promotions).toEqual([ - expect.objectContaining({ - id: expect.any(String), - code: "TEST", - campaign: null, - is_automatic: false, - type: "standard", - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - application_method: expect.objectContaining({ - id: expect.any(String), - value: 100, - type: "fixed", - target_type: "order", - allocation: null, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }), - }), - ]) - }) + const response = await api.get( + `/admin/promotions?fields=code,created_at,application_method.id`, + adminHeaders + ) - it("should get all promotions and its count filtered", async () => { - const [createdPromotion] = await promotionModuleService.create([ - { - code: "TEST", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "order", - value: "100", - }, - }, - ]) - - const api = useApi() as any - const response = await api.get( - `/admin/promotions?fields=code,created_at,application_method.id`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.count).toEqual(1) - expect(response.data.promotions).toEqual([ - { - id: expect.any(String), - code: "TEST", - created_at: expect.any(String), - application_method: { - id: expect.any(String), - promotion: expect.any(Object), - }, - }, - ]) - }) + expect(response.status).toEqual(200) + expect(response.data.count).toEqual(1) + expect(response.data.promotions).toEqual([ + { + id: expect.any(String), + code: "TEST", + created_at: expect.any(String), + application_method: { + id: expect.any(String), + promotion: expect.any(Object), + }, + }, + ]) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/retrieve-campaign.spec.ts b/integration-tests/modules/__tests__/promotion/admin/retrieve-campaign.spec.ts index 417c2d7d3e..2be28ab928 100644 --- a/integration-tests/modules/__tests__/promotion/admin/retrieve-campaign.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/retrieve-campaign.spec.ts @@ -1,13 +1,8 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IPromotionModuleService } from "@medusajs/types" import { CampaignBudgetType } from "@medusajs/utils" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" import { createAdminUser } from "../../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -30,112 +25,94 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/campaigns", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/campaigns", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should throw an error if id does not exist", async () => { + const { response } = await api + .get(`/admin/campaigns/does-not-exist`, adminHeaders) + .catch((e) => e) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + expect(response.status).toEqual(404) + expect(response.data.message).toEqual( + "Campaign with id: does-not-exist was not found" + ) + }) - let campaigns + it("should get the requested campaign", async () => { + const createdCampaign = await promotionModuleService.createCampaigns( + campaignData + ) - beforeEach(async () => {}) + const response = await api.get( + `/admin/campaigns/${createdCampaign.id}`, + adminHeaders + ) - it("should throw an error if id does not exist", async () => { - const api = useApi() as any - const { response } = await api - .get(`/admin/campaigns/does-not-exist`, adminHeaders) - .catch((e) => e) + expect(response.status).toEqual(200) + expect(response.data.campaign).toEqual({ + id: expect.any(String), + name: "campaign 1", + description: "test description", + currency: "USD", + campaign_identifier: "test-1", + starts_at: expect.any(String), + ends_at: expect.any(String), + budget: { + id: expect.any(String), + campaign: expect.any(Object), + type: "spend", + limit: 1000, + raw_limit: { + precision: 20, + value: "1000", + }, + raw_used: { + precision: 20, + value: "0", + }, + used: 0, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }) + }) - expect(response.status).toEqual(404) - expect(response.data.message).toEqual( - "Campaign with id: does-not-exist was not found" - ) - }) + it("should get the requested campaign with filtered fields and relations", async () => { + const createdCampaign = await promotionModuleService.createCampaigns( + campaignData + ) - it("should get the requested campaign", async () => { - const createdCampaign = await promotionModuleService.createCampaigns( - campaignData - ) + const response = await api.get( + `/admin/campaigns/${createdCampaign.id}?fields=name&expand=`, + adminHeaders + ) - const api = useApi() as any - const response = await api.get( - `/admin/campaigns/${createdCampaign.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.campaign).toEqual({ - id: expect.any(String), - name: "campaign 1", - description: "test description", - currency: "USD", - campaign_identifier: "test-1", - starts_at: expect.any(String), - ends_at: expect.any(String), - budget: { - id: expect.any(String), - campaign: expect.any(Object), - type: "spend", - limit: 1000, - raw_limit: { - precision: 20, - value: "1000", - }, - raw_used: { - precision: 20, - value: "0", - }, - used: 0, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, + expect(response.status).toEqual(200) + expect(response.data.campaign).toEqual({ + id: expect.any(String), + name: "campaign 1", + }) + }) }) - }) - - it("should get the requested campaign with filtered fields and relations", async () => { - const createdCampaign = await promotionModuleService.createCampaigns( - campaignData - ) - - const api = useApi() as any - const response = await api.get( - `/admin/campaigns/${createdCampaign.id}?fields=name&expand=`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.campaign).toEqual({ - id: expect.any(String), - name: "campaign 1", - }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/retrieve-promotion.spec.ts b/integration-tests/modules/__tests__/promotion/admin/retrieve-promotion.spec.ts index 75590b6235..91241b3dfd 100644 --- a/integration-tests/modules/__tests__/promotion/admin/retrieve-promotion.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/retrieve-promotion.spec.ts @@ -1,13 +1,8 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { IPromotionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { PromotionType } from "@medusajs/utils" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,114 +11,100 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/promotions", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/promotions", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should throw an error if id does not exist", async () => { - const api = useApi() as any - const { response } = await api - .get(`/admin/promotions/does-not-exist`, adminHeaders) - .catch((e) => e) - - expect(response.status).toEqual(404) - expect(response.data.message).toEqual( - "Promotion with id: does-not-exist was not found" - ) - }) - - it("should get the requested promotion", async () => { - const createdPromotion = await promotionModuleService.create({ - code: "TEST", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "order", - value: "100", - }, - }) - - const api = useApi() as any - const response = await api.get( - `/admin/promotions/${createdPromotion.id}`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.promotion).toEqual( - expect.objectContaining({ - id: expect.any(String), - code: "TEST", - campaign: null, - is_automatic: false, - type: "standard", - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - application_method: expect.objectContaining({ - id: expect.any(String), - promotion: expect.any(Object), - value: 100, - type: "fixed", - target_type: "order", - max_quantity: 0, - allocation: null, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }), + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) }) - ) - }) - it("should get the requested promotion with filtered fields and relations", async () => { - const createdPromotion = await promotionModuleService.create({ - code: "TEST", - type: PromotionType.STANDARD, - application_method: { - type: "fixed", - target_type: "order", - value: "100", - }, + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should throw an error if id does not exist", async () => { + const { response } = await api + .get(`/admin/promotions/does-not-exist`, adminHeaders) + .catch((e) => e) + + expect(response.status).toEqual(404) + expect(response.data.message).toEqual( + "Promotion with id: does-not-exist was not found" + ) + }) + + it("should get the requested promotion", async () => { + const createdPromotion = await promotionModuleService.create({ + code: "TEST", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "order", + value: "100", + }, + }) + + const response = await api.get( + `/admin/promotions/${createdPromotion.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.promotion).toEqual( + expect.objectContaining({ + id: expect.any(String), + code: "TEST", + campaign: null, + is_automatic: false, + type: "standard", + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + application_method: expect.objectContaining({ + id: expect.any(String), + promotion: expect.any(Object), + value: 100, + type: "fixed", + target_type: "order", + max_quantity: 0, + allocation: null, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }), + }) + ) + }) + + it("should get the requested promotion with filtered fields and relations", async () => { + const createdPromotion = await promotionModuleService.create({ + code: "TEST", + type: PromotionType.STANDARD, + application_method: { + type: "fixed", + target_type: "order", + value: "100", + }, + }) + + const response = await api.get( + `/admin/promotions/${createdPromotion.id}?fields=id,code&expand=`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.promotion).toEqual({ + id: expect.any(String), + code: "TEST", + }) + }) }) - - const api = useApi() as any - const response = await api.get( - `/admin/promotions/${createdPromotion.id}?fields=id,code&expand=`, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.promotion).toEqual({ - id: expect.any(String), - code: "TEST", - }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/update-campaign.spec.ts b/integration-tests/modules/__tests__/promotion/admin/update-campaign.spec.ts index c7e1e6f132..aeb68ef360 100644 --- a/integration-tests/modules/__tests__/promotion/admin/update-campaign.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/update-campaign.spec.ts @@ -1,12 +1,7 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { IPromotionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -15,104 +10,91 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/campaigns/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/campaigns/:id", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should throw an error if id does not exist", async () => { - const api = useApi() as any - const { response } = await api - .post(`/admin/campaigns/does-not-exist`, {}, adminHeaders) - .catch((e) => e) - - expect(response.status).toEqual(404) - expect(response.data.message).toEqual( - `Campaign with id "does-not-exist" not found` - ) - }) - - it("should update a campaign successfully", async () => { - const createdPromotion = await promotionModuleService.create({ - code: "TEST", - type: "standard", - }) - - const createdPromotion2 = await promotionModuleService.create({ - code: "TEST_2", - type: "standard", - }) - - const createdCampaign = await promotionModuleService.createCampaigns({ - name: "test", - campaign_identifier: "test", - starts_at: new Date("01/01/2024").toISOString(), - ends_at: new Date("01/01/2029").toISOString(), - promotions: [{ id: createdPromotion.id }], - budget: { - limit: 1000, - type: "usage", - used: 10, - }, - }) - - const api = useApi() as any - const response = await api.post( - `/admin/campaigns/${createdCampaign.id}`, - { - name: "test-2", - campaign_identifier: "test-2", - budget: { - limit: 2000, - }, - promotions: [{ id: createdPromotion2.id }], - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.campaign).toEqual( - expect.objectContaining({ - id: expect.any(String), - name: "test-2", - campaign_identifier: "test-2", - budget: expect.objectContaining({ - limit: 2000, - type: "usage", - used: 10, - }), - promotions: [ - expect.objectContaining({ - id: createdPromotion2.id, - }), - ], + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) }) - ) - }) + + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) + + it("should throw an error if id does not exist", async () => { + const { response } = await api + .post(`/admin/campaigns/does-not-exist`, {}, adminHeaders) + .catch((e) => e) + + expect(response.status).toEqual(404) + expect(response.data.message).toEqual( + `Campaign with id "does-not-exist" not found` + ) + }) + + it("should update a campaign successfully", async () => { + const createdPromotion = await promotionModuleService.create({ + code: "TEST", + type: "standard", + }) + + const createdPromotion2 = await promotionModuleService.create({ + code: "TEST_2", + type: "standard", + }) + + const createdCampaign = await promotionModuleService.createCampaigns({ + name: "test", + campaign_identifier: "test", + starts_at: new Date("01/01/2024").toISOString(), + ends_at: new Date("01/01/2029").toISOString(), + promotions: [{ id: createdPromotion.id }], + budget: { + limit: 1000, + type: "usage", + used: 10, + }, + }) + + const response = await api.post( + `/admin/campaigns/${createdCampaign.id}`, + { + name: "test-2", + campaign_identifier: "test-2", + budget: { + limit: 2000, + }, + promotions: [{ id: createdPromotion2.id }], + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.campaign).toEqual( + expect.objectContaining({ + id: expect.any(String), + name: "test-2", + campaign_identifier: "test-2", + budget: expect.objectContaining({ + limit: 2000, + type: "usage", + used: 10, + }), + promotions: [ + expect.objectContaining({ + id: createdPromotion2.id, + }), + ], + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/promotion/admin/update-promotion.spec.ts b/integration-tests/modules/__tests__/promotion/admin/update-promotion.spec.ts index 3b3241a488..669bfe22d0 100644 --- a/integration-tests/modules/__tests__/promotion/admin/update-promotion.spec.ts +++ b/integration-tests/modules/__tests__/promotion/admin/update-promotion.spec.ts @@ -1,13 +1,8 @@ -import { initDb, useDb } from "../../../../environment-helpers/use-db" - import { IPromotionModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { PromotionType } from "@medusajs/utils" import { createAdminUser } from "../../../helpers/create-admin-user" -import { getContainer } from "../../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,177 +11,161 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/promotions/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let promotionModuleService: IPromotionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/promotions/:id", () => { + let appContainer + let promotionModuleService: IPromotionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - promotionModuleService = appContainer.resolve( - ModuleRegistrationName.PROMOTION - ) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("should throw an error if id does not exist", async () => { - const api = useApi() as any - const { response } = await api - .post( - `/admin/promotions/does-not-exist`, - { type: PromotionType.STANDARD }, - adminHeaders - ) - .catch((e) => e) - - expect(response.status).toEqual(404) - expect(response.data.message).toEqual( - `Promotion with id "does-not-exist" not found` - ) - }) - - it("should throw an error when both campaign and campaign_id params are passed", async () => { - const createdPromotion = await promotionModuleService.create({ - code: "TEST", - type: PromotionType.STANDARD, - is_automatic: true, - application_method: { - target_type: "items", - type: "fixed", - allocation: "each", - value: "100", - max_quantity: 100, - }, - }) - - const api = useApi() as any - - const { response } = await api - .post( - `/admin/promotions/${createdPromotion.id}`, - { - campaign: { - name: "test campaign", - }, - campaign_id: "test", - }, - adminHeaders - ) - .catch((e) => e) - - expect(response.status).toEqual(400) - expect(response.data.message).toContain( - `Failed XOR relation between "campaign_id" and "campaign"` - ) - }) - - it("should update a promotion successfully", async () => { - const createdPromotion = await promotionModuleService.create({ - code: "TEST", - type: PromotionType.STANDARD, - is_automatic: true, - application_method: { - target_type: "items", - type: "fixed", - allocation: "each", - value: "100", - max_quantity: 100, - }, - }) - - const api = useApi() as any - const response = await api.post( - `/admin/promotions/${createdPromotion.id}`, - { - code: "TEST_TWO", - application_method: { - value: "200", - }, - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.promotion).toEqual( - expect.objectContaining({ - id: expect.any(String), - code: "TEST_TWO", - application_method: expect.objectContaining({ - value: 200, - }), + beforeAll(async () => { + appContainer = getContainer() + promotionModuleService = appContainer.resolve( + ModuleRegistrationName.PROMOTION + ) }) - ) - }) - it("should update a buyget promotion successfully", async () => { - const createdPromotion = await promotionModuleService.create({ - code: "PROMOTION_TEST", - type: PromotionType.BUYGET, - application_method: { - type: "fixed", - target_type: "items", - allocation: "across", - value: "100", - apply_to_quantity: 1, - buy_rules_min_quantity: 1, - buy_rules: [ - { - attribute: "product_collection.id", - operator: "eq", - values: ["pcol_towel"], - }, - ], - target_rules: [ - { - attribute: "product.id", - operator: "eq", - values: "prod_mat", - }, - ], - }, - }) - - const api = useApi() as any - const response = await api.post( - `/admin/promotions/${createdPromotion.id}`, - { - code: "TEST_TWO", - application_method: { - value: "200", - buy_rules_min_quantity: 6, - }, - }, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.promotion).toEqual( - expect.objectContaining({ - id: expect.any(String), - code: "TEST_TWO", - application_method: expect.objectContaining({ - value: 200, - buy_rules_min_quantity: 6, - }), + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) }) - ) - }) + + it("should throw an error if id does not exist", async () => { + const { response } = await api + .post( + `/admin/promotions/does-not-exist`, + { type: PromotionType.STANDARD }, + adminHeaders + ) + .catch((e) => e) + + expect(response.status).toEqual(404) + expect(response.data.message).toEqual( + `Promotion with id "does-not-exist" not found` + ) + }) + + it("should throw an error when both campaign and campaign_id params are passed", async () => { + const createdPromotion = await promotionModuleService.create({ + code: "TEST", + type: PromotionType.STANDARD, + is_automatic: true, + application_method: { + target_type: "items", + type: "fixed", + allocation: "each", + value: "100", + max_quantity: 100, + }, + }) + + const { response } = await api + .post( + `/admin/promotions/${createdPromotion.id}`, + { + campaign: { + name: "test campaign", + }, + campaign_id: "test", + }, + adminHeaders + ) + .catch((e) => e) + + expect(response.status).toEqual(400) + expect(response.data.message).toContain( + `Failed XOR relation between "campaign_id" and "campaign"` + ) + }) + + it("should update a promotion successfully", async () => { + const createdPromotion = await promotionModuleService.create({ + code: "TEST", + type: PromotionType.STANDARD, + is_automatic: true, + application_method: { + target_type: "items", + type: "fixed", + allocation: "each", + value: "100", + max_quantity: 100, + }, + }) + + const response = await api.post( + `/admin/promotions/${createdPromotion.id}`, + { + code: "TEST_TWO", + application_method: { + value: "200", + }, + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.promotion).toEqual( + expect.objectContaining({ + id: expect.any(String), + code: "TEST_TWO", + application_method: expect.objectContaining({ + value: 200, + }), + }) + ) + }) + + it("should update a buyget promotion successfully", async () => { + const createdPromotion = await promotionModuleService.create({ + code: "PROMOTION_TEST", + type: PromotionType.BUYGET, + application_method: { + type: "fixed", + target_type: "items", + allocation: "across", + value: "100", + apply_to_quantity: 1, + buy_rules_min_quantity: 1, + buy_rules: [ + { + attribute: "product_collection.id", + operator: "eq", + values: ["pcol_towel"], + }, + ], + target_rules: [ + { + attribute: "product.id", + operator: "eq", + values: "prod_mat", + }, + ], + }, + }) + + const response = await api.post( + `/admin/promotions/${createdPromotion.id}`, + { + code: "TEST_TWO", + application_method: { + value: "200", + buy_rules_min_quantity: 6, + }, + }, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.promotion).toEqual( + expect.objectContaining({ + id: expect.any(String), + code: "TEST_TWO", + application_method: expect.objectContaining({ + value: 200, + buy_rules_min_quantity: 6, + }), + }) + ) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/regions/admin/regions.spec.ts b/integration-tests/modules/__tests__/regions/admin/regions.spec.ts index c24b00d5f2..dfc988f387 100644 --- a/integration-tests/modules/__tests__/regions/admin/regions.spec.ts +++ b/integration-tests/modules/__tests__/regions/admin/regions.spec.ts @@ -1,11 +1,7 @@ import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IRegionModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" import { createAdminUser } from "../../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -14,210 +10,206 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("Regions - Admin", () => { - let dbConnection - let appContainer - let shutdownServer - let service: IRegionModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Regions - Admin", () => { + let appContainer + let service: IRegionModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - service = appContainer.resolve(ModuleRegistrationName.REGION) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterEach(async () => { - const db = useDb() - // TODO: Once teardown doesn't skip constraint checks and cascades, we can remove this - const existingRegions = await service.list({}) - await service.delete(existingRegions.map((r) => r.id)) - await db.teardown() - }) - - it("should create, update, and delete a region", async () => { - const api = useApi() as any - const created = await api.post( - `/admin/regions`, - { - name: "Test Region", - currency_code: "usd", - countries: ["us", "ca"], - metadata: { foo: "bar" }, - }, - adminHeaders - ) - - expect(created.status).toEqual(200) - expect(created.data.region).toEqual( - expect.objectContaining({ - id: created.data.region.id, - name: "Test Region", - currency_code: "usd", - metadata: { foo: "bar" }, + beforeAll(async () => { + appContainer = getContainer() + service = appContainer.resolve(ModuleRegistrationName.REGION) }) - ) - expect(created.data.region.countries.map((c) => c.iso_2)).toEqual([ - "us", - "ca", - ]) - const updated = await api.post( - `/admin/regions/${created.data.region.id}`, - { - name: "United States", - currency_code: "usd", - countries: ["us"], - metadata: { foo: "baz" }, - }, - adminHeaders - ) - - expect(updated.status).toEqual(200) - expect(updated.data.region).toEqual( - expect.objectContaining({ - id: updated.data.region.id, - name: "United States", - currency_code: "usd", - metadata: { foo: "baz" }, + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) }) - ) - expect(updated.data.region.countries.map((c) => c.iso_2)).toEqual(["us"]) - const deleted = await api.delete( - `/admin/regions/${updated.data.region.id}`, - adminHeaders - ) + afterEach(async () => { + // TODO: Once teardown doesn't skip constraint checks and cascades, we can remove this + const existingRegions = await service.list({}) + await service.delete(existingRegions.map((r) => r.id)) + }) - expect(deleted.status).toEqual(200) - expect(deleted.data).toEqual({ - id: updated.data.region.id, - object: "region", - deleted: true, - }) + it("should create, update, and delete a region", async () => { + const created = await api.post( + `/admin/regions`, + { + name: "Test Region", + currency_code: "usd", + countries: ["us", "ca"], + metadata: { foo: "bar" }, + }, + adminHeaders + ) - const deletedRegion = await service.retrieve(updated.data.region.id, { - withDeleted: true, - }) + expect(created.status).toEqual(200) + expect(created.data.region).toEqual( + expect.objectContaining({ + id: created.data.region.id, + name: "Test Region", + currency_code: "usd", + metadata: { foo: "bar" }, + }) + ) + expect(created.data.region.countries.map((c) => c.iso_2)).toEqual([ + "us", + "ca", + ]) - // @ts-ignore - expect(deletedRegion.deleted_at).toBeTruthy() - }) + const updated = await api.post( + `/admin/regions/${created.data.region.id}`, + { + name: "United States", + currency_code: "usd", + countries: ["us"], + metadata: { foo: "baz" }, + }, + adminHeaders + ) - it("should throw on missing required properties in create", async () => { - const api = useApi() as any - const err = await api - .post(`/admin/regions`, {}, adminHeaders) - .catch((e) => e) + expect(updated.status).toEqual(200) + expect(updated.data.region).toEqual( + expect.objectContaining({ + id: updated.data.region.id, + name: "United States", + currency_code: "usd", + metadata: { foo: "baz" }, + }) + ) + expect(updated.data.region.countries.map((c) => c.iso_2)).toEqual([ + "us", + ]) - expect(err.response.status).toEqual(400) - expect(err.response.data.message).toEqual( - "name must be a string, currency_code must be a string" - ) - }) + const deleted = await api.delete( + `/admin/regions/${updated.data.region.id}`, + adminHeaders + ) - it("should throw on unknown properties in create", async () => { - const api = useApi() as any - const error = await api - .post( - `/admin/regions`, - { - foo: "bar", - currency_code: "usd", + expect(deleted.status).toEqual(200) + expect(deleted.data).toEqual({ + id: updated.data.region.id, + object: "region", + deleted: true, + }) + + const deletedRegion = await service.retrieve(updated.data.region.id, { + withDeleted: true, + }) + + // @ts-ignore + expect(deletedRegion.deleted_at).toBeTruthy() + }) + + it("should throw on missing required properties in create", async () => { + const err = await api + .post(`/admin/regions`, {}, adminHeaders) + .catch((e) => e) + + expect(err.response.status).toEqual(400) + expect(err.response.data.message).toEqual( + "name must be a string, currency_code must be a string" + ) + }) + + it("should throw on unknown properties in create", async () => { + const error = await api + .post( + `/admin/regions`, + { + foo: "bar", + currency_code: "usd", + name: "Test Region", + }, + adminHeaders + ) + .catch((e) => e) + + expect(error.response.status).toEqual(400) + expect(error.response.data.message).toEqual( + "property foo should not exist" + ) + }) + + it("should throw on unknown properties in update", async () => { + const created = await service.create({ name: "Test Region", - }, - adminHeaders - ) - .catch((e) => e) - - expect(error.response.status).toEqual(400) - expect(error.response.data.message).toEqual("property foo should not exist") - }) - - it("should throw on unknown properties in update", async () => { - const api = useApi() as any - - const created = await service.create({ - name: "Test Region", - currency_code: "usd", - }) - - const error = await api - .post( - `/admin/regions/${created.id}`, - { - foo: "bar", currency_code: "usd", - name: "Test Region", - }, - adminHeaders - ) - .catch((e) => e) + }) - expect(error.response.status).toEqual(400) - expect(error.response.data.message).toEqual("property foo should not exist") - }) + const error = await api + .post( + `/admin/regions/${created.id}`, + { + foo: "bar", + currency_code: "usd", + name: "Test Region", + }, + adminHeaders + ) + .catch((e) => e) - it("should get all regions and count", async () => { - await service.create([ - { - name: "Test", - currency_code: "usd", - countries: ["jp"], - metadata: { foo: "bar" }, - }, - ]) - - const api = useApi() as any - const response = await api.get(`/admin/regions`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data.regions).toEqual([ - expect.objectContaining({ - id: expect.any(String), - name: "Test", - currency_code: "usd", - metadata: { foo: "bar" }, - }), - ]) - expect(response.data.regions[0].countries.map((c) => c.iso_2)).toEqual([ - "jp", - ]) - }) - - it("should get a region", async () => { - const [region] = await service.create([ - { - name: "Test", - currency_code: "usd", - countries: ["jp"], - metadata: { foo: "bar" }, - }, - ]) - - const api = useApi() as any - const response = await api.get(`/admin/regions/${region.id}`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data.region).toEqual( - expect.objectContaining({ - id: region.id, - name: "Test", - currency_code: "usd", - metadata: { foo: "bar" }, + expect(error.response.status).toEqual(400) + expect(error.response.data.message).toEqual( + "property foo should not exist" + ) }) - ) - expect(response.data.region.countries.map((c) => c.iso_2)).toEqual(["jp"]) - }) + + it("should get all regions and count", async () => { + await service.create([ + { + name: "Test", + currency_code: "usd", + countries: ["jp"], + metadata: { foo: "bar" }, + }, + ]) + + const response = await api.get(`/admin/regions`, adminHeaders) + + expect(response.status).toEqual(200) + expect(response.data.regions).toEqual([ + expect.objectContaining({ + id: expect.any(String), + name: "Test", + currency_code: "usd", + metadata: { foo: "bar" }, + }), + ]) + expect(response.data.regions[0].countries.map((c) => c.iso_2)).toEqual([ + "jp", + ]) + }) + + it("should get a region", async () => { + const [region] = await service.create([ + { + name: "Test", + currency_code: "usd", + countries: ["jp"], + metadata: { foo: "bar" }, + }, + ]) + + const response = await api.get( + `/admin/regions/${region.id}`, + adminHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.region).toEqual( + expect.objectContaining({ + id: region.id, + name: "Test", + currency_code: "usd", + metadata: { foo: "bar" }, + }) + ) + expect(response.data.region.countries.map((c) => c.iso_2)).toEqual([ + "jp", + ]) + }) + }) + }, }) diff --git a/integration-tests/modules/__tests__/store/admin/store.spec.ts b/integration-tests/modules/__tests__/store/admin/store.spec.ts index e1c57090c3..b46a304205 100644 --- a/integration-tests/modules/__tests__/store/admin/store.spec.ts +++ b/integration-tests/modules/__tests__/store/admin/store.spec.ts @@ -1,12 +1,7 @@ import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { IStoreModuleService } from "@medusajs/types" -import path from "path" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" -import { getContainer } from "../../../../environment-helpers/use-container" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { DataSource } from "typeorm" import { createAdminUser } from "../../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -15,68 +10,56 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("Store - Admin", () => { - let dbConnection: DataSource - let appContainer - let shutdownServer - let service: IStoreModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Store - Admin", () => { + let appContainer + let service: IStoreModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - service = appContainer.resolve(ModuleRegistrationName.STORE) - }) + beforeAll(async () => { + appContainer = getContainer() + service = appContainer.resolve(ModuleRegistrationName.STORE) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + it("should correctly implement the entire lifecycle of a store", async () => { + const createdStore = await service.create({ + name: "Test store", + supported_currency_codes: ["usd"], + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + expect(createdStore).toEqual( + expect.objectContaining({ + id: createdStore.id, + supported_currency_codes: ["usd"], + name: "Test store", + }) + ) - it("should correctly implement the entire lifecycle of a store", async () => { - const api = useApi() as any - const createdStore = await service.create({ - name: "Test store", - supported_currency_codes: ["usd"], + const updated = await api.post( + `/admin/stores/${createdStore.id}`, + { + name: "Updated store", + }, + adminHeaders + ) + + expect(updated.status).toEqual(200) + expect(updated.data.store).toEqual( + expect.objectContaining({ + id: createdStore.id, + name: "Updated store", + }) + ) + + await service.delete(createdStore.id) + const listedStores = await api.get(`/admin/stores`, adminHeaders) + expect(listedStores.data.stores).toHaveLength(0) + }) }) - - expect(createdStore).toEqual( - expect.objectContaining({ - id: createdStore.id, - supported_currency_codes: ["usd"], - name: "Test store", - }) - ) - - const updated = await api.post( - `/admin/stores/${createdStore.id}`, - { - name: "Updated store", - }, - adminHeaders - ) - - expect(updated.status).toEqual(200) - expect(updated.data.store).toEqual( - expect.objectContaining({ - id: createdStore.id, - name: "Updated store", - }) - ) - - await service.delete(createdStore.id) - const listedStores = await api.get(`/admin/stores`, adminHeaders) - expect(listedStores.data.stores).toHaveLength(0) - }) + }, }) diff --git a/integration-tests/modules/__tests__/tax/admin/tax.spec.ts b/integration-tests/modules/__tests__/tax/admin/tax.spec.ts index 9a4e7efce3..8112758c36 100644 --- a/integration-tests/modules/__tests__/tax/admin/tax.spec.ts +++ b/integration-tests/modules/__tests__/tax/admin/tax.spec.ts @@ -1,12 +1,8 @@ -import path from "path" import { ITaxModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../../helpers/create-admin-user" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { getContainer } from "../../../../environment-helpers/use-container" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -15,497 +11,499 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("Taxes - Admin", () => { - let dbConnection - let appContainer - let shutdownServer - let service: ITaxModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Taxes - Admin", () => { + let appContainer + let service: ITaxModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - service = appContainer.resolve(ModuleRegistrationName.TAX) - }) + beforeAll(async () => { + appContainer = getContainer() + service = appContainer.resolve(ModuleRegistrationName.TAX) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("can retrieve a tax rate", async () => { + const region = await service.createTaxRegions({ + country_code: "us", + }) + const rate = await service.create({ + tax_region_id: region.id, + code: "test", + rate: 2.5, + name: "Test Rate", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.get( + `/admin/tax-rates/${rate.id}`, + adminHeaders + ) - it("can retrieve a tax rate", async () => { - const region = await service.createTaxRegions({ - country_code: "us", - }) - const rate = await service.create({ - tax_region_id: region.id, - code: "test", - rate: 2.5, - name: "Test Rate", - }) + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + tax_rate: { + id: rate.id, + code: "test", + rate: 2.5, + name: "Test Rate", + metadata: null, + tax_region_id: region.id, + is_default: false, + is_combinable: false, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + created_by: null, + }, + }) + }) - const api = useApi() as any - const response = await api.get(`/admin/tax-rates/${rate.id}`, adminHeaders) + it("can create a tax region with rates and rules", async () => { + const regionRes = await api.post( + `/admin/tax-regions`, + { + country_code: "us", + default_tax_rate: { + code: "default", + rate: 2, + name: "default rate", + }, + }, + adminHeaders + ) - expect(response.status).toEqual(200) - expect(response.data).toEqual({ - tax_rate: { - id: rate.id, - code: "test", - rate: 2.5, - name: "Test Rate", - metadata: null, - tax_region_id: region.id, - is_default: false, - is_combinable: false, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - created_by: null, - }, - }) - }) + const usRegionId = regionRes.data.tax_region.id - it("can create a tax region with rates and rules", async () => { - const api = useApi() as any - const regionRes = await api.post( - `/admin/tax-regions`, - { - country_code: "us", - default_tax_rate: { - code: "default", - rate: 2, - name: "default rate", - }, - }, - adminHeaders - ) + expect(regionRes.status).toEqual(200) + expect(regionRes.data).toEqual({ + tax_region: { + id: expect.any(String), + country_code: "us", + parent_id: null, + province_code: null, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + created_by: "admin_user", + provider_id: null, + metadata: null, + }, + }) - const usRegionId = regionRes.data.tax_region.id + const rateRes = await api.post( + `/admin/tax-rates`, + { + tax_region_id: usRegionId, + code: "RATE2", + name: "another rate", + rate: 10, + rules: [{ reference: "product", reference_id: "prod_1234" }], + }, + adminHeaders + ) - expect(regionRes.status).toEqual(200) - expect(regionRes.data).toEqual({ - tax_region: { - id: expect.any(String), - country_code: "us", - parent_id: null, - province_code: null, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - created_by: "admin_user", - provider_id: null, - metadata: null, - }, - }) + expect(rateRes.status).toEqual(200) + expect(rateRes.data).toEqual({ + tax_rate: { + id: expect.any(String), + code: "RATE2", + rate: 10, + name: "another rate", + is_default: false, + metadata: null, + tax_region_id: usRegionId, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + created_by: "admin_user", + is_combinable: false, + }, + }) - const rateRes = await api.post( - `/admin/tax-rates`, - { - tax_region_id: usRegionId, - code: "RATE2", - name: "another rate", - rate: 10, - rules: [{ reference: "product", reference_id: "prod_1234" }], - }, - adminHeaders - ) + const provRegRes = await api.post( + `/admin/tax-regions`, + { + country_code: "US", + parent_id: usRegionId, + province_code: "cA", + }, + adminHeaders + ) - expect(rateRes.status).toEqual(200) - expect(rateRes.data).toEqual({ - tax_rate: { - id: expect.any(String), - code: "RATE2", - rate: 10, - name: "another rate", - is_default: false, - metadata: null, - tax_region_id: usRegionId, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - created_by: "admin_user", - is_combinable: false, - }, - }) + expect(provRegRes.status).toEqual(200) + expect(provRegRes.data).toEqual({ + tax_region: { + id: expect.any(String), + country_code: "us", + parent_id: usRegionId, + province_code: "ca", + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + created_by: "admin_user", + metadata: null, + provider_id: null, + }, + }) - const provRegRes = await api.post( - `/admin/tax-regions`, - { - country_code: "US", - parent_id: usRegionId, - province_code: "cA", - }, - adminHeaders - ) + const defRes = await api.post( + `/admin/tax-rates`, + { + tax_region_id: provRegRes.data.tax_region.id, + code: "DEFAULT", + name: "DEFAULT", + rate: 10, + is_default: true, + }, + adminHeaders + ) - expect(provRegRes.status).toEqual(200) - expect(provRegRes.data).toEqual({ - tax_region: { - id: expect.any(String), - country_code: "us", - parent_id: usRegionId, - province_code: "ca", - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - created_by: "admin_user", - metadata: null, - provider_id: null, - }, - }) + const listRes = await api.get(`/admin/tax-rates`, adminHeaders) - const defRes = await api.post( - `/admin/tax-rates`, - { - tax_region_id: provRegRes.data.tax_region.id, - code: "DEFAULT", - name: "DEFAULT", - rate: 10, - is_default: true, - }, - adminHeaders - ) + expect(listRes.status).toEqual(200) + expect(listRes.data.tax_rates).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: rateRes.data.tax_rate.id, + code: "RATE2", + rate: 10, + name: "another rate", + is_default: false, + metadata: null, + tax_region_id: usRegionId, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + created_by: "admin_user", + }), + expect.objectContaining({ id: defRes.data.tax_rate.id }), + expect.objectContaining({ + tax_region_id: usRegionId, + is_default: true, + rate: 2, + }), + ]) + ) + }) - const listRes = await api.get(`/admin/tax-rates`, adminHeaders) + it("can create a tax rate and update it", async () => { + const regionRes = await api.post( + `/admin/tax-regions`, + { + country_code: "us", + default_tax_rate: { + code: "default", + rate: 2, + name: "default rate", + }, + }, + adminHeaders + ) - expect(listRes.status).toEqual(200) - expect(listRes.data.tax_rates).toEqual( - expect.arrayContaining([ - expect.objectContaining({ + const usRegionId = regionRes.data.tax_region.id + + expect(regionRes.status).toEqual(200) + expect(regionRes.data).toEqual({ + tax_region: { + id: expect.any(String), + country_code: "us", + parent_id: null, + province_code: null, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + created_by: "admin_user", + provider_id: null, + metadata: null, + }, + }) + + const rateRes = await api.post( + `/admin/tax-rates`, + { + tax_region_id: usRegionId, + code: "RATE2", + name: "another rate", + rate: 10, + rules: [{ reference: "product", reference_id: "prod_1234" }], + }, + adminHeaders + ) + + expect(rateRes.status).toEqual(200) + expect(rateRes.data).toEqual({ + tax_rate: { + id: expect.any(String), + code: "RATE2", + rate: 10, + name: "another rate", + is_default: false, + metadata: null, + tax_region_id: usRegionId, + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + created_by: "admin_user", + is_combinable: false, + }, + }) + + const updateRes = await api.post( + `/admin/tax-rates/${rateRes.data.tax_rate.id}`, + { + code: "updatedcode", + rate: 12, + is_combinable: true, + name: "Another Name", + metadata: { you: "know it" }, + }, + adminHeaders + ) + + expect(updateRes.status).toEqual(200) + expect(updateRes.data).toEqual({ + tax_rate: { + id: expect.any(String), + code: "updatedcode", + rate: 12, + name: "Another Name", + is_default: false, + metadata: { you: "know it" }, + tax_region_id: usRegionId, + deleted_at: null, + created_at: expect.any(String), + updated_at: expect.any(String), + created_by: "admin_user", + is_combinable: true, + }, + }) + }) + + it("can create a tax rate and delete it", async () => { + const regionRes = await api.post( + `/admin/tax-regions`, + { + country_code: "us", + default_tax_rate: { + code: "default", + rate: 2, + name: "default rate", + }, + }, + adminHeaders + ) + + const usRegionId = regionRes.data.tax_region.id + + const rateRes = await api.post( + `/admin/tax-rates`, + { + tax_region_id: usRegionId, + code: "RATE2", + name: "another rate", + rate: 10, + rules: [{ reference: "product", reference_id: "prod_1234" }], + }, + adminHeaders + ) + + const deleteRes = await api.delete( + `/admin/tax-rates/${rateRes.data.tax_rate.id}`, + adminHeaders + ) + + expect(deleteRes.status).toEqual(200) + expect(deleteRes.data).toEqual({ id: rateRes.data.tax_rate.id, - code: "RATE2", - rate: 10, - name: "another rate", - is_default: false, - metadata: null, - tax_region_id: usRegionId, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - created_by: "admin_user", - }), - expect.objectContaining({ id: defRes.data.tax_rate.id }), - expect.objectContaining({ - tax_region_id: usRegionId, - is_default: true, - rate: 2, - }), - ]) - ) - }) + object: "tax_rate", + deleted: true, + }) - it("can create a tax rate and update it", async () => { - const api = useApi() as any - const regionRes = await api.post( - `/admin/tax-regions`, - { - country_code: "us", - default_tax_rate: { code: "default", rate: 2, name: "default rate" }, - }, - adminHeaders - ) + const rates = await service.list( + { id: rateRes.data.tax_rate.id }, + { withDeleted: true } + ) + expect(rates.length).toEqual(1) + expect(rates[0].deleted_at).not.toBeNull() + }) - const usRegionId = regionRes.data.tax_region.id + it("can create a tax region and delete it", async () => { + const regionRes = await api.post( + `/admin/tax-regions`, + { + country_code: "us", + default_tax_rate: { + code: "default", + rate: 2, + name: "default rate", + }, + }, + adminHeaders + ) - expect(regionRes.status).toEqual(200) - expect(regionRes.data).toEqual({ - tax_region: { - id: expect.any(String), - country_code: "us", - parent_id: null, - province_code: null, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - created_by: "admin_user", - provider_id: null, - metadata: null, - }, + const usRegionId = regionRes.data.tax_region.id + + const deleteRes = await api.delete( + `/admin/tax-regions/${usRegionId}`, + adminHeaders + ) + + expect(deleteRes.status).toEqual(200) + expect(deleteRes.data).toEqual({ + id: usRegionId, + object: "tax_region", + deleted: true, + }) + + const rates = await service.listTaxRegions( + { id: usRegionId }, + { withDeleted: true } + ) + expect(rates.length).toEqual(1) + expect(rates[0].deleted_at).not.toBeNull() + }) + + it("can create a tax rate add rules and remove them", async () => { + const regionRes = await api.post( + `/admin/tax-regions`, + { + country_code: "us", + default_tax_rate: { + code: "default", + rate: 2, + name: "default rate", + }, + }, + adminHeaders + ) + + const usRegionId = regionRes.data.tax_region.id + const rateRes = await api.post( + `/admin/tax-rates`, + { + tax_region_id: usRegionId, + code: "RATE2", + name: "another rate", + rate: 10, + rules: [{ reference: "product", reference_id: "prod_1234" }], + }, + adminHeaders + ) + const rateId = rateRes.data.tax_rate.id + let rules = await service.listTaxRateRules({ tax_rate_id: rateId }) + + expect(rules).toEqual([ + { + id: expect.any(String), + tax_rate_id: rateId, + reference: "product", + reference_id: "prod_1234", + created_by: "admin_user", + created_at: expect.any(Date), + updated_at: expect.any(Date), + deleted_at: null, + tax_rate: { id: rateId }, + metadata: null, + }, + ]) + + await api.post( + `/admin/tax-rates/${rateId}/rules`, + { + reference: "product", + reference_id: "prod_1111", + }, + adminHeaders + ) + + await api.post( + `/admin/tax-rates/${rateId}/rules`, + { + reference: "product", + reference_id: "prod_2222", + }, + adminHeaders + ) + rules = await service.listTaxRateRules({ tax_rate_id: rateId }) + expect(rules).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + tax_rate_id: rateId, + reference: "product", + reference_id: "prod_1234", + created_by: "admin_user", + }), + expect.objectContaining({ + tax_rate_id: rateId, + reference: "product", + reference_id: "prod_1111", + created_by: "admin_user", + }), + expect.objectContaining({ + tax_rate_id: rateId, + reference: "product", + reference_id: "prod_2222", + created_by: "admin_user", + }), + ]) + ) + + const toDeleteId = rules.find((r) => r.reference_id === "prod_1111")!.id + await api.delete( + `/admin/tax-rates/${rateId}/rules/${toDeleteId}`, + adminHeaders + ) + + rules = await service.listTaxRateRules({ tax_rate_id: rateId }) + expect(rules.length).toEqual(2) + + await api.post( + `/admin/tax-rates/${rateId}`, + { + rules: [ + { reference: "product", reference_id: "prod_3333" }, + { reference: "product", reference_id: "prod_4444" }, + { reference: "product", reference_id: "prod_5555" }, + { reference: "product", reference_id: "prod_6666" }, + ], + }, + adminHeaders + ) + rules = await service.listTaxRateRules({ tax_rate_id: rateId }) + expect(rules.length).toEqual(4) + expect(rules).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + tax_rate_id: rateId, + reference: "product", + reference_id: "prod_3333", + created_by: "admin_user", + }), + expect.objectContaining({ + tax_rate_id: rateId, + reference: "product", + reference_id: "prod_4444", + created_by: "admin_user", + }), + expect.objectContaining({ + tax_rate_id: rateId, + reference: "product", + reference_id: "prod_5555", + created_by: "admin_user", + }), + expect.objectContaining({ + tax_rate_id: rateId, + reference: "product", + reference_id: "prod_6666", + created_by: "admin_user", + }), + ]) + ) + }) }) - - const rateRes = await api.post( - `/admin/tax-rates`, - { - tax_region_id: usRegionId, - code: "RATE2", - name: "another rate", - rate: 10, - rules: [{ reference: "product", reference_id: "prod_1234" }], - }, - adminHeaders - ) - - expect(rateRes.status).toEqual(200) - expect(rateRes.data).toEqual({ - tax_rate: { - id: expect.any(String), - code: "RATE2", - rate: 10, - name: "another rate", - is_default: false, - metadata: null, - tax_region_id: usRegionId, - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - created_by: "admin_user", - is_combinable: false, - }, - }) - - const updateRes = await api.post( - `/admin/tax-rates/${rateRes.data.tax_rate.id}`, - { - code: "updatedcode", - rate: 12, - is_combinable: true, - name: "Another Name", - metadata: { you: "know it" }, - }, - adminHeaders - ) - - expect(updateRes.status).toEqual(200) - expect(updateRes.data).toEqual({ - tax_rate: { - id: expect.any(String), - code: "updatedcode", - rate: 12, - name: "Another Name", - is_default: false, - metadata: { you: "know it" }, - tax_region_id: usRegionId, - deleted_at: null, - created_at: expect.any(String), - updated_at: expect.any(String), - created_by: "admin_user", - is_combinable: true, - }, - }) - }) - - it("can create a tax rate and delete it", async () => { - const api = useApi() as any - const regionRes = await api.post( - `/admin/tax-regions`, - { - country_code: "us", - default_tax_rate: { code: "default", rate: 2, name: "default rate" }, - }, - adminHeaders - ) - - const usRegionId = regionRes.data.tax_region.id - - const rateRes = await api.post( - `/admin/tax-rates`, - { - tax_region_id: usRegionId, - code: "RATE2", - name: "another rate", - rate: 10, - rules: [{ reference: "product", reference_id: "prod_1234" }], - }, - adminHeaders - ) - - const deleteRes = await api.delete( - `/admin/tax-rates/${rateRes.data.tax_rate.id}`, - adminHeaders - ) - - expect(deleteRes.status).toEqual(200) - expect(deleteRes.data).toEqual({ - id: rateRes.data.tax_rate.id, - object: "tax_rate", - deleted: true, - }) - - const rates = await service.list( - { id: rateRes.data.tax_rate.id }, - { withDeleted: true } - ) - expect(rates.length).toEqual(1) - expect(rates[0].deleted_at).not.toBeNull() - }) - - it("can create a tax region and delete it", async () => { - const api = useApi() as any - const regionRes = await api.post( - `/admin/tax-regions`, - { - country_code: "us", - default_tax_rate: { code: "default", rate: 2, name: "default rate" }, - }, - adminHeaders - ) - - const usRegionId = regionRes.data.tax_region.id - - const deleteRes = await api.delete( - `/admin/tax-regions/${usRegionId}`, - adminHeaders - ) - - expect(deleteRes.status).toEqual(200) - expect(deleteRes.data).toEqual({ - id: usRegionId, - object: "tax_region", - deleted: true, - }) - - const rates = await service.listTaxRegions( - { id: usRegionId }, - { withDeleted: true } - ) - expect(rates.length).toEqual(1) - expect(rates[0].deleted_at).not.toBeNull() - }) - - it("can create a tax rate add rules and remove them", async () => { - const api = useApi() as any - const regionRes = await api.post( - `/admin/tax-regions`, - { - country_code: "us", - default_tax_rate: { code: "default", rate: 2, name: "default rate" }, - }, - adminHeaders - ) - - const usRegionId = regionRes.data.tax_region.id - const rateRes = await api.post( - `/admin/tax-rates`, - { - tax_region_id: usRegionId, - code: "RATE2", - name: "another rate", - rate: 10, - rules: [{ reference: "product", reference_id: "prod_1234" }], - }, - adminHeaders - ) - const rateId = rateRes.data.tax_rate.id - let rules = await service.listTaxRateRules({ tax_rate_id: rateId }) - - expect(rules).toEqual([ - { - id: expect.any(String), - tax_rate_id: rateId, - reference: "product", - reference_id: "prod_1234", - created_by: "admin_user", - created_at: expect.any(Date), - updated_at: expect.any(Date), - deleted_at: null, - tax_rate: { id: rateId }, - metadata: null, - }, - ]) - - await api.post( - `/admin/tax-rates/${rateId}/rules`, - { - reference: "product", - reference_id: "prod_1111", - }, - adminHeaders - ) - - await api.post( - `/admin/tax-rates/${rateId}/rules`, - { - reference: "product", - reference_id: "prod_2222", - }, - adminHeaders - ) - rules = await service.listTaxRateRules({ tax_rate_id: rateId }) - expect(rules).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - tax_rate_id: rateId, - reference: "product", - reference_id: "prod_1234", - created_by: "admin_user", - }), - expect.objectContaining({ - tax_rate_id: rateId, - reference: "product", - reference_id: "prod_1111", - created_by: "admin_user", - }), - expect.objectContaining({ - tax_rate_id: rateId, - reference: "product", - reference_id: "prod_2222", - created_by: "admin_user", - }), - ]) - ) - - const toDeleteId = rules.find((r) => r.reference_id === "prod_1111")!.id - await api.delete( - `/admin/tax-rates/${rateId}/rules/${toDeleteId}`, - adminHeaders - ) - - rules = await service.listTaxRateRules({ tax_rate_id: rateId }) - expect(rules.length).toEqual(2) - - await api.post( - `/admin/tax-rates/${rateId}`, - { - rules: [ - { reference: "product", reference_id: "prod_3333" }, - { reference: "product", reference_id: "prod_4444" }, - { reference: "product", reference_id: "prod_5555" }, - { reference: "product", reference_id: "prod_6666" }, - ], - }, - adminHeaders - ) - rules = await service.listTaxRateRules({ tax_rate_id: rateId }) - expect(rules.length).toEqual(4) - expect(rules).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - tax_rate_id: rateId, - reference: "product", - reference_id: "prod_3333", - created_by: "admin_user", - }), - expect.objectContaining({ - tax_rate_id: rateId, - reference: "product", - reference_id: "prod_4444", - created_by: "admin_user", - }), - expect.objectContaining({ - tax_rate_id: rateId, - reference: "product", - reference_id: "prod_5555", - created_by: "admin_user", - }), - expect.objectContaining({ - tax_rate_id: rateId, - reference: "product", - reference_id: "prod_6666", - created_by: "admin_user", - }), - ]) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/tax/workflow/tax.spec.ts b/integration-tests/modules/__tests__/tax/workflow/tax.spec.ts index ea6a57e0d1..5b1f1ccfdb 100644 --- a/integration-tests/modules/__tests__/tax/workflow/tax.spec.ts +++ b/integration-tests/modules/__tests__/tax/workflow/tax.spec.ts @@ -1,18 +1,12 @@ -import path from "path" import { ITaxModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../../helpers/create-admin-user" -import { initDb, useDb } from "../../../../environment-helpers/use-db" -import { getContainer } from "../../../../environment-helpers/use-container" -import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../../environment-helpers/use-api" import { createTaxRateRulesStepId, - maybeSetTaxRateRulesStepId, - updateTaxRatesStepId, updateTaxRatesWorkflow, } from "@medusajs/core-flows" +import { medusaIntegrationTestRunner } from "medusa-test-utils/dist" jest.setTimeout(50000) @@ -21,189 +15,178 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("Taxes - Workflow", () => { - let dbConnection - let appContainer - let shutdownServer - let service: ITaxModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Taxes - Workflow", () => { + let appContainer + let service: ITaxModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - service = appContainer.resolve(ModuleRegistrationName.TAX) - }) + beforeAll(async () => { + appContainer = getContainer() + service = appContainer.resolve(ModuleRegistrationName.TAX) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("compensates rules correctly", async () => { + const taxRegion = await service.createTaxRegions({ + country_code: "us", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const [rateOne, rateTwo] = await service.create([ + { + tax_region_id: taxRegion.id, + rate: 10, + code: "standard", + name: "Standard", + rules: [ + { reference: "shipping", reference_id: "shipping_12354" }, + { reference: "shipping", reference_id: "shipping_11111" }, + { reference: "shipping", reference_id: "shipping_22222" }, + ], + }, + { + tax_region_id: taxRegion.id, + rate: 2, + code: "reduced", + name: "Reduced", + rules: [ + { reference: "product", reference_id: "product_12354" }, + { reference: "product", reference_id: "product_11111" }, + { reference: "product", reference_id: "product_22222" }, + ], + }, + ]) - it("compensates rules correctly", async () => { - const taxRegion = await service.createTaxRegions({ - country_code: "us", + const workflow = updateTaxRatesWorkflow(appContainer) + + workflow.appendAction("throw", createTaxRateRulesStepId, { + invoke: async function failStep() { + throw new Error(`Failed to update`) + }, + }) + + await workflow.run({ + input: { + selector: { tax_region_id: taxRegion.id }, + update: { + rate: 2, + rules: [ + { reference: "product", reference_id: "product_12354" }, + { reference: "shipping", reference_id: "shipping_12354" }, + ], + }, + }, + throwOnError: false, + }) + + const taxRateRules = await service.listTaxRateRules({ + tax_rate: { tax_region_id: taxRegion.id }, + }) + + expect(taxRateRules.length).toEqual(6) + expect(taxRateRules).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + tax_rate_id: rateOne.id, + reference_id: "shipping_12354", + }), + expect.objectContaining({ + tax_rate_id: rateOne.id, + reference_id: "shipping_11111", + }), + expect.objectContaining({ + tax_rate_id: rateOne.id, + reference_id: "shipping_22222", + }), + expect.objectContaining({ + tax_rate_id: rateTwo.id, + reference_id: "product_12354", + }), + expect.objectContaining({ + tax_rate_id: rateTwo.id, + reference_id: "product_11111", + }), + expect.objectContaining({ + tax_rate_id: rateTwo.id, + reference_id: "product_22222", + }), + ]) + ) + }) + + it("creates rules correctly", async () => { + const taxRegion = await service.createTaxRegions({ + country_code: "us", + }) + + const [rateOne, rateTwo] = await service.create([ + { + tax_region_id: taxRegion.id, + rate: 10, + code: "standard", + name: "Standard", + rules: [ + { reference: "shipping", reference_id: "shipping_12354" }, + { reference: "shipping", reference_id: "shipping_11111" }, + { reference: "shipping", reference_id: "shipping_22222" }, + ], + }, + { + tax_region_id: taxRegion.id, + rate: 2, + code: "reduced", + name: "Reduced", + rules: [ + { reference: "product", reference_id: "product_12354" }, + { reference: "product", reference_id: "product_11111" }, + { reference: "product", reference_id: "product_22222" }, + ], + }, + ]) + + await updateTaxRatesWorkflow(appContainer).run({ + input: { + selector: { tax_region_id: taxRegion.id }, + update: { + rate: 2, + rules: [ + { reference: "product", reference_id: "product_12354" }, + { reference: "shipping", reference_id: "shipping_12354" }, + ], + }, + }, + }) + + const taxRateRules = await service.listTaxRateRules({ + tax_rate: { tax_region_id: taxRegion.id }, + }) + + expect(taxRateRules.length).toEqual(4) + expect(taxRateRules).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + tax_rate_id: rateOne.id, + reference_id: "shipping_12354", + }), + expect.objectContaining({ + tax_rate_id: rateTwo.id, + reference_id: "shipping_12354", + }), + expect.objectContaining({ + tax_rate_id: rateOne.id, + reference_id: "product_12354", + }), + expect.objectContaining({ + tax_rate_id: rateTwo.id, + reference_id: "product_12354", + }), + ]) + ) + }) }) - - const [rateOne, rateTwo] = await service.create([ - { - tax_region_id: taxRegion.id, - rate: 10, - code: "standard", - name: "Standard", - rules: [ - { reference: "shipping", reference_id: "shipping_12354" }, - { reference: "shipping", reference_id: "shipping_11111" }, - { reference: "shipping", reference_id: "shipping_22222" }, - ], - }, - { - tax_region_id: taxRegion.id, - rate: 2, - code: "reduced", - name: "Reduced", - rules: [ - { reference: "product", reference_id: "product_12354" }, - { reference: "product", reference_id: "product_11111" }, - { reference: "product", reference_id: "product_22222" }, - ], - }, - ]) - - const workflow = updateTaxRatesWorkflow(appContainer) - - workflow.appendAction("throw", createTaxRateRulesStepId, { - invoke: async function failStep() { - throw new Error(`Failed to update`) - }, - }) - - await workflow.run({ - input: { - selector: { tax_region_id: taxRegion.id }, - update: { - rate: 2, - rules: [ - { reference: "product", reference_id: "product_12354" }, - { reference: "shipping", reference_id: "shipping_12354" }, - ], - }, - }, - throwOnError: false, - }) - - const taxRateRules = await service.listTaxRateRules({ - tax_rate: { tax_region_id: taxRegion.id }, - }) - - expect(taxRateRules.length).toEqual(6) - expect(taxRateRules).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - tax_rate_id: rateOne.id, - reference_id: "shipping_12354", - }), - expect.objectContaining({ - tax_rate_id: rateOne.id, - reference_id: "shipping_11111", - }), - expect.objectContaining({ - tax_rate_id: rateOne.id, - reference_id: "shipping_22222", - }), - expect.objectContaining({ - tax_rate_id: rateTwo.id, - reference_id: "product_12354", - }), - expect.objectContaining({ - tax_rate_id: rateTwo.id, - reference_id: "product_11111", - }), - expect.objectContaining({ - tax_rate_id: rateTwo.id, - reference_id: "product_22222", - }), - ]) - ) - }) - - it("creates rules correctly", async () => { - const taxRegion = await service.createTaxRegions({ - country_code: "us", - }) - - const [rateOne, rateTwo] = await service.create([ - { - tax_region_id: taxRegion.id, - rate: 10, - code: "standard", - name: "Standard", - rules: [ - { reference: "shipping", reference_id: "shipping_12354" }, - { reference: "shipping", reference_id: "shipping_11111" }, - { reference: "shipping", reference_id: "shipping_22222" }, - ], - }, - { - tax_region_id: taxRegion.id, - rate: 2, - code: "reduced", - name: "Reduced", - rules: [ - { reference: "product", reference_id: "product_12354" }, - { reference: "product", reference_id: "product_11111" }, - { reference: "product", reference_id: "product_22222" }, - ], - }, - ]) - - await updateTaxRatesWorkflow(appContainer).run({ - input: { - selector: { tax_region_id: taxRegion.id }, - update: { - rate: 2, - rules: [ - { reference: "product", reference_id: "product_12354" }, - { reference: "shipping", reference_id: "shipping_12354" }, - ], - }, - }, - }) - - const taxRateRules = await service.listTaxRateRules({ - tax_rate: { tax_region_id: taxRegion.id }, - }) - - expect(taxRateRules.length).toEqual(4) - expect(taxRateRules).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - tax_rate_id: rateOne.id, - reference_id: "shipping_12354", - }), - expect.objectContaining({ - tax_rate_id: rateTwo.id, - reference_id: "shipping_12354", - }), - expect.objectContaining({ - tax_rate_id: rateOne.id, - reference_id: "product_12354", - }), - expect.objectContaining({ - tax_rate_id: rateTwo.id, - reference_id: "product_12354", - }), - ]) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/users/create-user.spec.ts b/integration-tests/modules/__tests__/users/create-user.spec.ts index c80b351a71..04a855aa82 100644 --- a/integration-tests/modules/__tests__/users/create-user.spec.ts +++ b/integration-tests/modules/__tests__/users/create-user.spec.ts @@ -1,10 +1,5 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" import { createAdminUser } from "../../helpers/create-admin-user" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -13,43 +8,26 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/users", () => { - let dbConnection - let shutdownServer +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/users", () => { + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, getContainer()) + }) - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - }) + it("create a user", async () => { + const body = { + email: "test_member@test.com", + } - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + const response = await api.post(`/admin/users`, body, adminHeaders) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("create a user", async () => { - const api = useApi()! as AxiosInstance - - const body = { - email: "test_member@test.com", - } - - const response = await api.post(`/admin/users`, body, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data).toEqual({ - user: expect.objectContaining(body), + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + user: expect.objectContaining(body), + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/users/delete-user.spec.ts b/integration-tests/modules/__tests__/users/delete-user.spec.ts index 80e7300c60..5ae237315c 100644 --- a/integration-tests/modules/__tests__/users/delete-user.spec.ts +++ b/integration-tests/modules/__tests__/users/delete-user.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../helpers/create-admin-user" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,56 +10,46 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("DELETE /admin/users/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("DELETE /admin/users/:id", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should delete a single user", async () => { + const user = await userModuleService.create({ + email: "member@test.com", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.delete( + `/admin/users/${user.id}`, + adminHeaders + ) - it("should delete a single user", async () => { - const user = await userModuleService.create({ - email: "member@test.com", + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + id: user.id, + object: "user", + deleted: true, + }) + + const { response: deletedResponse } = await api + .get(`/admin/users/${user.id}`, adminHeaders) + .catch((e) => e) + + expect(deletedResponse.status).toEqual(404) + expect(deletedResponse.data.type).toEqual("not_found") + }) }) - - const api = useApi()! as AxiosInstance - - const response = await api.delete(`/admin/users/${user.id}`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data).toEqual({ - id: user.id, - object: "user", - deleted: true, - }) - - const { response: deletedResponse } = await api - .get(`/admin/users/${user.id}`, adminHeaders) - .catch((e) => e) - - expect(deletedResponse.status).toEqual(404) - expect(deletedResponse.data.type).toEqual("not_found") - }) + }, }) diff --git a/integration-tests/modules/__tests__/users/get-me.spec.ts b/integration-tests/modules/__tests__/users/get-me.spec.ts index e3ac8530a9..f8ae17e48e 100644 --- a/integration-tests/modules/__tests__/users/get-me.spec.ts +++ b/integration-tests/modules/__tests__/users/get-me.spec.ts @@ -1,10 +1,5 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" import { createAdminUser } from "../../helpers/create-admin-user" +import { medusaIntegrationTestRunner } from "medusa-test-utils/dist" jest.setTimeout(50000) @@ -13,39 +8,22 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/users/me", () => { - let dbConnection - let shutdownServer +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/users/me", () => { + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders) + }) - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - }) + it("gets the current user", async () => { + const response = await api.get(`/admin/users/me`, adminHeaders) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) - - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - afterEach(async () => { - const db = useDb() - await db.teardown() - }) - - it("gets the current user", async () => { - const api = useApi()! as AxiosInstance - - const response = await api.get(`/admin/users/me`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data).toEqual({ - user: expect.objectContaining({ id: "admin_user" }), + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + user: expect.objectContaining({ id: "admin_user" }), + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/users/list-users.spec.ts b/integration-tests/modules/__tests__/users/list-users.spec.ts index 272ce4e7ce..17a3311364 100644 --- a/integration-tests/modules/__tests__/users/list-users.spec.ts +++ b/integration-tests/modules/__tests__/users/list-users.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../helpers/create-admin-user" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,57 +10,44 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/users", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/users", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should list users", async () => { + await userModuleService.create([ + { + email: "member@test.com", + }, + ]) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.get(`/admin/users`, adminHeaders) - it("should list users", async () => { - await userModuleService.create([ - { - email: "member@test.com", - }, - ]) - - const api = useApi()! as AxiosInstance - - const response = await api.get(`/admin/users`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data).toEqual({ - users: expect.arrayContaining([ - expect.objectContaining({ - email: "admin@medusa.js", - }), - expect.objectContaining({ email: "member@test.com" }), - ]), - count: 2, - offset: 0, - limit: 50, + expect(response.status).toEqual(200) + expect(response.data).toEqual({ + users: expect.arrayContaining([ + expect.objectContaining({ + email: "admin@medusa.js", + }), + expect.objectContaining({ email: "member@test.com" }), + ]), + count: 2, + offset: 0, + limit: 50, + }) + }) }) - }) + }, }) diff --git a/integration-tests/modules/__tests__/users/retrieve-user.spec.ts b/integration-tests/modules/__tests__/users/retrieve-user.spec.ts index 05c733f7bb..d4aacc5aac 100644 --- a/integration-tests/modules/__tests__/users/retrieve-user.spec.ts +++ b/integration-tests/modules/__tests__/users/retrieve-user.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../helpers/create-admin-user" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,47 +10,34 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("GET /admin/users/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("GET /admin/users/:id", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should retrieve a single user", async () => { + const user = await userModuleService.create({ + email: "member@test.com", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const response = await api.get(`/admin/users/${user.id}`, adminHeaders) - it("should retrieve a single user", async () => { - const user = await userModuleService.create({ - email: "member@test.com", + expect(response.status).toEqual(200) + expect(response.data.user).toEqual( + expect.objectContaining({ email: "member@test.com" }) + ) + }) }) - - const api = useApi()! as AxiosInstance - - const response = await api.get(`/admin/users/${user.id}`, adminHeaders) - - expect(response.status).toEqual(200) - expect(response.data.user).toEqual( - expect.objectContaining({ email: "member@test.com" }) - ) - }) + }, }) diff --git a/integration-tests/modules/__tests__/users/update-user.spec.ts b/integration-tests/modules/__tests__/users/update-user.spec.ts index f70cb45915..fe75de1530 100644 --- a/integration-tests/modules/__tests__/users/update-user.spec.ts +++ b/integration-tests/modules/__tests__/users/update-user.spec.ts @@ -1,13 +1,7 @@ -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" import { IUserModuleService } from "@medusajs/types" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { createAdminUser } from "../../helpers/create-admin-user" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" jest.setTimeout(50000) @@ -16,53 +10,40 @@ const adminHeaders = { headers: { "x-medusa-access-token": "test_token" }, } -describe("POST /admin/users/:id", () => { - let dbConnection - let appContainer - let shutdownServer - let userModuleService: IUserModuleService +medusaIntegrationTestRunner({ + env, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("POST /admin/users/:id", () => { + let appContainer + let userModuleService: IUserModuleService - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - appContainer = getContainer() - userModuleService = appContainer.resolve(ModuleRegistrationName.USER) - }) + beforeAll(async () => { + appContainer = getContainer() + userModuleService = appContainer.resolve(ModuleRegistrationName.USER) + }) - beforeEach(async () => { - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, appContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) + it("should update a single user", async () => { + const user = await userModuleService.create({ + email: "member@test.com", + }) - afterEach(async () => { - const db = useDb() - await db.teardown() - }) + const body = { + first_name: "John", + last_name: "Doe", + } + const response = await api.post( + `/admin/users/${user.id}`, + body, + adminHeaders + ) - it("should update a single user", async () => { - const user = await userModuleService.create({ - email: "member@test.com", + expect(response.status).toEqual(200) + expect(response.data.user).toEqual(expect.objectContaining(body)) + }) }) - - const api = useApi()! as AxiosInstance - - const body = { - first_name: "John", - last_name: "Doe", - } - const response = await api.post( - `/admin/users/${user.id}`, - body, - adminHeaders - ) - - expect(response.status).toEqual(200) - expect(response.data.user).toEqual(expect.objectContaining(body)) - }) + }, }) diff --git a/integration-tests/modules/__tests__/workflow-engine/api.ts b/integration-tests/modules/__tests__/workflow-engine/api.ts index 7498e32e30..6cb1facbc1 100644 --- a/integration-tests/modules/__tests__/workflow-engine/api.ts +++ b/integration-tests/modules/__tests__/workflow-engine/api.ts @@ -4,6 +4,7 @@ jest.setTimeout(5000000) const env = { MEDUSA_FF_MEDUSA_V2: false, + MEDUSA_FF_SALES_CHANNELS: true, } workflowEngineTestSuite(env, { force_modules_migration: true }) diff --git a/integration-tests/modules/__tests__/workflow-engine/tests.ts b/integration-tests/modules/__tests__/workflow-engine/tests.ts index e0c6b468a6..b5aa4608c7 100644 --- a/integration-tests/modules/__tests__/workflow-engine/tests.ts +++ b/integration-tests/modules/__tests__/workflow-engine/tests.ts @@ -4,266 +4,257 @@ import { StepResponse, WorkflowData, } from "@medusajs/workflows-sdk" -import { initDb, useDb } from "../../../environment-helpers/use-db" - -import { AxiosInstance } from "axios" -import adminSeeder from "../../../helpers/admin-seeder" import { createAdminUser } from "../../helpers/create-admin-user" -import { getContainer } from "../../../environment-helpers/use-container" -import path from "path" -import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" -import { useApi } from "../../../environment-helpers/use-api" +import { medusaIntegrationTestRunner } from "medusa-test-utils" -export const workflowEngineTestSuite = (env, extraParams = {}) => { +export const workflowEngineTestSuite = ( + env, + extraParams: { force_modules_migration?: boolean } = {} +) => { const adminHeaders = { headers: { "x-medusa-access-token": "test_token", }, } - describe("Workflow Engine API", () => { - let medusaContainer - let dbConnection - let shutdownServer + return medusaIntegrationTestRunner({ + env, + force_modules_migration: extraParams.force_modules_migration, + testSuite: ({ dbConnection, getContainer, api }) => { + describe("Workflow Engine API", () => { + let medusaContainer - beforeAll(async () => { - const cwd = path.resolve(path.join(__dirname, "..", "..")) - dbConnection = await initDb({ cwd, env, ...extraParams } as any) - shutdownServer = await startBootstrapApp({ cwd, env }) - medusaContainer = getContainer() + beforeAll(() => { + medusaContainer = getContainer() + }) - await createAdminUser(dbConnection, adminHeaders) - }) + beforeEach(async () => { + await createAdminUser(dbConnection, adminHeaders, medusaContainer) + }) - afterAll(async () => { - const db = useDb() - await db.shutdown() - await shutdownServer() - }) - - describe("running workflows", () => { - beforeAll(async () => { - const step1 = createStep( - { - name: "my-step", - }, - async (input: { initial: string }) => { - return new StepResponse({ - result: input.initial, - }) - } - ) - const step2 = createStep( - { - name: "my-step-async", - async: true, - }, - async () => {} - ) - - createWorkflow( - { - name: "my-workflow-name", - retentionTime: 1000, - }, - function (input: WorkflowData<{ initial: string }>) { - step1(input) - return step2() - } - ) - }) - - it("Should list all workflows in execution or completed and retrieve them by id", async () => { - const api = useApi()! as AxiosInstance - - for (let i = 3; i--; ) { - await api.post( - `/admin/workflows-executions/my-workflow-name/run`, - { - input: { - initial: "abc", + describe("running workflows", () => { + beforeAll(async () => { + const step1 = createStep( + { + name: "my-step", }, - }, - adminHeaders - ) - } - - const executions = await api.get( - `/admin/workflows-executions`, - adminHeaders - ) - - expect(executions.data.count).toEqual(3) - expect(executions.data.workflow_executions.length).toEqual(3) - expect(executions.data.workflow_executions[0]).toEqual({ - workflow_id: "my-workflow-name", - transaction_id: expect.any(String), - id: expect.any(String), - state: "invoking", - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }) - - const retrivedById = await api.get( - `/admin/workflows-executions/` + - executions.data.workflow_executions[0].id, - adminHeaders - ) - expect(retrivedById.data.workflow_execution).toEqual( - expect.objectContaining(executions.data.workflow_executions[0]) - ) - }) - - it("Should list all workflows matching the filters", async () => { - const api = useApi()! as AxiosInstance - - for (let i = 3; i--; ) { - await api.post( - `/admin/workflows-executions/my-workflow-name/run`, - { - input: { - initial: "abc", + async (input: { initial: string }) => { + return new StepResponse({ + result: input.initial, + }) + } + ) + const step2 = createStep( + { + name: "my-step-async", + async: true, }, - transaction_id: "transaction_" + (i + 1), - }, - adminHeaders - ) - } + async () => {} + ) - const executions = await api.get( - `/admin/workflows-executions?transaction_id[]=transaction_1&transaction_id[]=transaction_2`, - adminHeaders - ) + createWorkflow( + { + name: "my-workflow-name", + retentionTime: 1000, + }, + function (input: WorkflowData<{ initial: string }>) { + step1(input) + return step2() + } + ) + }) - expect(executions.data.count).toEqual(2) - expect(executions.data.workflow_executions.length).toEqual(2) - expect(executions.data.workflow_executions[0]).toEqual({ - workflow_id: "my-workflow-name", - transaction_id: expect.stringMatching(/transaction_1|transaction_2/), - id: expect.any(String), - state: "invoking", - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }) - expect(executions.data.workflow_executions[1]).toEqual({ - workflow_id: "my-workflow-name", - transaction_id: expect.stringMatching(/transaction_1|transaction_2/), - id: expect.any(String), - state: "invoking", - created_at: expect.any(String), - updated_at: expect.any(String), - deleted_at: null, - }) - }) - - it("Should execute a workflow and retrieve its execution while running and when it is completed", async () => { - const api = useApi()! as AxiosInstance - - const wf = await api.post( - `/admin/workflows-executions/my-workflow-name/run`, - { - input: { - initial: "abc", - }, - transaction_id: "trx_123", - }, - adminHeaders - ) - - expect(wf.data).toEqual({ - acknowledgement: { - transactionId: "trx_123", - workflowId: "my-workflow-name", - }, - }) - - const execution = await api.get( - `/admin/workflows-executions/my-workflow-name/trx_123`, - adminHeaders - ) - - expect(execution.data).toEqual({ - workflow_execution: expect.objectContaining({ - workflow_id: "my-workflow-name", - transaction_id: "trx_123", - id: expect.any(String), - state: "invoking", - execution: expect.objectContaining({ - hasAsyncSteps: true, - hasFailedSteps: false, - hasSkippedSteps: false, - hasWaitingSteps: false, - hasRevertedSteps: false, - }), - context: expect.objectContaining({ - data: expect.objectContaining({ - invoke: { - "my-step": { - __type: "Symbol(WorkflowWorkflowData)", - output: { - __type: "Symbol(WorkflowStepResponse)", - output: { - result: "abc", - }, - compensateInput: { - result: "abc", - }, - }, + it("Should list all workflows in execution or completed and retrieve them by id", async () => { + for (let i = 3; i--; ) { + await api.post( + `/admin/workflows-executions/my-workflow-name/run`, + { + input: { + initial: "abc", }, }, - payload: { + adminHeaders + ) + } + + const executions = await api.get( + `/admin/workflows-executions`, + adminHeaders + ) + + expect(executions.data.count).toEqual(3) + expect(executions.data.workflow_executions.length).toEqual(3) + expect(executions.data.workflow_executions[0]).toEqual({ + workflow_id: "my-workflow-name", + transaction_id: expect.any(String), + id: expect.any(String), + state: "invoking", + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }) + + const retrivedById = await api.get( + `/admin/workflows-executions/` + + executions.data.workflow_executions[0].id, + adminHeaders + ) + expect(retrivedById.data.workflow_execution).toEqual( + expect.objectContaining(executions.data.workflow_executions[0]) + ) + }) + + it("Should list all workflows matching the filters", async () => { + for (let i = 3; i--; ) { + await api.post( + `/admin/workflows-executions/my-workflow-name/run`, + { + input: { + initial: "abc", + }, + transaction_id: "transaction_" + (i + 1), + }, + adminHeaders + ) + } + + const executions = await api.get( + `/admin/workflows-executions?transaction_id[]=transaction_1&transaction_id[]=transaction_2`, + adminHeaders + ) + + expect(executions.data.count).toEqual(2) + expect(executions.data.workflow_executions.length).toEqual(2) + expect(executions.data.workflow_executions[0]).toEqual({ + workflow_id: "my-workflow-name", + transaction_id: expect.stringMatching( + /transaction_1|transaction_2/ + ), + id: expect.any(String), + state: "invoking", + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }) + expect(executions.data.workflow_executions[1]).toEqual({ + workflow_id: "my-workflow-name", + transaction_id: expect.stringMatching( + /transaction_1|transaction_2/ + ), + id: expect.any(String), + state: "invoking", + created_at: expect.any(String), + updated_at: expect.any(String), + deleted_at: null, + }) + }) + + it("Should execute a workflow and retrieve its execution while running and when it is completed", async () => { + const wf = await api.post( + `/admin/workflows-executions/my-workflow-name/run`, + { + input: { initial: "abc", }, - }), - }), - }), - }) + transaction_id: "trx_123", + }, + adminHeaders + ) - const respondAsync = await api.post( - `/admin/workflows-executions/my-workflow-name/steps/success`, - { - transaction_id: "trx_123", - step_id: "my-step-async", - response: { - all: "good", - }, - }, - adminHeaders - ) + expect(wf.data).toEqual({ + acknowledgement: { + transactionId: "trx_123", + workflowId: "my-workflow-name", + }, + }) - expect(respondAsync.data.success).toEqual(true) + const execution = await api.get( + `/admin/workflows-executions/my-workflow-name/trx_123`, + adminHeaders + ) - const completed = await api.get( - `/admin/workflows-executions/my-workflow-name/trx_123`, - adminHeaders - ) - - expect(completed.data).toEqual({ - workflow_execution: expect.objectContaining({ - workflow_id: "my-workflow-name", - transaction_id: "trx_123", - state: "done", - context: expect.objectContaining({ - data: expect.objectContaining({ - invoke: expect.objectContaining({ - "my-step-async": { - __type: "Symbol(WorkflowStepResponse)", - output: { - all: "good", + expect(execution.data).toEqual({ + workflow_execution: expect.objectContaining({ + workflow_id: "my-workflow-name", + transaction_id: "trx_123", + id: expect.any(String), + state: "invoking", + execution: expect.objectContaining({ + hasAsyncSteps: true, + hasFailedSteps: false, + hasSkippedSteps: false, + hasWaitingSteps: false, + hasRevertedSteps: false, + }), + context: expect.objectContaining({ + data: expect.objectContaining({ + invoke: { + "my-step": { + __type: "Symbol(WorkflowWorkflowData)", + output: { + __type: "Symbol(WorkflowStepResponse)", + output: { + result: "abc", + }, + compensateInput: { + result: "abc", + }, + }, + }, }, - compensateInput: { - all: "good", + payload: { + initial: "abc", }, - }, + }), }), }), - }), - }), + }) + + const respondAsync = await api.post( + `/admin/workflows-executions/my-workflow-name/steps/success`, + { + transaction_id: "trx_123", + step_id: "my-step-async", + response: { + all: "good", + }, + }, + adminHeaders + ) + + expect(respondAsync.data.success).toEqual(true) + + const completed = await api.get( + `/admin/workflows-executions/my-workflow-name/trx_123`, + adminHeaders + ) + + expect(completed.data).toEqual({ + workflow_execution: expect.objectContaining({ + workflow_id: "my-workflow-name", + transaction_id: "trx_123", + state: "done", + context: expect.objectContaining({ + data: expect.objectContaining({ + invoke: expect.objectContaining({ + "my-step-async": { + __type: "Symbol(WorkflowStepResponse)", + output: { + all: "good", + }, + compensateInput: { + all: "good", + }, + }, + }), + }), + }), + }), + }) + }) }) }) - }) + }, }) } diff --git a/integration-tests/modules/helpers/create-admin-user.ts b/integration-tests/modules/helpers/create-admin-user.ts index f163e176cb..cbc90a2970 100644 --- a/integration-tests/modules/helpers/create-admin-user.ts +++ b/integration-tests/modules/helpers/create-admin-user.ts @@ -4,9 +4,13 @@ import jwt from "jsonwebtoken" import { getContainer } from "../../environment-helpers/use-container" import adminSeeder from "../../helpers/admin-seeder" -export const createAdminUser = async (dbConnection, adminHeaders) => { +export const createAdminUser = async ( + dbConnection, + adminHeaders, + container? +) => { await adminSeeder(dbConnection) - const appContainer = getContainer()! + const appContainer = container ?? getContainer()! const authModule: IAuthModuleService = appContainer.resolve( ModuleRegistrationName.AUTH diff --git a/integration-tests/modules/jest.config.js b/integration-tests/modules/jest.config.js index fda20d9945..0685e4c19c 100644 --- a/integration-tests/modules/jest.config.js +++ b/integration-tests/modules/jest.config.js @@ -15,9 +15,11 @@ module.exports = { `.cache`, ], transformIgnorePatterns: [`/dist`], - transform: { "^.+\\.[jt]s$": `../../jest-transformer.js` }, + transform: { + "^.+\\.[jt]s$": `../../jest-transformer.js`, + }, setupFiles: ["../setup-env.js"], - setupFilesAfterEnv: ["../setup.js"], + /*setupFilesAfterEnv: ["../setup.js"], globalSetup: "../globalSetup.js", - globalTeardown: "../globalTeardown.js", + globalTeardown: "../globalTeardown.js",*/ } diff --git a/integration-tests/modules/package.json b/integration-tests/modules/package.json index 7293c5ecac..71f9a588f8 100644 --- a/integration-tests/modules/package.json +++ b/integration-tests/modules/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --detectOpenHandles --logHeapUsage --clearMocks --forceExit", + "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --ci --silent=false -i --detectOpenHandles --logHeapUsage --forceExit", "build": "babel src -d dist --extensions \".ts,.js\"" }, "dependencies": { @@ -30,6 +30,7 @@ "medusa-fulfillment-webshipper": "workspace:*", "medusa-interfaces": "workspace:*", "medusa-plugin-sendgrid": "workspace:*", + "medusa-test-utils": "workspace:*", "pg": "^8.11.0", "typeorm": "^0.3.16" }, diff --git a/packages/medusa-test-utils/package.json b/packages/medusa-test-utils/package.json index ef9e35c8b0..880c71541f 100644 --- a/packages/medusa-test-utils/package.json +++ b/packages/medusa-test-utils/package.json @@ -24,18 +24,46 @@ "author": "Sebastian Rindom", "license": "MIT", "devDependencies": { + "@medusajs/types": "^1.1.41", "cross-env": "^5.2.1", "jest": "^25.5.4", "rimraf": "^3.0.2", "typescript": "^5.1.6" }, + "peerDependencies": { + "@medusajs/medusa": ">1.19", + "axios": "^0.28.0", + "express": "^4.18.3", + "get-port": "^5.1.0", + "pg-god": "^1.0.12", + "typeorm": "^0.2.43" + }, + "peerDependenciesMeta": { + "@medusajs/medusa": { + "optional": true + }, + "axios": { + "optional": true + }, + "express": { + "optional": true + }, + "get-port": { + "optional": true + }, + "pg-god": { + "optional": true + }, + "typeorm": { + "optional": true + } + }, "dependencies": { "@medusajs/modules-sdk": "^1.12.6", "@medusajs/utils": "^1.1.41", "@mikro-orm/migrations": "5.9.7", "@mikro-orm/postgresql": "5.9.7", "medusa-core-utils": "^1.2.1", - "pg-god": "^1.0.12", "randomatic": "^3.1.1" }, "gitHead": "81a7ff73d012fda722f6e9ef0bd9ba0232d37808" diff --git a/packages/medusa-test-utils/src/index.ts b/packages/medusa-test-utils/src/index.ts index 10cc0895b9..46cd657210 100644 --- a/packages/medusa-test-utils/src/index.ts +++ b/packages/medusa-test-utils/src/index.ts @@ -6,3 +6,4 @@ export { default as MockRepository } from "./mock-repository" export * from "./init-modules" export { default as MockEventBusService } from "./mock-event-bus-service" export * from "./module-test-runner" +export * from "./medusa-test-runner" diff --git a/packages/medusa-test-utils/src/medusa-test-runner-utils/bootstrap-app.js b/packages/medusa-test-utils/src/medusa-test-runner-utils/bootstrap-app.js new file mode 100644 index 0000000000..09029ebef8 --- /dev/null +++ b/packages/medusa-test-utils/src/medusa-test-runner-utils/bootstrap-app.js @@ -0,0 +1,79 @@ +const path = require("path") +const express = require("express") +const getPort = require("get-port") +const { isObject } = require("@medusajs/utils") + +async function bootstrapApp({ cwd, env = {} } = {}) { + const app = express() + + if (isObject(env)) { + Object.entries(env).forEach(([k, v]) => (process.env[k] = v)) + } + + const loaders = require("@medusajs/medusa/dist/loaders").default + + const { container, dbConnection, pgConnection, disposeResources } = + await loaders({ + directory: path.resolve(cwd || process.cwd()), + expressApp: app, + isTest: false, + }) + + const PORT = await getPort() + + return { + disposeResources, + container, + db: dbConnection, + pgConnection, + app, + port: PORT, + } +} + +module.exports = { + startBootstrapApp: async ({ + cwd, + env = {}, + skipExpressListen = false, + } = {}) => { + const { app, port, container, db, pgConnection } = await bootstrapApp({ + cwd, + env, + }) + let expressServer + + if (skipExpressListen) { + return + } + + const shutdown = async () => { + await Promise.all([ + container.dispose(), + expressServer.close(), + db?.destroy(), + pgConnection?.context?.destroy(), + container.dispose(), + ]) + + if (typeof global !== "undefined" && global?.gc) { + global.gc() + } + } + + return await new Promise((resolve, reject) => { + expressServer = app.listen(port, async (err) => { + if (err) { + await shutdown() + return reject(err) + } + process.send(port) + resolve({ + shutdown, + container, + port, + }) + }) + }) + }, +} diff --git a/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.js b/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.js new file mode 100644 index 0000000000..e97c63e5c6 --- /dev/null +++ b/packages/medusa-test-utils/src/medusa-test-runner-utils/use-db.js @@ -0,0 +1,113 @@ +const path = require("path") + +const { getConfigFile } = require("medusa-core-utils") +const { asValue } = require("awilix") +const { + isObject, + createMedusaContainer, + MedusaV2Flag, +} = require("@medusajs/utils") +const { DataSource } = require("typeorm") +const { ContainerRegistrationKeys } = require("@medusajs/utils") +const { migrateMedusaApp } = require("@medusajs/medusa/dist/loaders/medusa-app") +const { logger } = require("@medusajs/medusa-cli/dist/reporter") + +module.exports = { + initDb: async function ({ + cwd, + database_extra, + env, + force_modules_migration, + dbUrl = DB_URL, + dbSchema = "public", + }) { + if (isObject(env)) { + Object.entries(env).forEach(([k, v]) => (process.env[k] = v)) + } + + const { configModule } = getConfigFile(cwd, `medusa-config`) + + const featureFlagsLoader = + require("@medusajs/medusa/dist/loaders/feature-flags").default + + const featureFlagRouter = featureFlagsLoader(configModule) + const modelsLoader = require("@medusajs/medusa/dist/loaders/models").default + const entities = modelsLoader({}, { register: false }) + + // get migrations with enabled featureflags + const migrationDir = path.resolve( + path.join( + cwd, + `../../`, + `node_modules`, + `@medusajs`, + `medusa`, + `dist`, + `migrations`, + `*.js` + ) + ) + + const { + getEnabledMigrations, + getModuleSharedResources, + } = require("@medusajs/medusa/dist/commands/utils/get-migrations") + + const { migrations: moduleMigrations, models: moduleModels } = + getModuleSharedResources(configModule, featureFlagRouter) + + const enabledMigrations = getEnabledMigrations([migrationDir], (flag) => + featureFlagRouter.isFeatureEnabled(flag) + ) + + const enabledEntities = entities.filter( + (e) => typeof e.isFeatureEnabled === "undefined" || e.isFeatureEnabled() + ) + + const dbDataSource = new DataSource({ + type: "postgres", + url: dbUrl, + entities: enabledEntities.concat(moduleModels), + migrations: enabledMigrations.concat(moduleMigrations), + extra: database_extra ?? {}, + //name: "integration-tests", + schema: dbSchema, + }) + + await dbDataSource.initialize() + + await dbDataSource.runMigrations() + + if ( + force_modules_migration || + featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key) + ) { + const pgConnectionLoader = + require("@medusajs/medusa/dist/loaders/pg-connection").default + + const featureFlagLoader = + require("@medusajs/medusa/dist/loaders/feature-flags").default + + const container = createMedusaContainer() + + const featureFlagRouter = await featureFlagLoader(configModule) + + const pgConnection = await pgConnectionLoader({ configModule, container }) + + container.register({ + [ContainerRegistrationKeys.CONFIG_MODULE]: asValue(configModule), + [ContainerRegistrationKeys.LOGGER]: asValue(logger), + [ContainerRegistrationKeys.MANAGER]: asValue(dbDataSource.manager), + [ContainerRegistrationKeys.PG_CONNECTION]: asValue(pgConnection), + featureFlagRouter: asValue(featureFlagRouter), + }) + + await migrateMedusaApp( + { configModule, container }, + { registerInContainer: false } + ) + } + + return { dbDataSource, pgConnection } + }, +} diff --git a/packages/medusa-test-utils/src/medusa-test-runner.ts b/packages/medusa-test-utils/src/medusa-test-runner.ts new file mode 100644 index 0000000000..128336ae26 --- /dev/null +++ b/packages/medusa-test-utils/src/medusa-test-runner.ts @@ -0,0 +1,238 @@ +import { getDatabaseURL } from "./database" +import { initDb } from "./medusa-test-runner-utils/use-db" +import { startBootstrapApp } from "./medusa-test-runner-utils/bootstrap-app" +import { createDatabase, dropDatabase } from "pg-god" +import { ContainerLike } from "@medusajs/types" + +const axios = require("axios").default + +const keepTables = [ + "store", + "staged_job", + "shipping_profile", + "fulfillment_provider", + "payment_provider", + "country", + "region_country", + "currency", + "migrations", + "mikro_orm_migrations", +] + +const DB_HOST = process.env.DB_HOST +const DB_USERNAME = process.env.DB_USERNAME +const DB_PASSWORD = process.env.DB_PASSWORD + +const pgGodCredentials = { + user: DB_USERNAME, + password: DB_PASSWORD, + host: DB_HOST, +} + +const dbTestUtilFactory = (): any => ({ + db_: null, + pgConnection_: null, + + clear: async function () { + this.db_?.synchronize(true) + }, + + create: async function (dbName: string) { + await createDatabase({ databaseName: dbName }, pgGodCredentials) + }, + + teardown: async function ({ + forceDelete, + schema, + }: { forceDelete?: string[]; schema?: string } = {}) { + forceDelete = forceDelete || [] + const manager = this.db_.manager + + await manager.query(`SET session_replication_role = 'replica';`) + const tableNames = await manager.query(`SELECT table_name + FROM information_schema.tables + WHERE table_schema = '${ + schema ?? "public" + }';`) + + for (const { table_name } of tableNames) { + if ( + keepTables.includes(table_name) && + !forceDelete.includes(table_name) + ) { + continue + } + + await manager.query(`DELETE + FROM "${table_name}";`) + } + + await manager.query(`SET session_replication_role = 'origin';`) + }, + + shutdown: async function (dbName: string) { + await this.db_?.destroy() + await this.pgConnection_?.context?.destroy() + + return await dropDatabase( + { databaseName: dbName, errorIfNonExist: false }, + pgGodCredentials + ) + }, +}) + +export interface MedusaSuiteOptions { + dbUtils: any + dbConnection: any // Legacy typeorm connection + getContainer: () => ContainerLike + api: any + dbConfig: { + dbName: string + schema: string + clientUrl: string + } +} + +export function medusaIntegrationTestRunner({ + moduleName, + dbName, + schema = "public", + env = {}, + force_modules_migration = false, + debug = false, + testSuite, +}: { + moduleName?: string + env?: Record + dbName?: string + schema?: string + debug?: boolean + force_modules_migration?: boolean + testSuite: ( + options: MedusaSuiteOptions + ) => () => void +}) { + const tempName = parseInt(process.env.JEST_WORKER_ID || "1") + moduleName = moduleName ?? Math.random().toString(36).substring(7) + dbName ??= `medusa-${moduleName.toLowerCase()}-integration-${tempName}` + + let dbConfig = { + dbName, + clientUrl: getDatabaseURL(dbName), + schema, + debug, + } + + // Intercept call to this utils to apply the unique client url for the current suite + const originalCreatePgConnection = + require("@medusajs/utils/dist/modules-sdk/create-pg-connection").createPgConnection + require("@medusajs/utils/dist/modules-sdk/create-pg-connection").createPgConnection = + (options: any) => { + return originalCreatePgConnection({ + ...options, + clientUrl: dbConfig.clientUrl, + }) + } + + const originalDatabaseLoader = + require("@medusajs/medusa/dist/loaders/database").default + require("@medusajs/medusa/dist/loaders/database").default = ( + options: any + ) => { + options.configModule.projectConfig.database_url + return originalDatabaseLoader({ + ...options, + configModule: { + ...options.configModule, + projectConfig: { + database_logging: debug, // Will be used for the debug flag of the database options + ...options.configModule.projectConfig, + database_url: dbConfig.clientUrl, + }, + }, + }) + } + + const cwd = process.cwd() + + let shutdown: () => Promise + let dbUtils = dbTestUtilFactory() + let container: ContainerLike + let apiUtils: any + + let options = { + dbUtils, + api: new Proxy( + {}, + { + get: (target, prop) => { + return apiUtils[prop] + }, + } + ), + dbConnection: new Proxy( + {}, + { + get: (target, prop) => { + return dbUtils.db_[prop] + }, + } + ), + getContainer: () => container, + } as MedusaSuiteOptions + + const beforeAll_ = async () => { + try { + await dbUtils.create(dbName) + const { dbDataSource, pgConnection } = await initDb({ + cwd, + env, + force_modules_migration, + database_extra: {}, + dbUrl: dbConfig.clientUrl, + dbSchema: dbConfig.schema, + }) + dbUtils.db_ = dbDataSource + dbUtils.pgConnection_ = pgConnection + + const { + shutdown: shutdown_, + container: container_, + port, + } = await startBootstrapApp({ + cwd, + env, + }) + + apiUtils = axios.create({ baseURL: `http://localhost:${port}` }) + + container = container_ + shutdown = shutdown_ + } catch (error) { + console.error("Error setting up integration environment:", error) + } + } + + const afterEach_ = async () => { + try { + await dbUtils.teardown({ forceDelete: [], schema }) + } catch (error) { + console.error("Error tearing down database:", error) + } + } + + return describe("", () => { + beforeAll(beforeAll_) + afterEach(afterEach_) + afterAll(async () => { + try { + await dbUtils.shutdown(dbName) + await shutdown() + } catch (error) { + console.error("Error shutting down integration environment:", error) + } + }) + + testSuite(options!) + }) +} diff --git a/packages/medusa-test-utils/src/module-test-runner.ts b/packages/medusa-test-utils/src/module-test-runner.ts index ebe036aa4b..bb31aae00c 100644 --- a/packages/medusa-test-utils/src/module-test-runner.ts +++ b/packages/medusa-test-utils/src/module-test-runner.ts @@ -39,6 +39,8 @@ export function moduleIntegrationTestRunner({ debug?: boolean testSuite: (options: SuiteOptions) => () => void }) { + process.env.LOG_LEVEL = "error" + moduleModels = Object.values(require(`${process.cwd()}/src/models`)) // migrationPath ??= process.cwd() + "/src/migrations/!(*.d).{js,ts,cjs}" diff --git a/packages/medusa/src/loaders/medusa-app.ts b/packages/medusa/src/loaders/medusa-app.ts index 665bef8e67..1dc4c5836f 100644 --- a/packages/medusa/src/loaders/medusa-app.ts +++ b/packages/medusa/src/loaders/medusa-app.ts @@ -66,8 +66,12 @@ export async function migrateMedusaApp( const sharedResourcesConfig = { database: { - clientUrl: configModule.projectConfig.database_url, + clientUrl: + injectedDependencies[ContainerRegistrationKeys.PG_CONNECTION]?.client + ?.config?.connection?.connectionString ?? + configModule.projectConfig.database_url, driverOptions: configModule.projectConfig.database_extra, + debug: !!(configModule.projectConfig.database_logging ?? false), }, } @@ -85,7 +89,7 @@ export async function migrateMedusaApp( ).options ??= { database: { type: "postgres", - url: configModule.projectConfig.database_url, + url: sharedResourcesConfig.database.clientUrl, extra: configModule.projectConfig.database_extra, schema: configModule.projectConfig.database_schema, logging: configModule.projectConfig.database_logging, @@ -132,6 +136,7 @@ export const loadMedusaApp = async ( database: { clientUrl: configModule.projectConfig.database_url, driverOptions: configModule.projectConfig.database_extra, + debug: !!(configModule.projectConfig.database_logging ?? false), }, } diff --git a/packages/modules-sdk/src/medusa-app.ts b/packages/modules-sdk/src/medusa-app.ts index 124b899078..305626ad52 100644 --- a/packages/modules-sdk/src/medusa-app.ts +++ b/packages/modules-sdk/src/medusa-app.ts @@ -337,7 +337,7 @@ async function MedusaApp_({ ) } - const linkModuleOpt = { ...linkModuleOptions } + const linkModuleOpt = { ...(linkModuleOptions ?? {}) } linkModuleOpt.database ??= { ...(sharedResourcesConfig?.database ?? {}), } diff --git a/packages/modules-sdk/src/medusa-module.ts b/packages/modules-sdk/src/medusa-module.ts index 29cedd938a..39e6cf96fd 100644 --- a/packages/modules-sdk/src/medusa-module.ts +++ b/packages/modules-sdk/src/medusa-module.ts @@ -285,11 +285,14 @@ export class MedusaModule { moduleDefinition ) + const logger_ = + container.resolve("logger", { allowUnregistered: true }) ?? logger + try { await moduleLoader({ container, moduleResolutions, - logger, + logger: logger_, migrationOnly, }) } catch (err) { @@ -314,7 +317,7 @@ export class MedusaModule { ].__joinerConfig() if (!joinerConfig.primaryKeys) { - logger.warn( + logger_.warn( `Primary keys are not defined by the module ${keyName}. Setting default primary key to 'id'${EOL}` ) @@ -407,11 +410,14 @@ export class MedusaModule { moduleExports ) + const logger_ = + container.resolve("logger", { allowUnregistered: true }) ?? logger + try { await moduleLoader({ container, moduleResolutions, - logger, + logger: logger_, }) } catch (err) { errorLoading(err) diff --git a/yarn.lock b/yarn.lock index cc63a681b9..6e89889f4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8914,7 +8914,7 @@ __metadata: languageName: unknown linkType: soft -"@medusajs/types@^1.10.0, @medusajs/types@^1.11.11, @medusajs/types@^1.11.12, @medusajs/types@^1.11.13, @medusajs/types@^1.11.6, @medusajs/types@^1.11.8, @medusajs/types@^1.11.9, @medusajs/types@^1.8.10, @medusajs/types@workspace:^, @medusajs/types@workspace:packages/types": +"@medusajs/types@^1.1.41, @medusajs/types@^1.10.0, @medusajs/types@^1.11.11, @medusajs/types@^1.11.12, @medusajs/types@^1.11.13, @medusajs/types@^1.11.6, @medusajs/types@^1.11.8, @medusajs/types@^1.11.9, @medusajs/types@^1.8.10, @medusajs/types@workspace:^, @medusajs/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@medusajs/types@workspace:packages/types" dependencies: @@ -31811,6 +31811,7 @@ __metadata: medusa-fulfillment-webshipper: "workspace:*" medusa-interfaces: "workspace:*" medusa-plugin-sendgrid: "workspace:*" + medusa-test-utils: "workspace:*" pg: ^8.11.0 typeorm: ^0.3.16 languageName: unknown @@ -38296,21 +38297,41 @@ __metadata: languageName: unknown linkType: soft -"medusa-test-utils@^1.1.40, medusa-test-utils@^1.1.41, medusa-test-utils@workspace:^, medusa-test-utils@workspace:packages/medusa-test-utils": +"medusa-test-utils@^1.1.40, medusa-test-utils@^1.1.41, medusa-test-utils@workspace:*, medusa-test-utils@workspace:^, medusa-test-utils@workspace:packages/medusa-test-utils": version: 0.0.0-use.local resolution: "medusa-test-utils@workspace:packages/medusa-test-utils" dependencies: "@medusajs/modules-sdk": ^1.12.6 + "@medusajs/types": ^1.1.41 "@medusajs/utils": ^1.1.41 "@mikro-orm/migrations": 5.9.7 "@mikro-orm/postgresql": 5.9.7 cross-env: ^5.2.1 jest: ^25.5.4 medusa-core-utils: ^1.2.1 - pg-god: ^1.0.12 randomatic: ^3.1.1 rimraf: ^3.0.2 typescript: ^5.1.6 + peerDependencies: + "@medusajs/medusa": ">1.19" + axios: ^0.28.0 + express: ^4.18.3 + get-port: ^5.1.0 + pg-god: ^1.0.12 + typeorm: ^0.2.43 + peerDependenciesMeta: + "@medusajs/medusa": + optional: true + axios: + optional: true + express: + optional: true + get-port: + optional: true + pg-god: + optional: true + typeorm: + optional: true languageName: unknown linkType: soft