fix(medusa-plugin-brightpearl): automatic token refresh

This commit is contained in:
Sebastian Rindom
2020-09-21 18:12:02 +02:00
parent cd5e3494c6
commit 34eb53f72e
4 changed files with 121 additions and 34 deletions
@@ -21,6 +21,8 @@
"@babel/preset-env": "^7.7.5", "@babel/preset-env": "^7.7.5",
"@babel/register": "^7.7.4", "@babel/register": "^7.7.4",
"@babel/runtime": "^7.9.6", "@babel/runtime": "^7.9.6",
"axios-mock-adapter": "^1.18.2",
"axios-mock-server": "^0.19.0",
"client-sessions": "^0.8.0", "client-sessions": "^0.8.0",
"cross-env": "^7.0.2", "cross-env": "^7.0.2",
"eslint": "^6.8.0", "eslint": "^6.8.0",
@@ -1,5 +1,6 @@
import BrightpearlService from "../brightpearl" import BrightpearlService from "../brightpearl"
import Brightpearl, { mockCreateOrder } from "../../utils/brightpearl" import { mockCreateOrder } from "../../utils/brightpearl"
import MockAdapter from "axios-mock-adapter"
jest.mock("../../utils/brightpearl") jest.mock("../../utils/brightpearl")
@@ -46,6 +47,43 @@ const RegionService = {
} }
describe("BrightpearlService", () => { describe("BrightpearlService", () => {
describe("getClient", () => {
it("creates client", async () => {
const oauth = {
refreshToken: () => {
return Promise.resolve({
access_token: "good",
})
},
retrieveByName: () => {
return Promise.resolve({
data: {
access_token: "bad",
},
})
},
}
const bpService = new BrightpearlService({ oauthService: oauth }, {})
const client = await bpService.getClient()
const mockServer = new MockAdapter(client.client)
mockServer.onGet("/success").reply(() => {
return [200]
})
mockServer.onGet("/fail").reply((req) => {
if (req.headers.Authorization === "Bearer good") {
return [200]
}
return [401]
})
await client.test.fail()
await client.test.fail()
})
})
describe("createSalesOrder", () => { describe("createSalesOrder", () => {
const order = { const order = {
items: [ items: [
@@ -26,10 +26,6 @@ class BrightpearlService extends BaseService {
} }
async getClient() { async getClient() {
if (this.brightpearlClient_) {
return this.brightpearlClient_
}
const authData = await this.oauthService_.retrieveByName("brightpearl") const authData = await this.oauthService_.retrieveByName("brightpearl")
const { data } = authData const { data } = authData
@@ -60,7 +56,6 @@ class BrightpearlService extends BaseService {
) )
this.authData_ = data this.authData_ = data
this.brightpearlClient_ = client
return client return client
} }
@@ -1,37 +1,89 @@
import axios from "axios"
export const mockCreateOrder = jest export const mockCreateOrder = jest
.fn() .fn()
.mockReturnValue(Promise.resolve("1234")) .mockReturnValue(Promise.resolve("1234"))
const mock = jest.fn().mockImplementation(() => { const mock = jest.fn().mockImplementation(function (options, onRefresh) {
return { this.token_ = options.access_token
warehouses: { this.client = axios.create({
createReservation: jest.fn().mockReturnValue(Promise.resolve()), baseURL: `https://mock.com`,
}, headers: {
payments: { "brightpearl-app-ref": "medusa-dev",
create: jest.fn().mockReturnValue(Promise.resolve()), "brightpearl-dev-ref": "sebrindom",
},
orders: {
create: mockCreateOrder,
retrieve: jest.fn().mockReturnValue(Promise.resolve()),
},
products: {
retrieveBySKU: jest.fn().mockReturnValue(
Promise.resolve({
productId: 1234,
})
),
},
customers: {
retrieveByEmail: jest.fn().mockReturnValue(
Promise.resolve([
{
primaryEmail: "test@example.com",
contactId: "12345",
},
])
),
}, },
})
this.updateAuth = (data) => {
this.token_ = data.access_token
} }
this.client.interceptors.request.use((request) => {
const token = this.token_
if (token) {
request.headers["Authorization"] = `Bearer ${token}`
}
return request
})
this.client.interceptors.response.use(undefined, async (error) => {
const response = error.response
if (response) {
if (
response.status === 401 &&
error.config &&
!error.config.__isRetryRequest
) {
try {
await onRefresh(this)
} catch (authError) {
// refreshing has failed, but report the original error, i.e. 401
return Promise.reject(error)
}
// retry the original request
error.config.__isRetryRequest = true
return this.client(error.config)
}
}
return Promise.reject(error)
})
this.test = {
success: () => this.client.get("/success"),
fail: () => this.client.get("/fail"),
}
this.warehouses = {
createReservation: jest.fn().mockReturnValue(Promise.resolve()),
}
this.payments = {
create: jest.fn().mockReturnValue(Promise.resolve()),
}
this.orders = {
create: mockCreateOrder,
retrieve: jest.fn().mockReturnValue(Promise.resolve()),
}
this.products = {
retrieveBySKU: jest.fn().mockReturnValue(
Promise.resolve({
productId: 1234,
})
),
}
this.customers = {
retrieveByEmail: jest.fn().mockReturnValue(
Promise.resolve([
{
primaryEmail: "test@example.com",
contactId: "12345",
},
])
),
}
return this
}) })
export default mock export default mock