docs: added authentication in integration tests (#11363)
This commit is contained in:
+197
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Prerequisites } from "docs-ui"
|
import { Prerequisites, CodeTabs, CodeTab } from "docs-ui"
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: `${pageNumber} Example: Write Integration Tests for API Routes`,
|
title: `${pageNumber} Example: Write Integration Tests for API Routes`,
|
||||||
@@ -312,6 +312,8 @@ Some requests require passing headers. For example, all routes prefixed with `/s
|
|||||||
|
|
||||||
The `get`, `post`, and `delete` methods accept an optional third parameter that you can pass a `headers` property to, whose value is an object of headers to pass in the request.
|
The `get`, `post`, and `delete` methods accept an optional third parameter that you can pass a `headers` property to, whose value is an object of headers to pass in the request.
|
||||||
|
|
||||||
|
### Pass Publishable API Key
|
||||||
|
|
||||||
For example, to pass a publishable API key in the header for a request to a `/store` route:
|
For example, to pass a publishable API key in the header for a request to a `/store` route:
|
||||||
|
|
||||||
export const headersHighlights = [
|
export const headersHighlights = [
|
||||||
@@ -367,3 +369,197 @@ jest.setTimeout(60 * 1000)
|
|||||||
In your test suit, you add a `beforeAll` hook to create a publishable API key before the tests run. To create the API key, you can use the `createApiKeysWorkflow` or the [API Key Module's service](!resources!/commerce-modules/api-key).
|
In your test suit, you add a `beforeAll` hook to create a publishable API key before the tests run. To create the API key, you can use the `createApiKeysWorkflow` or the [API Key Module's service](!resources!/commerce-modules/api-key).
|
||||||
|
|
||||||
Then, in the test, you pass an object as the last parameter to `api.get` with a `headers` property. The `headers` property is an object with the key `x-publishable-api-key` and the value of the API key's token.
|
Then, in the test, you pass an object as the last parameter to `api.get` with a `headers` property. The `headers` property is an object with the key `x-publishable-api-key` and the value of the API key's token.
|
||||||
|
|
||||||
|
### Send Authenticated Requests
|
||||||
|
|
||||||
|
If your custom route is accessible by authenticated users only, such as routes prefixed by `/admin` or `/store/customers/me`, you can create a test customer or user, generate a JWT token for them, and pass the token in the request's Authorization header.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
<Note title="Tip">
|
||||||
|
|
||||||
|
For custom actor types, you only need to change the `actorType` value in the `jwt.sign` method.
|
||||||
|
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
<CodeTabs group="user-type">
|
||||||
|
<CodeTab label="Admin User" value="admin">
|
||||||
|
|
||||||
|
export const adminHighlights = [
|
||||||
|
["8", "headers", "Define the headers that you'll pass in the request."],
|
||||||
|
["10", "beforeEach", "Run before every test."],
|
||||||
|
["16", "user", "Create the admin user."],
|
||||||
|
["20", "authIdentity", "Create the auth identity for the user."],
|
||||||
|
["35", "token", "Generate a JWT token for the user."],
|
||||||
|
["47", "headers", "Set the token in the Authorization header."],
|
||||||
|
["52", "headers", "Pass the headers to the request."]
|
||||||
|
]
|
||||||
|
|
||||||
|
```ts title="integration-tests/http/custom-routes.spec.ts" highlights={adminHighlights}
|
||||||
|
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
||||||
|
import jwt from "jsonwebtoken"
|
||||||
|
|
||||||
|
medusaIntegrationTestRunner({
|
||||||
|
testSuite: ({ api, getContainer }) => {
|
||||||
|
describe("Custom endpoints", () => {
|
||||||
|
describe("GET /custom", () => {
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
}
|
||||||
|
beforeEach(async () => {
|
||||||
|
const container = getContainer()
|
||||||
|
|
||||||
|
const authModuleService = container.resolve("auth")
|
||||||
|
const userModuleService = container.resolve("user")
|
||||||
|
|
||||||
|
const user = await userModuleService.createUsers({
|
||||||
|
email: "admin@medusa.js",
|
||||||
|
|
||||||
|
})
|
||||||
|
const authIdentity = await authModuleService.createAuthIdentities({
|
||||||
|
provider_identities: [
|
||||||
|
{
|
||||||
|
provider: "emailpass",
|
||||||
|
entity_id: "admin@medusa.js",
|
||||||
|
provider_metadata: {
|
||||||
|
password: "supersecret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
app_metadata: {
|
||||||
|
user_id: user.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const token = jwt.sign(
|
||||||
|
{
|
||||||
|
actor_id: user.id,
|
||||||
|
actor_type: "user",
|
||||||
|
auth_identity_id: authIdentity.id,
|
||||||
|
},
|
||||||
|
"supersecret",
|
||||||
|
{
|
||||||
|
expiresIn: "1d",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
headers["authorization"] = `Bearer ${token}`
|
||||||
|
})
|
||||||
|
it("returns correct message", async () => {
|
||||||
|
const response = await api.get(
|
||||||
|
`/admin/custom`,
|
||||||
|
{ headers }
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
jest.setTimeout(60 * 1000)
|
||||||
|
```
|
||||||
|
|
||||||
|
</CodeTab>
|
||||||
|
<CodeTab label="Customer User" value="customer">
|
||||||
|
|
||||||
|
export const customerHighlights = [
|
||||||
|
["10", "headers", "Define the headers that you'll pass in the request."],
|
||||||
|
["12", "beforeEach", "Run before every test."],
|
||||||
|
["18", "customer", "Create the customer."],
|
||||||
|
["22", "authIdentity", "Create the auth identity for the customer."],
|
||||||
|
["37", "token", "Generate a JWT token for the customer."],
|
||||||
|
["49", "headers", "Set the token in the Authorization header."],
|
||||||
|
["52", "pak", "Create a publishable API key"],
|
||||||
|
["64", "headers", "Set the publishable API key in the request's header."],
|
||||||
|
["69", "headers", "Pass the headers to the request."]
|
||||||
|
]
|
||||||
|
|
||||||
|
```ts title="integration-tests/http/custom-routes.spec.ts" highlights={customerHighlights}
|
||||||
|
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
|
||||||
|
import { ApiKeyDTO } from "@medusajs/framework/types"
|
||||||
|
import jwt from "jsonwebtoken"
|
||||||
|
import { createApiKeysWorkflow } from "@medusajs/medusa/core-flows"
|
||||||
|
|
||||||
|
medusaIntegrationTestRunner({
|
||||||
|
testSuite: ({ api, getContainer }) => {
|
||||||
|
describe("Custom endpoints", () => {
|
||||||
|
describe("GET /custom", () => {
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
}
|
||||||
|
beforeEach(async () => {
|
||||||
|
const container = getContainer()
|
||||||
|
|
||||||
|
const authModuleService = container.resolve("auth")
|
||||||
|
const customerModuleService = container.resolve("customer")
|
||||||
|
|
||||||
|
const customer = await customerModuleService.createCustomers({
|
||||||
|
email: "admin@medusa.js",
|
||||||
|
|
||||||
|
})
|
||||||
|
const authIdentity = await authModuleService.createAuthIdentities({
|
||||||
|
provider_identities: [
|
||||||
|
{
|
||||||
|
provider: "emailpass",
|
||||||
|
entity_id: "customer@medusa.js",
|
||||||
|
provider_metadata: {
|
||||||
|
password: "supersecret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
app_metadata: {
|
||||||
|
user_id: customer.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const token = jwt.sign(
|
||||||
|
{
|
||||||
|
actor_id: customer.id,
|
||||||
|
actor_type: "customer",
|
||||||
|
auth_identity_id: authIdentity.id,
|
||||||
|
},
|
||||||
|
"supersecret",
|
||||||
|
{
|
||||||
|
expiresIn: "1d",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
headers["authorization"] = `Bearer ${token}`
|
||||||
|
|
||||||
|
|
||||||
|
const pak = (await createApiKeysWorkflow(getContainer()).run({
|
||||||
|
input: {
|
||||||
|
api_keys: [
|
||||||
|
{
|
||||||
|
type: "publishable",
|
||||||
|
title: "Test Key",
|
||||||
|
created_by: ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})).result[0]
|
||||||
|
|
||||||
|
headers["x-publishable-api-key"] = pak.token
|
||||||
|
})
|
||||||
|
it("returns correct message", async () => {
|
||||||
|
const response = await api.get(
|
||||||
|
`/store/customers/me/custom`,
|
||||||
|
{ headers }
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
jest.setTimeout(60 * 1000)
|
||||||
|
```
|
||||||
|
|
||||||
|
</CodeTab>
|
||||||
|
</CodeTabs>
|
||||||
|
|
||||||
|
In the test suite, you add a `beforeEach` hook that creates a user or customer, an auth identity, and generates a JWT token for them. The JWT token is then set in the `Authorization` header of the request.
|
||||||
|
|
||||||
|
You also create and pass a publishable API key in the header for the customer as it's required for requests to `/store` routes. Learn more in [this section](#pass-publishable-api-key).
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export const generatedEditDates = {
|
|||||||
"app/learn/fundamentals/data-models/index/page.mdx": "2024-10-21T13:30:21.368Z",
|
"app/learn/fundamentals/data-models/index/page.mdx": "2024-10-21T13:30:21.368Z",
|
||||||
"app/learn/fundamentals/custom-cli-scripts/page.mdx": "2024-10-23T07:08:55.898Z",
|
"app/learn/fundamentals/custom-cli-scripts/page.mdx": "2024-10-23T07:08:55.898Z",
|
||||||
"app/learn/fundamentals/data-models/property-types/page.mdx": "2024-12-12T10:41:32.999Z",
|
"app/learn/fundamentals/data-models/property-types/page.mdx": "2024-12-12T10:41:32.999Z",
|
||||||
"app/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx": "2025-01-31T13:19:02.586Z",
|
"app/learn/debugging-and-testing/testing-tools/integration-tests/api-routes/page.mdx": "2025-02-07T12:16:51.237Z",
|
||||||
"app/learn/debugging-and-testing/testing-tools/integration-tests/page.mdx": "2024-12-09T15:52:01.019Z",
|
"app/learn/debugging-and-testing/testing-tools/integration-tests/page.mdx": "2024-12-09T15:52:01.019Z",
|
||||||
"app/learn/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx": "2025-01-31T13:19:02.586Z",
|
"app/learn/debugging-and-testing/testing-tools/integration-tests/workflows/page.mdx": "2025-01-31T13:19:02.586Z",
|
||||||
"app/learn/debugging-and-testing/testing-tools/page.mdx": "2025-01-31T13:19:02.587Z",
|
"app/learn/debugging-and-testing/testing-tools/page.mdx": "2025-01-31T13:19:02.587Z",
|
||||||
|
|||||||
+11435
-11274
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user