De-mock DynamoDB tests.

This commit is contained in:
Sam Rose 2025-03-03 17:43:09 +00:00
parent b0c1d7ee6d
commit 1040830a64
No known key found for this signature in database
2 changed files with 61 additions and 112 deletions

View File

@ -165,6 +165,7 @@ jobs:
oracle,
sqs,
elasticsearch,
dynamodb,
none,
]
steps:
@ -205,6 +206,8 @@ jobs:
docker pull postgres:9.5.25
elif [ "${{ matrix.datasource }}" == "elasticsearch" ]; then
docker pull elasticsearch@${{ steps.dotenv.outputs.ELASTICSEARCH_SHA }}
elif [ "${{ matrix.datasource }}" == "dynamodb" ]; then
docker pull amazon/dynamodb-local@${{ steps.dotenv.outputs.DYNAMODB_SHA }}
fi
docker pull minio/minio &
docker pull redis &

View File

@ -1,149 +1,95 @@
import { Datasource } from "@budibase/types"
import { DynamoDBConfig, DynamoDBIntegration } from "../dynamodb"
import { DatabaseName, datasourceDescribe } from "./utils"
import { CreateTableCommandInput, DynamoDB } from "@aws-sdk/client-dynamodb"
const describes = datasourceDescribe({ only: [DatabaseName.DYNAMODB] })
async function createTable(client: DynamoDB, req: CreateTableCommandInput) {
try {
await client.deleteTable({ TableName: req.TableName })
} catch (e: any) {
if (e.name !== "ResourceNotFoundException") {
throw e
}
}
return await client.createTable(req)
}
if (describes.length > 0) {
describe.each(describes)("DynamoDB Integration", ({ dsProvider }) => {
let tableName = "Users"
let table = "Users"
let rawDatasource: Datasource
let dynamodb: DynamoDBIntegration
function item(json: Record<string, any>) {
return { table, json: { Item: json } }
}
function key(json: Record<string, any>) {
return { table, json: { Key: json } }
}
beforeEach(async () => {
const ds = await dsProvider()
rawDatasource = ds.rawDatasource!
dynamodb = new DynamoDBIntegration(
rawDatasource.config! as DynamoDBConfig
)
})
it.only("calls the create method with the correct params", async () => {
await dynamodb.create({
table: tableName,
json: {
Name: "John",
},
const client = new DynamoDB(rawDatasource.config as DynamoDBConfig)
await createTable(client, {
TableName: table,
KeySchema: [{ AttributeName: "Id", KeyType: "HASH" }],
AttributeDefinitions: [{ AttributeName: "Id", AttributeType: "N" }],
ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 },
})
})
it("calls the read method with the correct params", async () => {
const indexName = "Test"
it("can create and read a record", async () => {
await dynamodb.create(item({ Id: 1, Name: "John" }))
const response = await dynamodb.read({
table: tableName,
index: indexName,
json: {},
})
expect(config.integration.client.query).toHaveBeenCalledWith({
TableName: tableName,
IndexName: indexName,
})
expect(response).toEqual([])
const resp = await dynamodb.get(key({ Id: 1 }))
expect(resp.Item).toEqual({ Id: 1, Name: "John" })
})
it("calls the scan method with the correct params", async () => {
const indexName = "Test"
it("can scan", async () => {
await dynamodb.create(item({ Id: 1, Name: "John" }))
await dynamodb.create(item({ Id: 2, Name: "Jane" }))
await dynamodb.create(item({ Id: 3, Name: "Jack" }))
const response = await dynamodb.scan({
table: tableName,
index: indexName,
json: {},
})
expect(config.integration.client.scan).toHaveBeenCalledWith({
TableName: tableName,
IndexName: indexName,
})
expect(response).toEqual([])
const resp = await dynamodb.scan({ table, json: {}, index: null })
expect(resp).toEqual(
expect.arrayContaining([
{ Id: 1, Name: "John" },
{ Id: 2, Name: "Jane" },
{ Id: 3, Name: "Jack" },
])
)
})
it("calls the get method with the correct params", async () => {
await dynamodb.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 () => {
it("can update", async () => {
await dynamodb.create(item({ Id: 1, Foo: "John" }))
await dynamodb.update({
table: tableName,
table,
json: {
Name: "John",
Key: { Id: 1 },
UpdateExpression: "SET Foo = :foo",
ExpressionAttributeValues: { ":foo": "Jane" },
},
})
expect(config.integration.client.update).toHaveBeenCalledWith({
TableName: tableName,
Name: "John",
})
const updatedRecord = await dynamodb.get(key({ Id: 1 }))
expect(updatedRecord.Item).toEqual({ Id: 1, Foo: "Jane" })
})
it("calls the delete method with the correct params", async () => {
await dynamodb.delete({
table: tableName,
json: {
Name: "John",
},
})
expect(config.integration.client.delete).toHaveBeenCalledWith({
TableName: tableName,
Name: "John",
})
})
it("can delete", async () => {
await dynamodb.create(item({ Id: 1, Name: "John" }))
await dynamodb.delete(key({ Id: 1 }))
it("configures the dynamoDB constructor based on an empty endpoint parameter", async () => {
const config = {
region: "us-east-1",
accessKeyId: "test",
secretAccessKey: "test",
}
const integration: any = new DynamoDBIntegration.integration(config)
expect(integration.config).toEqual({
currentClockSkew: true,
...config,
})
})
it("configures the dynamoDB constructor based on a localhost endpoint parameter", async () => {
const config = {
region: "us-east-1",
accessKeyId: "test",
secretAccessKey: "test",
endpoint: "localhost:8080",
}
const integration: any = new DynamoDBIntegration.integration(config)
expect(integration.config).toEqual({
region: "us-east-1",
currentClockSkew: true,
endpoint: "localhost:8080",
})
})
it("configures the dynamoDB constructor based on a remote endpoint parameter", async () => {
const config = {
region: "us-east-1",
accessKeyId: "test",
secretAccessKey: "test",
endpoint: "dynamodb.aws.foo.net",
}
const integration = new DynamoDBIntegration.integration(config)
// @ts-ignore
expect(integration.config).toEqual({
currentClockSkew: true,
...config,
})
const deletedRecord = await dynamodb.get(key({ Id: 1 }))
expect(deletedRecord.Item).toBeUndefined()
})
})
}