+ import { params } from "@sveltech/routify"
+ import { backendUiStore } from "builderStore"
+
+ if ($params.query) {
+ const query = $backendUiStore.queries.find(
+ m => m._id === $params.query
+ )
+ if (query) {
+ backendUiStore.actions.queries.select(query)
+ }
+ }
+
+
+
diff --git a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/_layout.svelte b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/_layout.svelte
index 27f3346d92..d8d97a69f9 100644
--- a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/_layout.svelte
+++ b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/_layout.svelte
@@ -2,12 +2,12 @@
import { params } from "@roxi/routify"
import { backendUiStore } from "builderStore"
- if ($params.selectedDatasourceId) {
+ if ($params.selectedDatasource) {
const datasource = $backendUiStore.datasources.find(
m => m._id === $params.selectedDatasource
)
if (datasource) {
- backendUiStore.actions.datasources.select(datasource)
+ backendUiStore.actions.datasources.select(datasource._id)
}
}
diff --git a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte
index 670ca8e03f..46ae11bd07 100644
--- a/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte
+++ b/packages/builder/src/pages/[application]/data/datasource/[selectedDatasource]/index.svelte
@@ -1,6 +1,6 @@
+
+ {#if $backendUiStore.tables.length === 0}
+ Connect your first datasource to start building.
+ {:else}Select a datasource to edit{/if}
+
+
\ No newline at end of file
diff --git a/packages/builder/src/pages/[application]/data/table/index.svelte b/packages/builder/src/pages/[application]/data/table/index.svelte
index 70d43b1b49..d1659257d4 100644
--- a/packages/builder/src/pages/[application]/data/table/index.svelte
+++ b/packages/builder/src/pages/[application]/data/table/index.svelte
@@ -1,23 +1,10 @@
diff --git a/packages/server/__mocks__/@elastic/elasticsearch.js b/packages/server/__mocks__/@elastic/elasticsearch.js
new file mode 100644
index 0000000000..c6b2bad48a
--- /dev/null
+++ b/packages/server/__mocks__/@elastic/elasticsearch.js
@@ -0,0 +1,24 @@
+const elastic = {}
+
+elastic.Client = function() {
+ this.index = jest.fn().mockResolvedValue({ body: [] })
+ this.search = jest.fn().mockResolvedValue({
+ body: {
+ hits: {
+ hits: [
+ {
+ _source: {
+ name: "test",
+ },
+ },
+ ],
+ },
+ },
+ })
+ this.update = jest.fn().mockResolvedValue({ body: [] })
+ this.delete = jest.fn().mockResolvedValue({ body: [] })
+
+ this.close = jest.fn()
+}
+
+module.exports = elastic
diff --git a/packages/server/__mocks__/airtable.js b/packages/server/__mocks__/airtable.js
new file mode 100644
index 0000000000..f9b3a1b35d
--- /dev/null
+++ b/packages/server/__mocks__/airtable.js
@@ -0,0 +1,5 @@
+function Airtable() {
+ this.base = jest.fn()
+}
+
+module.exports = Airtable
diff --git a/packages/server/__mocks__/arangojs.js b/packages/server/__mocks__/arangojs.js
new file mode 100644
index 0000000000..1a40529ca0
--- /dev/null
+++ b/packages/server/__mocks__/arangojs.js
@@ -0,0 +1,21 @@
+const arangodb = {}
+
+arangodb.Database = function() {
+ this.query = jest.fn(() => ({
+ all: jest.fn(),
+ }))
+ this.collection = jest.fn(() => "collection")
+ this.close = jest.fn()
+}
+
+arangodb.aql = (strings, ...args) => {
+ let str = strings.join("{}")
+
+ for (let arg of args) {
+ str = str.replace("{}", arg)
+ }
+
+ return str
+}
+
+module.exports = arangodb
diff --git a/packages/server/__mocks__/aws-sdk.js b/packages/server/__mocks__/aws-sdk.js
new file mode 100644
index 0000000000..503d098256
--- /dev/null
+++ b/packages/server/__mocks__/aws-sdk.js
@@ -0,0 +1,38 @@
+const aws = {}
+
+const response = body => () => ({ promise: () => body })
+
+function DocumentClient() {
+ this.put = jest.fn(response({}))
+ this.query = jest.fn(
+ response({
+ Items: [],
+ })
+ )
+ this.scan = jest.fn(
+ response({
+ Items: [
+ {
+ Name: "test",
+ },
+ ],
+ })
+ )
+ this.get = jest.fn(response({}))
+ this.update = jest.fn(response({}))
+ this.delete = jest.fn(response({}))
+}
+
+function S3() {
+ this.listObjects = jest.fn(
+ response({
+ Contents: {},
+ })
+ )
+}
+
+aws.DynamoDB = { DocumentClient }
+aws.S3 = S3
+aws.config = { update: jest.fn() }
+
+module.exports = aws
diff --git a/packages/server/__mocks__/mongodb.js b/packages/server/__mocks__/mongodb.js
new file mode 100644
index 0000000000..160ca89ebe
--- /dev/null
+++ b/packages/server/__mocks__/mongodb.js
@@ -0,0 +1,19 @@
+const mongodb = {}
+
+mongodb.MongoClient = function() {
+ this.connect = jest.fn()
+ this.close = jest.fn()
+ this.insertOne = jest.fn()
+ this.find = jest.fn(() => ({ toArray: () => [] }))
+
+ this.collection = jest.fn(() => ({
+ insertOne: this.insertOne,
+ find: this.find,
+ }))
+
+ this.db = () => ({
+ collection: this.collection,
+ })
+}
+
+module.exports = mongodb
diff --git a/packages/server/__mocks__/mssql.js b/packages/server/__mocks__/mssql.js
new file mode 100644
index 0000000000..6119c014da
--- /dev/null
+++ b/packages/server/__mocks__/mssql.js
@@ -0,0 +1,14 @@
+const mssql = {}
+
+mssql.query = jest.fn(() => ({
+ recordset: [
+ {
+ a: "string",
+ b: 1,
+ },
+ ],
+}))
+
+mssql.connect = jest.fn(() => ({ recordset: [] }))
+
+module.exports = mssql
diff --git a/packages/server/__mocks__/mysql.js b/packages/server/__mocks__/mysql.js
new file mode 100644
index 0000000000..2b4df3e44b
--- /dev/null
+++ b/packages/server/__mocks__/mysql.js
@@ -0,0 +1,10 @@
+const mysql = {}
+
+const client = {
+ connect: jest.fn(),
+ query: jest.fn(),
+}
+
+mysql.createConnection = jest.fn(() => client)
+
+module.exports = mysql
diff --git a/packages/server/__mocks__/pg.js b/packages/server/__mocks__/pg.js
index 2bda8afad0..0d8b8cc26a 100644
--- a/packages/server/__mocks__/pg.js
+++ b/packages/server/__mocks__/pg.js
@@ -3,18 +3,16 @@ const pg = {}
// constructor
function Client() {}
-Client.prototype.query = async function() {
- return {
- rows: [
- {
- a: "string",
- b: 1,
- },
- ],
- }
-}
+Client.prototype.query = jest.fn(() => ({
+ rows: [
+ {
+ a: "string",
+ b: 1,
+ },
+ ],
+}))
-Client.prototype.connect = async function() {}
+Client.prototype.connect = jest.fn()
pg.Client = Client
diff --git a/packages/server/build/pouchdb.js b/packages/server/build/pouchdb.js
new file mode 100644
index 0000000000..16942a7a86
--- /dev/null
+++ b/packages/server/build/pouchdb.js
@@ -0,0 +1,9 @@
+function CouchDB() {
+ this.post = jest.fn()
+ this.allDocs = jest.fn(() => ({ rows: [] }))
+ this.put = jest.fn()
+ this.remove = jest.fn()
+ this.plugin = jest.fn()
+}
+
+module.exports = CouchDB
diff --git a/packages/server/src/integrations/dynamodb.js b/packages/server/src/integrations/dynamodb.js
index 668e11e263..4897690075 100644
--- a/packages/server/src/integrations/dynamodb.js
+++ b/packages/server/src/integrations/dynamodb.js
@@ -166,7 +166,7 @@ class DynamoDBIntegration {
async update(query) {
const params = {
- TableName: query.Table,
+ TableName: query.table,
...query.json,
}
return this.client.update(params).promise()
diff --git a/packages/server/src/integrations/microsoftSqlServer.js b/packages/server/src/integrations/microsoftSqlServer.js
index eea67a7256..f5e30fd65b 100644
--- a/packages/server/src/integrations/microsoftSqlServer.js
+++ b/packages/server/src/integrations/microsoftSqlServer.js
@@ -65,7 +65,7 @@ class SqlServerIntegration {
try {
await this.connect()
const response = await this.client.query(query.sql)
- return response.recordset
+ return response.recordset || [{ created: true }]
} catch (err) {
console.error("Error querying MS SQL Server", err)
throw err
diff --git a/packages/server/src/integrations/mysql.js b/packages/server/src/integrations/mysql.js
index af1a1baf92..c505c4fc14 100644
--- a/packages/server/src/integrations/mysql.js
+++ b/packages/server/src/integrations/mysql.js
@@ -73,20 +73,23 @@ class MySQLIntegration {
})
}
- create(query) {
- return this.query(query)
+ async create(query) {
+ const results = await this.query(query)
+ return results.length ? results : [{ created: true }]
}
read(query) {
return this.query(query)
}
- update(query) {
- return this.query(query)
+ async update(query) {
+ const results = await this.query(query)
+ return results.length ? results : [{ updated: true }]
}
- delete(query) {
- return this.query(query)
+ async delete(query) {
+ const results = await this.query(query)
+ return results.length ? results : [{ deleted: true }]
}
}
diff --git a/packages/server/src/integrations/tests/TestConfiguration.js b/packages/server/src/integrations/tests/TestConfiguration.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/server/src/integrations/tests/airtable.spec.js b/packages/server/src/integrations/tests/airtable.spec.js
new file mode 100644
index 0000000000..e6654f6f71
--- /dev/null
+++ b/packages/server/src/integrations/tests/airtable.spec.js
@@ -0,0 +1,70 @@
+const Airtable = require("airtable")
+const AirtableIntegration = require("../airtable")
+jest.mock("airtable")
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new AirtableIntegration.integration(config)
+ this.client = {
+ create: jest.fn(),
+ select: jest.fn(),
+ update: jest.fn(),
+ destroy: jest.fn(),
+ }
+ this.integration.client = () => this.client
+ }
+}
+
+describe("Airtable Integration", () => {
+ let config
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const response = await config.integration.create({
+ table: "test",
+ json: {}
+ })
+ expect(config.client.create).toHaveBeenCalledWith([
+ {
+ fields: {}
+ }
+ ])
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const response = await config.integration.read({
+ table: "test",
+ view: "Grid view"
+ })
+ expect(config.client.select).toHaveBeenCalledWith({
+ maxRecords: 10, view: "Grid view"
+ })
+ })
+
+ it("calls the update method with the correct params", async () => {
+ const response = await config.integration.update({
+ table: "test",
+ id: "123",
+ json: {
+ name: "test"
+ }
+ })
+ expect(config.client.update).toHaveBeenCalledWith([
+ {
+ id: "123",
+ fields: { name: "test" }
+ }
+ ])
+ })
+
+ it("calls the delete method with the correct params", async () => {
+ const ids = [1,2,3,4]
+ const response = await config.integration.delete({
+ ids
+ })
+ expect(config.client.destroy).toHaveBeenCalledWith(ids)
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/arangodb.spec.js b/packages/server/src/integrations/tests/arangodb.spec.js
new file mode 100644
index 0000000000..437a7fd3ec
--- /dev/null
+++ b/packages/server/src/integrations/tests/arangodb.spec.js
@@ -0,0 +1,35 @@
+const arangodb = require("arangojs")
+const ArangoDBIntegration = require("../arangodb")
+jest.mock("arangojs")
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new ArangoDBIntegration.integration(config)
+ }
+}
+
+describe("ArangoDB Integration", () => {
+ let config
+ let indexName = "Users"
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const body = {
+ json: "Hello"
+ }
+
+ const response = await config.integration.create(body)
+ expect(config.integration.client.query).toHaveBeenCalledWith(`INSERT Hello INTO collection RETURN NEW`)
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const query = {
+ json: `test`,
+ }
+ const response = await config.integration.read(query)
+ expect(config.integration.client.query).toHaveBeenCalledWith(query.sql)
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/couchdb.spec.js b/packages/server/src/integrations/tests/couchdb.spec.js
new file mode 100644
index 0000000000..cfe522c617
--- /dev/null
+++ b/packages/server/src/integrations/tests/couchdb.spec.js
@@ -0,0 +1,68 @@
+const PouchDB = require("pouchdb")
+const CouchDBIntegration = require("../couchdb")
+jest.mock("pouchdb", () => function CouchDBMock() {
+ this.post = jest.fn()
+ this.allDocs = jest.fn(() => ({ rows: [] }))
+ this.put = jest.fn()
+ this.remove = jest.fn()
+ this.plugin = jest.fn()
+})
+
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new CouchDBIntegration.integration(config)
+ }
+}
+
+describe("CouchDB Integration", () => {
+ let config
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const doc = {
+ test: 1
+ }
+ const response = await config.integration.create({
+ json: doc
+ })
+ expect(config.integration.client.post).toHaveBeenCalledWith(doc)
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const doc = {
+ name: "search"
+ }
+
+ const response = await config.integration.read({
+ json: doc
+ })
+
+ expect(config.integration.client.allDocs).toHaveBeenCalledWith({
+ include_docs: true,
+ name: "search"
+ })
+ })
+
+ it("calls the update method with the correct params", async () => {
+ const doc = {
+ _id: "1234",
+ name: "search"
+ }
+
+ const response = await config.integration.update({
+ json: doc
+ })
+
+ expect(config.integration.client.put).toHaveBeenCalledWith(doc)
+ })
+
+ it("calls the delete method with the correct params", async () => {
+ const id = "1234"
+ const response = await config.integration.delete({ id })
+ expect(config.integration.client.remove).toHaveBeenCalledWith(id)
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/dynamodb.spec.js b/packages/server/src/integrations/tests/dynamodb.spec.js
new file mode 100644
index 0000000000..4c6b931090
--- /dev/null
+++ b/packages/server/src/integrations/tests/dynamodb.spec.js
@@ -0,0 +1,103 @@
+const AWS = require("aws-sdk")
+const DynamoDBIntegration = require("../dynamodb")
+jest.mock("aws-sdk")
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new DynamoDBIntegration.integration(config)
+ }
+}
+
+describe("DynamoDB Integration", () => {
+ let config
+ let tableName = "Users"
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const response = await config.integration.create({
+ table: tableName,
+ json: {
+ Name: "John"
+ }
+ })
+ expect(config.integration.client.put).toHaveBeenCalledWith({
+ TableName: tableName,
+ Name: "John"
+ })
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const indexName = "Test"
+
+ const response = await config.integration.read({
+ table: tableName,
+ index: indexName,
+ json: {}
+ })
+ expect(config.integration.client.query).toHaveBeenCalledWith({
+ TableName: tableName,
+ IndexName: indexName,
+ })
+ expect(response).toEqual([])
+ })
+
+ it("calls the scan method with the correct params", async () => {
+ const indexName = "Test"
+
+ const response = await config.integration.scan({
+ table: tableName,
+ index: indexName,
+ json: {}
+ })
+ expect(config.integration.client.scan).toHaveBeenCalledWith({
+ TableName: tableName,
+ IndexName: indexName,
+ })
+ expect(response).toEqual([{
+ Name: "test"
+ }])
+ })
+
+ it("calls the get method with the correct params", async () => {
+ const response = await config.integration.get({
+ table: tableName,
+ json: {
+ Id: 123
+ }
+ })
+
+ expect(config.integration.client.get).toHaveBeenCalledWith({
+ TableName: tableName,
+ Id: 123
+ })
+ })
+
+ it("calls the update method with the correct params", async () => {
+ const response = await config.integration.update({
+ table: tableName,
+ json: {
+ Name: "John"
+ }
+ })
+ expect(config.integration.client.update).toHaveBeenCalledWith({
+ TableName: tableName,
+ Name: "John"
+ })
+ })
+
+ it("calls the delete method with the correct params", async () => {
+ const response = await config.integration.delete({
+ table: tableName,
+ json: {
+ Name: "John"
+ }
+ })
+ expect(config.integration.client.delete).toHaveBeenCalledWith({
+ TableName: tableName,
+ Name: "John"
+ })
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/elasticsearch.spec.js b/packages/server/src/integrations/tests/elasticsearch.spec.js
new file mode 100644
index 0000000000..fc97e04bcc
--- /dev/null
+++ b/packages/server/src/integrations/tests/elasticsearch.spec.js
@@ -0,0 +1,81 @@
+const elasticsearch = require("@elastic/elasticsearch")
+const ElasticSearchIntegration = require("../elasticsearch")
+jest.mock("@elastic/elasticsearch")
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new ElasticSearchIntegration.integration(config)
+ }
+}
+
+describe("Elasticsearch Integration", () => {
+ let config
+ let indexName = "Users"
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const body = {
+ name: "Hello"
+ }
+ const response = await config.integration.create({
+ index: indexName,
+ json: body
+ })
+ expect(config.integration.client.index).toHaveBeenCalledWith({
+ index: indexName,
+ body
+ })
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const body = {
+ query: {
+ term: {
+ name: "kimchy"
+ }
+ }
+ }
+ const response = await config.integration.read({
+ index: indexName,
+ json: body
+ })
+ expect(config.integration.client.search).toHaveBeenCalledWith({
+ index: indexName,
+ body
+ })
+ expect(response).toEqual(expect.any(Array))
+ })
+
+ it("calls the update method with the correct params", async () => {
+ const body = {
+ name: "updated"
+ }
+
+ const response = await config.integration.update({
+ id: "1234",
+ index: indexName,
+ json: body
+ })
+
+ expect(config.integration.client.update).toHaveBeenCalledWith({
+ id: "1234",
+ index: indexName,
+ body
+ })
+ expect(response).toEqual(expect.any(Array))
+ })
+
+ it("calls the delete method with the correct params", async () => {
+ const body = {
+ id: "1234"
+ }
+
+ const response = await config.integration.delete(body)
+
+ expect(config.integration.client.delete).toHaveBeenCalledWith(body)
+ expect(response).toEqual(expect.any(Array))
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/microsoftSqlServer.spec.js b/packages/server/src/integrations/tests/microsoftSqlServer.spec.js
new file mode 100644
index 0000000000..29399b840f
--- /dev/null
+++ b/packages/server/src/integrations/tests/microsoftSqlServer.spec.js
@@ -0,0 +1,47 @@
+const sqlServer = require("mssql")
+const MSSQLIntegration = require("../microsoftSqlServer")
+jest.mock("mssql")
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new MSSQLIntegration.integration(config)
+ }
+}
+
+describe("MS SQL Server Integration", () => {
+ let config
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const sql = "insert into users (name, age) values ('Joe', 123);"
+ const response = await config.integration.create({
+ sql
+ })
+ expect(config.integration.client.query).toHaveBeenCalledWith(sql)
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const sql = "select * from users;"
+ const response = await config.integration.read({
+ sql
+ })
+ expect(config.integration.client.query).toHaveBeenCalledWith(sql)
+ })
+
+ describe("no rows returned", () => {
+ beforeEach(() => {
+ config.integration.client.query.mockImplementation(() => ({ rows: [] }))
+ })
+
+ it("returns the correct response when the create response has no rows", async () => {
+ const sql = "insert into users (name, age) values ('Joe', 123);"
+ const response = await config.integration.create({
+ sql
+ })
+ expect(response).toEqual([{ created: true }])
+ })
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/mongo.spec.js b/packages/server/src/integrations/tests/mongo.spec.js
new file mode 100644
index 0000000000..1e37d5dd70
--- /dev/null
+++ b/packages/server/src/integrations/tests/mongo.spec.js
@@ -0,0 +1,40 @@
+const mongo = require("mongodb")
+const MongoDBIntegration = require("../mongodb")
+jest.mock("mongodb")
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new MongoDBIntegration.integration(config)
+ }
+}
+
+describe("MongoDB Integration", () => {
+ let config
+ let indexName = "Users"
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const body = {
+ name: "Hello"
+ }
+ const response = await config.integration.create({
+ index: indexName,
+ json: body
+ })
+ expect(config.integration.client.insertOne).toHaveBeenCalledWith(body)
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const query = {
+ json: {
+ address: "test"
+ }
+ }
+ const response = await config.integration.read(query)
+ expect(config.integration.client.find).toHaveBeenCalledWith(query.json)
+ expect(response).toEqual(expect.any(Array))
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/mysql.spec.js b/packages/server/src/integrations/tests/mysql.spec.js
new file mode 100644
index 0000000000..eca3e523b0
--- /dev/null
+++ b/packages/server/src/integrations/tests/mysql.spec.js
@@ -0,0 +1,83 @@
+const pg = require("mysql")
+const MySQLIntegration = require("../mysql")
+jest.mock("mysql")
+
+class TestConfiguration {
+ constructor(config = { ssl: {} }) {
+ this.integration = new MySQLIntegration.integration(config)
+ this.query = jest.fn(() => [{ id: 1 }])
+ this.integration.query = this.query
+ }
+}
+
+describe("MySQL Integration", () => {
+ let config
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const sql = "insert into users (name, age) values ('Joe', 123);"
+ const response = await config.integration.create({
+ sql
+ })
+ expect(config.query).toHaveBeenCalledWith({ sql })
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const sql = "select * from users;"
+ const response = await config.integration.read({
+ sql
+ })
+ expect(config.query).toHaveBeenCalledWith({
+ sql
+ })
+ })
+
+ it("calls the update method with the correct params", async () => {
+ const sql = "update table users set name = 'test';"
+ const response = await config.integration.update({
+ sql
+ })
+ expect(config.query).toHaveBeenCalledWith({ sql })
+ })
+
+ it("calls the delete method with the correct params", async () => {
+ const sql = "delete from users where name = 'todelete';"
+ const response = await config.integration.delete({
+ sql
+ })
+ expect(config.query).toHaveBeenCalledWith({ sql })
+ })
+
+ describe("no rows returned", () => {
+ beforeEach(() => {
+ config.query.mockImplementation(() => [])
+ })
+
+ it("returns the correct response when the create response has no rows", async () => {
+ const sql = "insert into users (name, age) values ('Joe', 123);"
+ const response = await config.integration.create({
+ sql
+ })
+ expect(response).toEqual([{ created: true }])
+ })
+
+ it("returns the correct response when the update response has no rows", async () => {
+ const sql = "update table users set name = 'test';"
+ const response = await config.integration.update({
+ sql
+ })
+ expect(response).toEqual([{ updated: true }])
+ })
+
+ it("returns the correct response when the delete response has no rows", async () => {
+ const sql = "delete from users where name = 'todelete';"
+ const response = await config.integration.delete({
+ sql
+ })
+ expect(response).toEqual([{ deleted: true }])
+ })
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/postgres.spec.js b/packages/server/src/integrations/tests/postgres.spec.js
new file mode 100644
index 0000000000..8a8876a556
--- /dev/null
+++ b/packages/server/src/integrations/tests/postgres.spec.js
@@ -0,0 +1,79 @@
+const pg = require("pg")
+const PostgresIntegration = require("../postgres")
+jest.mock("pg")
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new PostgresIntegration.integration(config)
+ }
+}
+
+describe("Postgres Integration", () => {
+ let config
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const sql = "insert into users (name, age) values ('Joe', 123);"
+ const response = await config.integration.create({
+ sql
+ })
+ expect(config.integration.client.query).toHaveBeenCalledWith(sql)
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const sql = "select * from users;"
+ const response = await config.integration.read({
+ sql
+ })
+ expect(config.integration.client.query).toHaveBeenCalledWith(sql)
+ })
+
+ it("calls the update method with the correct params", async () => {
+ const sql = "update table users set name = 'test';"
+ const response = await config.integration.update({
+ sql
+ })
+ expect(config.integration.client.query).toHaveBeenCalledWith(sql)
+ })
+
+ it("calls the delete method with the correct params", async () => {
+ const sql = "delete from users where name = 'todelete';"
+ const response = await config.integration.delete({
+ sql
+ })
+ expect(config.integration.client.query).toHaveBeenCalledWith(sql)
+ })
+
+ describe("no rows returned", () => {
+ beforeEach(() => {
+ config.integration.client.query.mockImplementation(() => ({ rows: [] }))
+ })
+
+ it("returns the correct response when the create response has no rows", async () => {
+ const sql = "insert into users (name, age) values ('Joe', 123);"
+ const response = await config.integration.create({
+ sql
+ })
+ expect(response).toEqual([{ created: true }])
+ })
+
+ it("returns the correct response when the update response has no rows", async () => {
+ const sql = "update table users set name = 'test';"
+ const response = await config.integration.update({
+ sql
+ })
+ expect(response).toEqual([{ updated: true }])
+ })
+
+ it("returns the correct response when the delete response has no rows", async () => {
+ const sql = "delete from users where name = 'todelete';"
+ const response = await config.integration.delete({
+ sql
+ })
+ expect(response).toEqual([{ deleted: true }])
+ })
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/rest.spec.js b/packages/server/src/integrations/tests/rest.spec.js
new file mode 100644
index 0000000000..db8749baa1
--- /dev/null
+++ b/packages/server/src/integrations/tests/rest.spec.js
@@ -0,0 +1,98 @@
+const fetch = require("node-fetch")
+const RestIntegration = require("../rest")
+jest.mock("node-fetch", () => jest.fn(() => ({ json: jest.fn(), text: jest.fn() })))
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new RestIntegration.integration(config)
+ }
+}
+
+describe("REST Integration", () => {
+ const BASE_URL = "https://myapi.com"
+ let config
+
+ beforeEach(() => {
+ config = new TestConfiguration({
+ url: BASE_URL
+ })
+ })
+
+ it("calls the create method with the correct params", async () => {
+ const query = {
+ path: "/api",
+ queryString: "?test=1",
+ headers: {
+ Accept: "application/json"
+ },
+ json: {
+ name: "test"
+ }
+ }
+ const response = await config.integration.create(query)
+ expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
+ method: "POST",
+ body: "{\"name\":\"test\"}",
+ headers: {
+ Accept: "application/json"
+ }
+ })
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const query = {
+ path: "/api",
+ queryString: "?test=1",
+ headers: {
+ Accept: "text/html"
+ }
+ }
+ const response = await config.integration.read(query)
+ expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
+ headers: {
+ Accept: "text/html"
+ }
+ })
+ })
+
+ it("calls the update method with the correct params", async () => {
+ const query = {
+ path: "/api",
+ queryString: "?test=1",
+ headers: {
+ Accept: "application/json"
+ },
+ json: {
+ name: "test"
+ }
+ }
+ const response = await config.integration.update(query)
+ expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
+ method: "POST",
+ body: "{\"name\":\"test\"}",
+ headers: {
+ Accept: "application/json"
+ }
+ })
+ })
+
+ it("calls the delete method with the correct params", async () => {
+ const query = {
+ path: "/api",
+ queryString: "?test=1",
+ headers: {
+ Accept: "application/json"
+ },
+ json: {
+ name: "test"
+ }
+ }
+ const response = await config.integration.delete(query)
+ expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
+ method: "DELETE",
+ headers: {
+ Accept: "application/json"
+ }
+ })
+ })
+})
\ No newline at end of file
diff --git a/packages/server/src/integrations/tests/s3.spec.js b/packages/server/src/integrations/tests/s3.spec.js
new file mode 100644
index 0000000000..7ac403dbd4
--- /dev/null
+++ b/packages/server/src/integrations/tests/s3.spec.js
@@ -0,0 +1,26 @@
+const AWS = require("aws-sdk")
+const S3Integration = require("../s3")
+jest.mock("aws-sdk")
+
+class TestConfiguration {
+ constructor(config = {}) {
+ this.integration = new S3Integration.integration(config)
+ }
+}
+
+describe("S3 Integration", () => {
+ let config
+
+ beforeEach(() => {
+ config = new TestConfiguration()
+ })
+
+ it("calls the read method with the correct params", async () => {
+ const response = await config.integration.read({
+ bucket: "test"
+ })
+ expect(config.integration.client.listObjects).toHaveBeenCalledWith({
+ Bucket: "test"
+ })
+ })
+})
\ No newline at end of file