Skip to content

Commit

Permalink
Unexpected token when export data (#10721)
Browse files Browse the repository at this point in the history
* Tidy ID string for JSON parse

* Display error for composite keys

* Unit test WIP

* directly assign the mock function on the datasource

* Unit tests for exportRows ID handling

---------

Co-authored-by: Martin McKeaveney <martinmckeaveney@gmail.com>
  • Loading branch information
melohagan and shogunpurple committed Jun 9, 2023
1 parent a98b70b commit a3fdd46
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 3 deletions.
12 changes: 9 additions & 3 deletions packages/server/src/api/controllers/row/external.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,15 @@ export async function exportRows(ctx: UserCtx) {
ctx.request.body = {
query: {
oneOf: {
_id: ctx.request.body.rows.map(
(row: string) => JSON.parse(decodeURI(row))[0]
),
_id: ctx.request.body.rows.map((row: string) => {
const ids = JSON.parse(
decodeURI(row).replace(/'/g, `"`).replace(/%2C/g, ",")
)
if (ids.length > 1) {
ctx.throw(400, "Export data does not support composite keys.")
}
return ids[0]
}),
},
},
}
Expand Down
120 changes: 120 additions & 0 deletions packages/server/src/api/controllers/tests/row.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { exportRows } from "../row/external"
import sdk from "../../../sdk"
import { ExternalRequest } from "../row/ExternalRequest"

// @ts-ignore
sdk.datasources = {
get: jest.fn(),
}

jest.mock("../row/ExternalRequest")
jest.mock("../view/exporters", () => ({
csv: jest.fn(),
Format: {
CSV: "csv",
},
}))
jest.mock("../../../utilities/fileSystem")

function getUserCtx() {
return {
params: {
tableId: "datasource__tablename",
},
query: {
format: "csv",
},
request: {
body: {},
},
throw: jest.fn(() => {
throw "Err"
}),
attachment: jest.fn(),
}
}

describe("external row controller", () => {
describe("exportRows", () => {
beforeAll(() => {
//@ts-ignore
jest.spyOn(ExternalRequest.prototype, "run").mockImplementation(() => [])
})

afterEach(() => {
jest.clearAllMocks()
})

it("should throw a 400 if no datasource entities are present", async () => {
let userCtx = getUserCtx()
try {
//@ts-ignore
await exportRows(userCtx)
} catch (e) {
expect(userCtx.throw).toHaveBeenCalledWith(
400,
"Datasource has not been configured for plus API."
)
}
})

it("should handle single quotes from a row ID", async () => {
//@ts-ignore
sdk.datasources.get.mockImplementation(() => ({
entities: {
tablename: {
schema: {},
},
},
}))
let userCtx = getUserCtx()
userCtx.request.body = {
rows: ["['d001']"],
}

//@ts-ignore
await exportRows(userCtx)

expect(userCtx.request.body).toEqual({
query: {
oneOf: {
_id: ["d001"],
},
},
})
})

it("should throw a 400 if any composite keys are present", async () => {
let userCtx = getUserCtx()
userCtx.request.body = {
rows: ["[123]", "['d001'%2C'10111']"],
}
try {
//@ts-ignore
await exportRows(userCtx)
} catch (e) {
expect(userCtx.throw).toHaveBeenCalledWith(
400,
"Export data does not support composite keys."
)
}
})

it("should throw a 400 if no table name was found", async () => {
let userCtx = getUserCtx()
userCtx.params.tableId = "datasource__"
userCtx.request.body = {
rows: ["[123]"],
}
try {
//@ts-ignore
await exportRows(userCtx)
} catch (e) {
expect(userCtx.throw).toHaveBeenCalledWith(
400,
"Could not find table name."
)
}
})
})
})

0 comments on commit a3fdd46

Please sign in to comment.