Add tests for REST pagination

This commit is contained in:
Andrew Kingston 2022-01-07 10:49:31 +00:00
parent 422c0a3033
commit bf22c5130f
2 changed files with 293 additions and 34 deletions

View File

@ -218,13 +218,13 @@ module RestModule {
} }
addBody(bodyType: string, body: string | any, input: any, pagination: PaginationConfig | null, paginationValues: PaginationValues | null) { addBody(bodyType: string, body: string | any, input: any, pagination: PaginationConfig | null, paginationValues: PaginationValues | null) {
if (bodyType === BodyTypes.NONE) {
return input
}
if (!input.headers) { if (!input.headers) {
input.headers = {} input.headers = {}
} }
let error, object = {}, string = "" if (bodyType === BodyTypes.NONE) {
return input
}
let error, object: any = {}, string = ""
try { try {
if (body) { if (body) {
string = typeof body !== "string" ? JSON.stringify(body) : body string = typeof body !== "string" ? JSON.stringify(body) : body
@ -278,19 +278,15 @@ module RestModule {
input.body = string input.body = string
input.headers["Content-Type"] = "application/xml" input.headers["Content-Type"] = "application/xml"
break break
default:
case BodyTypes.JSON: case BodyTypes.JSON:
// if JSON error, throw it // if JSON error, throw it
if (error) { if (error) {
throw "Invalid JSON for request body" throw "Invalid JSON for request body"
} }
if (!body) {
body = {}
}
addPaginationToBody((key: string, value: any) => { addPaginationToBody((key: string, value: any) => {
body[key] = value object[key] = value
}) })
input.body = JSON.stringify(body) input.body = JSON.stringify(object)
input.headers["Content-Type"] = "application/json" input.headers["Content-Type"] = "application/json"
break break
} }

View File

@ -4,19 +4,23 @@ jest.mock("node-fetch", () =>
raw: () => { raw: () => {
return { "content-type": ["application/json"] } return { "content-type": ["application/json"] }
}, },
get: () => ["application/json"] get: () => ["application/json"],
}, },
json: jest.fn(), json: jest.fn(() => ({
text: jest.fn() my_next_cursor: 123,
})),
text: jest.fn(),
})) }))
) )
const fetch = require("node-fetch") const fetch = require("node-fetch")
const RestIntegration = require("../rest") const RestIntegration = require("../rest")
const { AuthType } = require("../rest") const { AuthType } = require("../rest")
const FormData = require("form-data")
const { URLSearchParams } = require("url")
const HEADERS = { const HEADERS = {
"Accept": "application/json", Accept: "application/json",
"Content-Type": "application/json" "Content-Type": "application/json",
} }
class TestConfiguration { class TestConfiguration {
@ -165,17 +169,20 @@ describe("REST Integration", () => {
status: 200, status: 200,
json: json ? async () => json : undefined, json: json ? async () => json : undefined,
text: text ? async () => text : undefined, text: text ? async () => text : undefined,
headers: { get: key => key === "content-length" ? 100 : header, raw: () => ({ "content-type": header }) } headers: {
get: key => (key === "content-length" ? 100 : header),
raw: () => ({ "content-type": header }),
},
} }
} }
it("should be able to parse JSON response", async () => { it("should be able to parse JSON response", async () => {
const input = buildInput({a: 1}, null, "application/json") const input = buildInput({ a: 1 }, null, "application/json")
const output = await config.integration.parseResponse(input) const output = await config.integration.parseResponse(input)
expect(output.data).toEqual({a: 1}) expect(output.data).toEqual({ a: 1 })
expect(output.info.code).toEqual(200) expect(output.info.code).toEqual(200)
expect(output.info.size).toEqual("100B") expect(output.info.size).toEqual("100B")
expect(output.extra.raw).toEqual(JSON.stringify({a: 1})) expect(output.extra.raw).toEqual(JSON.stringify({ a: 1 }))
expect(output.extra.headers["content-type"]).toEqual("application/json") expect(output.extra.headers["content-type"]).toEqual("application/json")
}) })
@ -192,7 +199,7 @@ describe("REST Integration", () => {
const text = "<root><a>1</a><b>2</b></root>" const text = "<root><a>1</a><b>2</b></root>"
const input = buildInput(null, text, "application/xml") const input = buildInput(null, text, "application/xml")
const output = await config.integration.parseResponse(input) const output = await config.integration.parseResponse(input)
expect(output.data).toEqual({a: "1", b: "2"}) expect(output.data).toEqual({ a: "1", b: "2" })
expect(output.extra.raw).toEqual(text) expect(output.extra.raw).toEqual(text)
expect(output.extra.headers["content-type"]).toEqual("application/xml") expect(output.extra.headers["content-type"]).toEqual("application/xml")
}) })
@ -202,53 +209,309 @@ describe("REST Integration", () => {
const basicAuth = { const basicAuth = {
_id: "c59c14bd1898a43baa08da68959b24686", _id: "c59c14bd1898a43baa08da68959b24686",
name: "basic-1", name: "basic-1",
type : AuthType.BASIC, type: AuthType.BASIC,
config : { config: {
username: "user", username: "user",
password: "password" password: "password",
} },
} }
const bearerAuth = { const bearerAuth = {
_id: "0d91d732f34e4befabeff50b392a8ff3", _id: "0d91d732f34e4befabeff50b392a8ff3",
name: "bearer-1", name: "bearer-1",
type : AuthType.BEARER, type: AuthType.BEARER,
config : { config: {
"token": "mytoken" token: "mytoken",
} },
} }
beforeEach(() => { beforeEach(() => {
config = new TestConfiguration({ config = new TestConfiguration({
url: BASE_URL, url: BASE_URL,
authConfigs : [basicAuth, bearerAuth] authConfigs: [basicAuth, bearerAuth],
}) })
}) })
it("adds basic auth", async () => { it("adds basic auth", async () => {
const query = { const query = {
authConfigId: "c59c14bd1898a43baa08da68959b24686" authConfigId: "c59c14bd1898a43baa08da68959b24686",
} }
await config.integration.read(query) await config.integration.read(query)
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/?`, { expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/?`, {
method: "GET", method: "GET",
headers: { headers: {
Authorization: "Basic dXNlcjpwYXNzd29yZA==" Authorization: "Basic dXNlcjpwYXNzd29yZA==",
}, },
}) })
}) })
it("adds bearer auth", async () => { it("adds bearer auth", async () => {
const query = { const query = {
authConfigId: "0d91d732f34e4befabeff50b392a8ff3" authConfigId: "0d91d732f34e4befabeff50b392a8ff3",
} }
await config.integration.read(query) await config.integration.read(query)
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/?`, { expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/?`, {
method: "GET", method: "GET",
headers: { headers: {
Authorization: "Bearer mytoken" Authorization: "Bearer mytoken",
}, },
}) })
}) })
}) })
describe("page based pagination", () => {
it("can paginate using query params", async () => {
const pageParam = "my_page_param"
const sizeParam = "my_size_param"
const pageValue = 3
const sizeValue = 10
const query = {
path: "api",
pagination: {
type: "page",
location: "query",
pageParam,
sizeParam,
},
paginationValues: {
page: pageValue,
limit: sizeValue,
},
}
await config.integration.read(query)
expect(fetch).toHaveBeenCalledWith(
`${BASE_URL}/api?${pageParam}=${pageValue}&${sizeParam}=${sizeValue}&`,
{
headers: {},
method: "GET",
}
)
})
it("can paginate using JSON request body", async () => {
const pageParam = "my_page_param"
const sizeParam = "my_size_param"
const pageValue = 3
const sizeValue = 10
const query = {
bodyType: "json",
path: "api",
pagination: {
type: "page",
location: "body",
pageParam,
sizeParam,
},
paginationValues: {
page: pageValue,
limit: sizeValue,
},
}
await config.integration.create(query)
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?`, {
body: JSON.stringify({
[pageParam]: pageValue,
[sizeParam]: sizeValue,
}),
headers: {
"Content-Type": "application/json",
},
method: "POST",
})
})
it("can paginate using form-data request body", async () => {
const pageParam = "my_page_param"
const sizeParam = "my_size_param"
const pageValue = 3
const sizeValue = 10
const query = {
bodyType: "form",
path: "api",
pagination: {
type: "page",
location: "body",
pageParam,
sizeParam,
},
paginationValues: {
page: pageValue,
limit: sizeValue,
},
}
await config.integration.create(query)
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?`, {
body: expect.any(FormData),
headers: {},
method: "POST",
})
const sentData = JSON.stringify(fetch.mock.calls[0][1].body)
expect(sentData).toContain(pageParam)
expect(sentData).toContain(sizeParam)
})
it("can paginate using form-encoded request body", async () => {
const pageParam = "my_page_param"
const sizeParam = "my_size_param"
const pageValue = 3
const sizeValue = 10
const query = {
bodyType: "encoded",
path: "api",
pagination: {
type: "page",
location: "body",
pageParam,
sizeParam,
},
paginationValues: {
page: pageValue,
limit: sizeValue,
},
}
await config.integration.create(query)
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?`, {
body: expect.any(URLSearchParams),
headers: {},
method: "POST",
})
const sentData = fetch.mock.calls[0][1].body
expect(sentData.has(pageParam))
expect(sentData.get(pageParam)).toEqual(pageValue.toString())
expect(sentData.has(sizeParam))
expect(sentData.get(sizeParam)).toEqual(sizeValue.toString())
})
})
describe("cursor based pagination", () => {
it("can paginate using query params", async () => {
const pageParam = "my_page_param"
const sizeParam = "my_size_param"
const pageValue = 3
const sizeValue = 10
const query = {
path: "api",
pagination: {
type: "cursor",
location: "query",
pageParam,
sizeParam,
responseParam: "my_next_cursor",
},
paginationValues: {
page: pageValue,
limit: sizeValue,
},
}
const res = await config.integration.read(query)
expect(fetch).toHaveBeenCalledWith(
`${BASE_URL}/api?${pageParam}=${pageValue}&${sizeParam}=${sizeValue}&`,
{
headers: {},
method: "GET",
}
)
expect(res.pagination.cursor).toEqual(123)
})
it("can paginate using JSON request body", async () => {
const pageParam = "my_page_param"
const sizeParam = "my_size_param"
const pageValue = 3
const sizeValue = 10
const query = {
bodyType: "json",
path: "api",
pagination: {
type: "page",
location: "body",
pageParam,
sizeParam,
responseParam: "my_next_cursor",
},
paginationValues: {
page: pageValue,
limit: sizeValue,
},
}
const res = await config.integration.create(query)
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?`, {
body: JSON.stringify({
[pageParam]: pageValue,
[sizeParam]: sizeValue,
}),
headers: {
"Content-Type": "application/json",
},
method: "POST",
})
expect(res.pagination.cursor).toEqual(123)
})
it("can paginate using form-data request body", async () => {
const pageParam = "my_page_param"
const sizeParam = "my_size_param"
const pageValue = 3
const sizeValue = 10
const query = {
bodyType: "form",
path: "api",
pagination: {
type: "page",
location: "body",
pageParam,
sizeParam,
responseParam: "my_next_cursor",
},
paginationValues: {
page: pageValue,
limit: sizeValue,
},
}
const res = await config.integration.create(query)
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?`, {
body: expect.any(FormData),
headers: {},
method: "POST",
})
const sentData = JSON.stringify(fetch.mock.calls[0][1].body)
expect(sentData).toContain(pageParam)
expect(sentData).toContain(sizeParam)
expect(res.pagination.cursor).toEqual(123)
})
it("can paginate using form-encoded request body", async () => {
const pageParam = "my_page_param"
const sizeParam = "my_size_param"
const pageValue = 3
const sizeValue = 10
const query = {
bodyType: "encoded",
path: "api",
pagination: {
type: "page",
location: "body",
pageParam,
sizeParam,
responseParam: "my_next_cursor",
},
paginationValues: {
page: pageValue,
limit: sizeValue,
},
}
const res = await config.integration.create(query)
expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?`, {
body: expect.any(URLSearchParams),
headers: {},
method: "POST",
})
const sentData = fetch.mock.calls[0][1].body
expect(sentData.has(pageParam))
expect(sentData.get(pageParam)).toEqual(pageValue.toString())
expect(sentData.has(sizeParam))
expect(sentData.get(sizeParam)).toEqual(sizeValue.toString())
expect(res.pagination.cursor).toEqual(123)
})
})
}) })