Merge branch 'master' into fix/BUDI-7444
This commit is contained in:
commit
5240c2c2ca
|
@ -107,3 +107,4 @@ budibase-component
|
||||||
budibase-datasource
|
budibase-datasource
|
||||||
|
|
||||||
*.iml
|
*.iml
|
||||||
|
.nx
|
|
@ -32,10 +32,14 @@
|
||||||
import TourWrap from "components/portal/onboarding/TourWrap.svelte"
|
import TourWrap from "components/portal/onboarding/TourWrap.svelte"
|
||||||
import { TOUR_STEP_KEYS } from "components/portal/onboarding/tours.js"
|
import { TOUR_STEP_KEYS } from "components/portal/onboarding/tours.js"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
import PosthogClient from "../../analytics/PosthogClient"
|
||||||
|
|
||||||
export let application
|
export let application
|
||||||
export let loaded
|
export let loaded
|
||||||
|
|
||||||
|
const posthog = new PosthogClient(process.env.POSTHOG_TOKEN)
|
||||||
|
|
||||||
let unpublishModal
|
let unpublishModal
|
||||||
let updateAppModal
|
let updateAppModal
|
||||||
let revertModal
|
let revertModal
|
||||||
|
@ -44,6 +48,7 @@
|
||||||
let appActionPopoverOpen = false
|
let appActionPopoverOpen = false
|
||||||
let appActionPopoverAnchor
|
let appActionPopoverAnchor
|
||||||
let publishing = false
|
let publishing = false
|
||||||
|
let showNpsSurvey = false
|
||||||
let lastOpened
|
let lastOpened
|
||||||
|
|
||||||
$: filteredApps = $appsStore.apps.filter(app => app.devId === application)
|
$: filteredApps = $appsStore.apps.filter(app => app.devId === application)
|
||||||
|
@ -98,6 +103,7 @@
|
||||||
type: "success",
|
type: "success",
|
||||||
icon: "GlobeCheck",
|
icon: "GlobeCheck",
|
||||||
})
|
})
|
||||||
|
showNpsSurvey = true
|
||||||
await completePublish()
|
await completePublish()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
@ -148,6 +154,10 @@
|
||||||
notifications.error("Error refreshing app")
|
notifications.error("Error refreshing app")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
posthog.init()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
@ -345,6 +355,10 @@
|
||||||
<RevertModal bind:this={revertModal} />
|
<RevertModal bind:this={revertModal} />
|
||||||
<VersionModal hideIcon bind:this={versionModal} />
|
<VersionModal hideIcon bind:this={versionModal} />
|
||||||
|
|
||||||
|
{#if showNpsSurvey}
|
||||||
|
<div class="nps-survey" />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.app-action-popover-content {
|
.app-action-popover-content {
|
||||||
padding: var(--spacing-xl);
|
padding: var(--spacing-xl);
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
module MongoMock {
|
|
||||||
const mongodb: any = {}
|
|
||||||
|
|
||||||
mongodb.MongoClient = function () {
|
|
||||||
this.connect = jest.fn()
|
|
||||||
this.close = jest.fn()
|
|
||||||
this.insertOne = jest.fn()
|
|
||||||
this.insertMany = jest.fn(() => ({ toArray: () => [] }))
|
|
||||||
this.find = jest.fn(() => ({ toArray: () => [] }))
|
|
||||||
this.findOne = jest.fn()
|
|
||||||
this.findOneAndUpdate = jest.fn()
|
|
||||||
this.count = jest.fn()
|
|
||||||
this.deleteOne = jest.fn()
|
|
||||||
this.deleteMany = jest.fn(() => ({ toArray: () => [] }))
|
|
||||||
this.updateOne = jest.fn()
|
|
||||||
this.updateMany = jest.fn(() => ({ toArray: () => [] }))
|
|
||||||
|
|
||||||
this.collection = jest.fn(() => ({
|
|
||||||
insertOne: this.insertOne,
|
|
||||||
find: this.find,
|
|
||||||
insertMany: this.insertMany,
|
|
||||||
findOne: this.findOne,
|
|
||||||
findOneAndUpdate: this.findOneAndUpdate,
|
|
||||||
count: this.count,
|
|
||||||
deleteOne: this.deleteOne,
|
|
||||||
deleteMany: this.deleteMany,
|
|
||||||
updateOne: this.updateOne,
|
|
||||||
updateMany: this.updateMany,
|
|
||||||
}))
|
|
||||||
|
|
||||||
this.db = () => ({
|
|
||||||
collection: this.collection,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
mongodb.ObjectId = jest.requireActual("mongodb").ObjectId
|
|
||||||
|
|
||||||
module.exports = mongodb
|
|
||||||
}
|
|
|
@ -3,8 +3,6 @@ import * as setup from "../utilities"
|
||||||
import { databaseTestProviders } from "../../../../integrations/tests/utils"
|
import { databaseTestProviders } from "../../../../integrations/tests/utils"
|
||||||
import { MongoClient, type Collection, BSON } from "mongodb"
|
import { MongoClient, type Collection, BSON } from "mongodb"
|
||||||
|
|
||||||
jest.unmock("mongodb")
|
|
||||||
|
|
||||||
const collection = "test_collection"
|
const collection = "test_collection"
|
||||||
|
|
||||||
const expectValidId = expect.stringMatching(/^\w{24}$/)
|
const expectValidId = expect.stringMatching(/^\w{24}$/)
|
||||||
|
@ -36,27 +34,27 @@ describe("/queries", () => {
|
||||||
return await config.api.query.save(combinedQuery)
|
return await config.api.query.save(combinedQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function withClient(
|
async function withClient<T>(
|
||||||
callback: (client: MongoClient) => Promise<void>
|
callback: (client: MongoClient) => Promise<T>
|
||||||
): Promise<void> {
|
): Promise<T> {
|
||||||
const ds = await databaseTestProviders.mongodb.datasource()
|
const ds = await databaseTestProviders.mongodb.datasource()
|
||||||
const client = new MongoClient(ds.config!.connectionString)
|
const client = new MongoClient(ds.config!.connectionString)
|
||||||
await client.connect()
|
await client.connect()
|
||||||
try {
|
try {
|
||||||
await callback(client)
|
return await callback(client)
|
||||||
} finally {
|
} finally {
|
||||||
await client.close()
|
await client.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function withCollection(
|
async function withCollection<T>(
|
||||||
callback: (collection: Collection) => Promise<void>
|
callback: (collection: Collection) => Promise<T>
|
||||||
): Promise<void> {
|
): Promise<T> {
|
||||||
await withClient(async client => {
|
return await withClient(async client => {
|
||||||
const db = client.db(
|
const db = client.db(
|
||||||
(await databaseTestProviders.mongodb.datasource()).config!.db
|
(await databaseTestProviders.mongodb.datasource()).config!.db
|
||||||
)
|
)
|
||||||
await callback(db.collection(collection))
|
return await callback(db.collection(collection))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,6 +325,42 @@ describe("/queries", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should be able to updateOne by ObjectId", async () => {
|
||||||
|
const insertResult = await withCollection(c => c.insertOne({ name: "one" }))
|
||||||
|
const query = await createQuery({
|
||||||
|
fields: {
|
||||||
|
json: {
|
||||||
|
filter: { _id: { $eq: `ObjectId("${insertResult.insertedId}")` } },
|
||||||
|
update: { $set: { name: "newName" } },
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
actionType: "updateOne",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
queryVerb: "update",
|
||||||
|
})
|
||||||
|
|
||||||
|
const result = await config.api.query.execute(query._id!)
|
||||||
|
|
||||||
|
expect(result.data).toEqual([
|
||||||
|
{
|
||||||
|
acknowledged: true,
|
||||||
|
matchedCount: 1,
|
||||||
|
modifiedCount: 1,
|
||||||
|
upsertedCount: 0,
|
||||||
|
upsertedId: null,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await withCollection(async collection => {
|
||||||
|
const doc = await collection.findOne({ name: { $eq: "newName" } })
|
||||||
|
expect(doc).toEqual({
|
||||||
|
_id: insertResult.insertedId,
|
||||||
|
name: "newName",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it("should be able to delete all records", async () => {
|
it("should be able to delete all records", async () => {
|
||||||
const query = await createQuery({
|
const query = await createQuery({
|
||||||
fields: {
|
fields: {
|
||||||
|
@ -390,4 +424,85 @@ describe("/queries", () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should throw an error if the incorrect actionType is specified", async () => {
|
||||||
|
const verbs = ["read", "create", "update", "delete"]
|
||||||
|
for (const verb of verbs) {
|
||||||
|
const query = await createQuery({
|
||||||
|
fields: { json: {}, extra: { actionType: "invalid" } },
|
||||||
|
queryVerb: verb,
|
||||||
|
})
|
||||||
|
await config.api.query.execute(query._id!, undefined, { status: 400 })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should ignore extra brackets in query", async () => {
|
||||||
|
const query = await createQuery({
|
||||||
|
fields: {
|
||||||
|
json: { foo: "te}st" },
|
||||||
|
extra: {
|
||||||
|
actionType: "insertOne",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
queryVerb: "create",
|
||||||
|
})
|
||||||
|
|
||||||
|
const result = await config.api.query.execute(query._id!)
|
||||||
|
expect(result.data).toEqual([
|
||||||
|
{
|
||||||
|
acknowledged: true,
|
||||||
|
insertedId: expectValidId,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await withCollection(async collection => {
|
||||||
|
const doc = await collection.findOne({ foo: { $eq: "te}st" } })
|
||||||
|
expect(doc).toEqual({
|
||||||
|
_id: expectValidBsonObjectId,
|
||||||
|
foo: "te}st",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should ignore be able to save deeply nested data", async () => {
|
||||||
|
const data = {
|
||||||
|
foo: "bar",
|
||||||
|
data: [
|
||||||
|
{ cid: 1 },
|
||||||
|
{ cid: 2 },
|
||||||
|
{
|
||||||
|
nested: {
|
||||||
|
name: "test",
|
||||||
|
ary: [1, 2, 3],
|
||||||
|
aryOfObjects: [{ a: 1 }, { b: 2 }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
const query = await createQuery({
|
||||||
|
fields: {
|
||||||
|
json: data,
|
||||||
|
extra: {
|
||||||
|
actionType: "insertOne",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
queryVerb: "create",
|
||||||
|
})
|
||||||
|
|
||||||
|
const result = await config.api.query.execute(query._id!)
|
||||||
|
expect(result.data).toEqual([
|
||||||
|
{
|
||||||
|
acknowledged: true,
|
||||||
|
insertedId: expectValidId,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await withCollection(async collection => {
|
||||||
|
const doc = await collection.findOne({ foo: { $eq: "bar" } })
|
||||||
|
expect(doc).toEqual({
|
||||||
|
_id: expectValidBsonObjectId,
|
||||||
|
...data,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {
|
||||||
} from "mongodb"
|
} from "mongodb"
|
||||||
import environment from "../environment"
|
import environment from "../environment"
|
||||||
|
|
||||||
interface MongoDBConfig {
|
export interface MongoDBConfig {
|
||||||
connectionString: string
|
connectionString: string
|
||||||
db: string
|
db: string
|
||||||
tlsCertificateKeyFile: string
|
tlsCertificateKeyFile: string
|
||||||
|
@ -348,7 +348,7 @@ const getSchema = () => {
|
||||||
|
|
||||||
const SCHEMA: Integration = getSchema()
|
const SCHEMA: Integration = getSchema()
|
||||||
|
|
||||||
class MongoIntegration implements IntegrationBase {
|
export class MongoIntegration implements IntegrationBase {
|
||||||
private config: MongoDBConfig
|
private config: MongoDBConfig
|
||||||
private client: MongoClient
|
private client: MongoClient
|
||||||
|
|
||||||
|
|
|
@ -1,325 +0,0 @@
|
||||||
const mongo = require("mongodb")
|
|
||||||
|
|
||||||
import { default as MongoDBIntegration } from "../mongodb"
|
|
||||||
|
|
||||||
jest.mock("mongodb")
|
|
||||||
|
|
||||||
class TestConfiguration {
|
|
||||||
integration: any
|
|
||||||
|
|
||||||
constructor(config: any = {}) {
|
|
||||||
this.integration = new MongoDBIntegration.integration(config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("MongoDB Integration", () => {
|
|
||||||
let config: any
|
|
||||||
let indexName = "Users"
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
config = new TestConfiguration()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("calls the create method with the correct params", async () => {
|
|
||||||
const body = {
|
|
||||||
name: "Hello",
|
|
||||||
}
|
|
||||||
await config.integration.create({
|
|
||||||
index: indexName,
|
|
||||||
json: body,
|
|
||||||
extra: { collection: "testCollection", actionType: "insertOne" },
|
|
||||||
})
|
|
||||||
expect(config.integration.client.insertOne).toHaveBeenCalledWith(body)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("calls the read method with the correct params", async () => {
|
|
||||||
const query = {
|
|
||||||
json: {
|
|
||||||
address: "test",
|
|
||||||
},
|
|
||||||
extra: { collection: "testCollection", actionType: "find" },
|
|
||||||
}
|
|
||||||
const response = await config.integration.read(query)
|
|
||||||
expect(config.integration.client.find).toHaveBeenCalledWith(query.json)
|
|
||||||
expect(response).toEqual(expect.any(Array))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("calls the delete method with the correct params", async () => {
|
|
||||||
const query = {
|
|
||||||
json: {
|
|
||||||
filter: {
|
|
||||||
id: "test",
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
opt: "option",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extra: { collection: "testCollection", actionType: "deleteOne" },
|
|
||||||
}
|
|
||||||
await config.integration.delete(query)
|
|
||||||
expect(config.integration.client.deleteOne).toHaveBeenCalledWith(
|
|
||||||
query.json.filter,
|
|
||||||
query.json.options
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("calls the update method with the correct params", async () => {
|
|
||||||
const query = {
|
|
||||||
json: {
|
|
||||||
filter: {
|
|
||||||
id: "test",
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
name: "TestName",
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
upsert: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extra: { collection: "testCollection", actionType: "updateOne" },
|
|
||||||
}
|
|
||||||
await config.integration.update(query)
|
|
||||||
expect(config.integration.client.updateOne).toHaveBeenCalledWith(
|
|
||||||
query.json.filter,
|
|
||||||
query.json.update,
|
|
||||||
query.json.options
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("throws an error when an invalid query.extra.actionType is passed for each method", async () => {
|
|
||||||
const query = {
|
|
||||||
extra: { collection: "testCollection", actionType: "deleteOne" },
|
|
||||||
}
|
|
||||||
|
|
||||||
let error = null
|
|
||||||
try {
|
|
||||||
await config.integration.read(query)
|
|
||||||
} catch (err) {
|
|
||||||
error = err
|
|
||||||
}
|
|
||||||
expect(error).toBeDefined()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("creates ObjectIds if the field contains a match on ObjectId", async () => {
|
|
||||||
const query = {
|
|
||||||
json: {
|
|
||||||
filter: {
|
|
||||||
_id: "ObjectId('ACBD12345678ABCD12345678')",
|
|
||||||
name: "ObjectId('BBBB12345678ABCD12345678')",
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
_id: "ObjectId('FFFF12345678ABCD12345678')",
|
|
||||||
name: "ObjectId('CCCC12345678ABCD12345678')",
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
upsert: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extra: { collection: "testCollection", actionType: "updateOne" },
|
|
||||||
}
|
|
||||||
await config.integration.update(query)
|
|
||||||
expect(config.integration.client.updateOne).toHaveBeenCalled()
|
|
||||||
|
|
||||||
const args = config.integration.client.updateOne.mock.calls[0]
|
|
||||||
expect(args[0]).toEqual({
|
|
||||||
_id: mongo.ObjectId.createFromHexString("ACBD12345678ABCD12345678"),
|
|
||||||
name: mongo.ObjectId.createFromHexString("BBBB12345678ABCD12345678"),
|
|
||||||
})
|
|
||||||
expect(args[1]).toEqual({
|
|
||||||
_id: mongo.ObjectId.createFromHexString("FFFF12345678ABCD12345678"),
|
|
||||||
name: mongo.ObjectId.createFromHexString("CCCC12345678ABCD12345678"),
|
|
||||||
})
|
|
||||||
expect(args[2]).toEqual({
|
|
||||||
upsert: false,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("creates ObjectIds if the $ operator fields contains a match on ObjectId", async () => {
|
|
||||||
const query = {
|
|
||||||
json: {
|
|
||||||
filter: {
|
|
||||||
_id: {
|
|
||||||
$eq: "ObjectId('ACBD12345678ABCD12345678')",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
$set: {
|
|
||||||
_id: "ObjectId('FFFF12345678ABCD12345678')",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
upsert: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extra: { collection: "testCollection", actionType: "updateOne" },
|
|
||||||
}
|
|
||||||
await config.integration.update(query)
|
|
||||||
expect(config.integration.client.updateOne).toHaveBeenCalled()
|
|
||||||
|
|
||||||
const args = config.integration.client.updateOne.mock.calls[0]
|
|
||||||
expect(args[0]).toEqual({
|
|
||||||
_id: {
|
|
||||||
$eq: mongo.ObjectId.createFromHexString("ACBD12345678ABCD12345678"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(args[1]).toEqual({
|
|
||||||
$set: {
|
|
||||||
_id: mongo.ObjectId.createFromHexString("FFFF12345678ABCD12345678"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(args[2]).toEqual({
|
|
||||||
upsert: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("supports findOneAndUpdate", async () => {
|
|
||||||
const query = {
|
|
||||||
json: {
|
|
||||||
filter: {
|
|
||||||
_id: {
|
|
||||||
$eq: "ObjectId('ACBD12345678ABCD12345678')",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
$set: {
|
|
||||||
name: "UPDATED",
|
|
||||||
age: 99,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
upsert: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extra: { collection: "testCollection", actionType: "findOneAndUpdate" },
|
|
||||||
}
|
|
||||||
await config.integration.read(query)
|
|
||||||
expect(config.integration.client.findOneAndUpdate).toHaveBeenCalled()
|
|
||||||
|
|
||||||
const args = config.integration.client.findOneAndUpdate.mock.calls[0]
|
|
||||||
expect(args[0]).toEqual({
|
|
||||||
_id: {
|
|
||||||
$eq: mongo.ObjectId.createFromHexString("ACBD12345678ABCD12345678"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(args[1]).toEqual({
|
|
||||||
$set: {
|
|
||||||
name: "UPDATED",
|
|
||||||
age: 99,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(args[2]).toEqual({
|
|
||||||
upsert: false,
|
|
||||||
includeResultMetadata: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("can parse nested objects with arrays", async () => {
|
|
||||||
const query = {
|
|
||||||
json: `{
|
|
||||||
"_id": {
|
|
||||||
"$eq": "ObjectId('ACBD12345678ABCD12345678')"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$set": {
|
|
||||||
"value": {
|
|
||||||
"data": [
|
|
||||||
{ "cid": 1 },
|
|
||||||
{ "cid": 2 },
|
|
||||||
{ "nested": {
|
|
||||||
"name": "test"
|
|
||||||
}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"upsert": true
|
|
||||||
}`,
|
|
||||||
extra: { collection: "testCollection", actionType: "updateOne" },
|
|
||||||
}
|
|
||||||
await config.integration.update(query)
|
|
||||||
expect(config.integration.client.updateOne).toHaveBeenCalled()
|
|
||||||
|
|
||||||
const args = config.integration.client.updateOne.mock.calls[0]
|
|
||||||
expect(args[0]).toEqual({
|
|
||||||
_id: {
|
|
||||||
$eq: mongo.ObjectId.createFromHexString("ACBD12345678ABCD12345678"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(args[1]).toEqual({
|
|
||||||
$set: {
|
|
||||||
value: {
|
|
||||||
data: [
|
|
||||||
{ cid: 1 },
|
|
||||||
{ cid: 2 },
|
|
||||||
{
|
|
||||||
nested: {
|
|
||||||
name: "test",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(args[2]).toEqual({
|
|
||||||
upsert: true,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("ignores braces within strings when parsing nested objects", async () => {
|
|
||||||
const query = {
|
|
||||||
json: `{
|
|
||||||
"_id": {
|
|
||||||
"$eq": "ObjectId('ACBD12345678ABCD12345678')"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$set": {
|
|
||||||
"value": {
|
|
||||||
"data": [
|
|
||||||
{ "cid": 1 },
|
|
||||||
{ "cid": 2 },
|
|
||||||
{ "nested": {
|
|
||||||
"name": "te}st"
|
|
||||||
}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"upsert": true,
|
|
||||||
"extra": "ad\\"{\\"d"
|
|
||||||
}`,
|
|
||||||
extra: { collection: "testCollection", actionType: "updateOne" },
|
|
||||||
}
|
|
||||||
await config.integration.update(query)
|
|
||||||
expect(config.integration.client.updateOne).toHaveBeenCalled()
|
|
||||||
|
|
||||||
const args = config.integration.client.updateOne.mock.calls[0]
|
|
||||||
expect(args[0]).toEqual({
|
|
||||||
_id: {
|
|
||||||
$eq: mongo.ObjectId.createFromHexString("ACBD12345678ABCD12345678"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(args[1]).toEqual({
|
|
||||||
$set: {
|
|
||||||
value: {
|
|
||||||
data: [
|
|
||||||
{ cid: 1 },
|
|
||||||
{ cid: 2 },
|
|
||||||
{
|
|
||||||
nested: {
|
|
||||||
name: "te}st",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
expect(args[2]).toEqual({
|
|
||||||
upsert: true,
|
|
||||||
extra: 'ad"{"d',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
PreviewQueryRequest,
|
PreviewQueryRequest,
|
||||||
PreviewQueryResponse,
|
PreviewQueryResponse,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { TestAPI } from "./base"
|
import { Expectations, TestAPI } from "./base"
|
||||||
|
|
||||||
export class QueryAPI extends TestAPI {
|
export class QueryAPI extends TestAPI {
|
||||||
save = async (body: Query): Promise<Query> => {
|
save = async (body: Query): Promise<Query> => {
|
||||||
|
@ -14,12 +14,14 @@ export class QueryAPI extends TestAPI {
|
||||||
|
|
||||||
execute = async (
|
execute = async (
|
||||||
queryId: string,
|
queryId: string,
|
||||||
body?: ExecuteQueryRequest
|
body?: ExecuteQueryRequest,
|
||||||
|
expectations?: Expectations
|
||||||
): Promise<ExecuteQueryResponse> => {
|
): Promise<ExecuteQueryResponse> => {
|
||||||
return await this._post<ExecuteQueryResponse>(
|
return await this._post<ExecuteQueryResponse>(
|
||||||
`/api/v2/queries/${queryId}`,
|
`/api/v2/queries/${queryId}`,
|
||||||
{
|
{
|
||||||
body,
|
body,
|
||||||
|
expectations,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue