const jwt = require("jsonwebtoken") const path = require("path") const { Address, Customer, Order, Region } = require("@medusajs/medusa") const setupServer = require("../../../environment-helpers/setup-server") const { useApi } = require("../../../environment-helpers/use-api") const { initDb, useDb } = require("../../../environment-helpers/use-db") const { simpleOrderFactory } = require("../../../factories") jest.setTimeout(30000) describe("/store/customers", () => { let medusaProcess let dbConnection const doAfterEach = async () => { const db = useDb() await db.teardown() } beforeAll(async () => { const cwd = path.resolve(path.join(__dirname, "..", "..")) dbConnection = await initDb({ cwd }) medusaProcess = await setupServer({ cwd }) }) afterAll(async () => { const db = useDb() await db.shutdown() medusaProcess.kill() }) describe("POST /store/customers/confirm-claim", () => { let orderId beforeEach(async () => { const manager = dbConnection.manager await manager.insert(Customer, { id: "test_customer", first_name: "John", last_name: "Deere", email: "john@deere.com", password_hash: "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" has_account: true, }) await manager.insert(Customer, { id: "test_customer-1", first_name: "John", last_name: "Deere", email: "john@deere.com", }) const order = await simpleOrderFactory(dbConnection, { customer: { id: "test_customer-1", }, }) orderId = order.id }) afterEach(async () => { await doAfterEach() }) it("Successfully confirms a claim ", async () => { const api = useApi() const token = jwt.sign( { claimingCustomerId: "test_customer", orders: [orderId], }, "test" ) const authResponse = await api.post("/store/auth", { email: "john@deere.com", password: "test", }) const [authCookie] = authResponse.headers["set-cookie"][0].split(";") const authHeader = { headers: { Cookie: authCookie, }, } const ordersRes1 = await api.get(`/store/customers/me/orders`, authHeader) expect(ordersRes1.data.orders.length).toEqual(0) const response = await api.post("/store/orders/customer/confirm", { token, }) expect(response.status).toBe(200) const ordersRes2 = await api.get(`/store/customers/me/orders`, authHeader) expect(ordersRes2.data.orders.length).toEqual(1) }) }) describe("POST /store/customers", () => { beforeEach(async () => { const manager = dbConnection.manager await manager.insert(Customer, { id: "test_customer", first_name: "John", last_name: "Deere", email: "john@deere.com", has_account: true, }) }) afterEach(async () => { await doAfterEach() }) it("creates a customer", async () => { const api = useApi() const response = await api.post("/store/customers", { first_name: "James", last_name: "Bond", email: "james@bond.com", password: "test", }) expect(response.status).toEqual(200) expect(response.data.customer).not.toHaveProperty("password_hash") }) it("normalizes email", async () => { const api = useApi() const response = await api.post("/store/customers", { first_name: "James", last_name: "Bond", email: "James@Bond.com", password: "test", }) expect(response.status).toEqual(200) expect(response.data.customer).not.toHaveProperty("password_hash") expect(response.data.customer.email).toEqual("james@bond.com") }) it("responds 422 on duplicate", async () => { const api = useApi() const response = await api .post("/store/customers", { first_name: "James", last_name: "Bond", email: "john@deere.com", password: "test", }) .catch((err) => err.response) expect(response.status).toEqual(422) }) }) describe("GET /store/customers/me/orders", () => { beforeEach(async () => { const manager = dbConnection.manager await manager.query(`ALTER SEQUENCE order_display_id_seq RESTART WITH 1`) await manager.insert(Address, { id: "addr_test", first_name: "String", last_name: "Stringson", address_1: "String st", city: "Stringville", postal_code: "1236", province: "ca", country_code: "us", }) await manager.insert(Region, { id: "region", name: "Test Region", currency_code: "usd", tax_rate: 0, }) await manager.insert(Customer, { id: "test_customer", first_name: "John", last_name: "Deere", email: "john@deere.com", password_hash: "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" has_account: true, }) await manager.insert(Customer, { id: "test_customer1", first_name: "John", last_name: "Deere", email: "joh1n@deere.com", password_hash: "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" has_account: true, }) await manager.insert(Order, { id: "order_test_completed", email: "test1@email.com", display_id: 1, customer_id: "test_customer", region_id: "region", status: "completed", tax_rate: 0, currency_code: "usd", }) await manager.insert(Order, { id: "order_test_completed1", email: "test1@email.com", display_id: 2, customer_id: "test_customer1", region_id: "region", status: "completed", tax_rate: 0, currency_code: "usd", }) await manager.insert(Order, { id: "order_test_canceled", email: "test1@email.com", display_id: 3, customer_id: "test_customer", region_id: "region", status: "canceled", tax_rate: 0, currency_code: "usd", }) }) afterEach(async () => { await doAfterEach() }) it("looks up completed orders", async () => { const api = useApi() const authResponse = await api.post("/store/auth", { email: "john@deere.com", password: "test", }) const [authCookie] = authResponse.headers["set-cookie"][0].split(";") const response = await api .get("/store/customers/me/orders?status[]=completed", { headers: { Cookie: authCookie, }, }) .catch((err) => { return err.response }) expect(response.status).toEqual(200) expect(response.data.orders[0].display_id).toEqual(1) expect(response.data.orders[0].email).toEqual("test1@email.com") expect(response.data.orders.length).toEqual(1) }) it("looks up cancelled and completed orders", async () => { const api = useApi() const authResponse = await api.post("/store/auth", { email: "john@deere.com", password: "test", }) const [authCookie] = authResponse.headers["set-cookie"][0].split(";") const response = await api .get( "/store/customers/me/orders?status[]=completed&status[]=canceled", { headers: { Cookie: authCookie, }, } ) .catch((err) => { return console.log(err.response.data.message) }) expect(response.status).toEqual(200) expect(response.data.orders.length).toEqual(2) expect(response.data.orders).toEqual( expect.arrayContaining([ expect.objectContaining({ display_id: 3, status: "canceled", }), expect.objectContaining({ display_id: 1, status: "completed", }), ]) ) expect(response.data.orders.length).toEqual(2) }) }) describe("POST /store/customers/me", () => { beforeEach(async () => { const manager = dbConnection.manager await manager.insert(Address, { id: "addr_test", first_name: "String", last_name: "Stringson", address_1: "String st", city: "Stringville", postal_code: "1236", province: "ca", country_code: "us", }) await manager.insert(Customer, { id: "test_customer", first_name: "John", last_name: "Deere", email: "john@deere.com", password_hash: "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" has_account: true, }) }) afterEach(async () => { await doAfterEach() }) it("updates a customer", async () => { const api = useApi() const authResponse = await api.post("/store/auth", { email: "john@deere.com", password: "test", }) const [authCookie] = authResponse.headers["set-cookie"][0].split(";") const response = await api .post( `/store/customers/me`, { password: "test", metadata: { key: "value" }, }, { headers: { Cookie: authCookie, }, } ) .catch((e) => console.log("err", e)) expect(response.status).toEqual(200) expect(response.data.customer).not.toHaveProperty("password_hash") expect(response.data.customer).toEqual( expect.objectContaining({ metadata: { key: "value" }, }) ) }) it("updates customer billing address", async () => { const api = useApi() const authResponse = await api.post("/store/auth", { email: "john@deere.com", password: "test", }) const [authCookie] = authResponse.headers["set-cookie"][0].split(";") const response = await api.post( `/store/customers/me`, { billing_address: { first_name: "test", last_name: "testson", address_1: "Test st", city: "Testion", postal_code: "1235", province: "ca", country_code: "us", }, }, { headers: { Cookie: authCookie, }, } ) expect(response.status).toEqual(200) expect(response.data.customer).not.toHaveProperty("password_hash") expect(response.data.customer.billing_address).toEqual( expect.objectContaining({ first_name: "test", last_name: "testson", address_1: "Test st", city: "Testion", postal_code: "1235", province: "ca", country_code: "us", }) ) }) it("updates customer billing address with string", async () => { const api = useApi() const authResponse = await api.post("/store/auth", { email: "john@deere.com", password: "test", }) const [authCookie] = authResponse.headers["set-cookie"][0].split(";") const response = await api.post( `/store/customers/me`, { billing_address: "addr_test", }, { headers: { Cookie: authCookie, }, } ) expect(response.status).toEqual(200) expect(response.data.customer).not.toHaveProperty("password_hash") expect(response.data.customer.billing_address).toEqual( expect.objectContaining({ first_name: "String", last_name: "Stringson", address_1: "String st", city: "Stringville", postal_code: "1236", province: "ca", country_code: "us", }) ) }) it("unsets customer billing address", async () => { const api = useApi() const authResponse = await api.post("/store/auth", { email: "john@deere.com", password: "test", }) const [authCookie] = authResponse.headers["set-cookie"][0].split(";") const check = await api.post( `/store/customers/me`, { billing_address: "addr_test", }, { headers: { Cookie: authCookie, }, } ) expect(check.status).toEqual(200) expect(check.data.customer.billing_address_id).toEqual("addr_test") const response = await api.post( `/store/customers/me`, { billing_address: null, }, { headers: { Cookie: authCookie, }, } ) expect(response.status).toEqual(200) expect(response.data.customer.billing_address_id).toEqual(null) }) }) describe("POST /store/customers/password-token", () => { beforeEach(async () => { const manager = dbConnection.manager await manager.insert(Customer, { id: "test_customer", first_name: "John", last_name: "Deere", email: "john@deere.com", password_hash: "c2NyeXB0AAEAAAABAAAAAVMdaddoGjwU1TafDLLlBKnOTQga7P2dbrfgf3fB+rCD/cJOMuGzAvRdKutbYkVpuJWTU39P7OpuWNkUVoEETOVLMJafbI8qs8Qx/7jMQXkN", // password matching "test" has_account: true, }) }) afterEach(async () => { await doAfterEach() }) it("creates token", async () => { const api = useApi() const response = await api.post(`/store/customers/password-token`, { email: "john@deere.com", }) expect(response.status).toEqual(204) }) it("Returns 204 for non-existent customer", async () => { const api = useApi() const response = await api.post(`/store/customers/password-token`, { email: "non-existent@test.com", }) expect(response.status).toEqual(204) }) }) describe("POST /store/customers/password-reset", () => { afterEach(async () => { await doAfterEach() }) it("Returns 204 for non-existent customer", async () => { const api = useApi() const response = await api .post(`/store/customers/password-reset`, { email: "non-existent@test.com", token: "token", password: "password", }) .catch((error) => { return error }) expect(response.response.status).toEqual(401) expect(response.response.data).toEqual({ type: "unauthorized", message: "Invalid or expired password reset token", }) }) }) })