From b0c1d7ee6dcf693dc0925995cf735c3ae1baf749 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 17:10:20 +0000 Subject: [PATCH 1/4] wip --- packages/server/datasource-sha.env | 3 +- packages/server/src/integrations/dynamodb.ts | 6 +- .../src/integrations/tests/dynamodb.spec.ts | 276 ++++++++---------- .../src/integrations/tests/utils/dynamodb.ts | 41 +++ .../src/integrations/tests/utils/images.ts | 1 + .../src/integrations/tests/utils/index.ts | 3 + 6 files changed, 179 insertions(+), 151 deletions(-) create mode 100644 packages/server/src/integrations/tests/utils/dynamodb.ts diff --git a/packages/server/datasource-sha.env b/packages/server/datasource-sha.env index 69750793ce..13413dcb59 100644 --- a/packages/server/datasource-sha.env +++ b/packages/server/datasource-sha.env @@ -3,4 +3,5 @@ MYSQL_SHA=sha256:9de9d54fecee6253130e65154b930978b1fcc336bcc86dfd06e89b72a2588eb POSTGRES_SHA=sha256:bd0d8e485d1aca439d39e5ea99b931160bd28d862e74c786f7508e9d0053090e MONGODB_SHA=sha256:afa36bca12295b5f9dae68a493c706113922bdab520e901bd5d6c9d7247a1d8d MARIADB_SHA=sha256:e59ba8783bf7bc02a4779f103bb0d8751ac0e10f9471089709608377eded7aa8 -ELASTICSEARCH_SHA=sha256:9a6443f55243f6acbfeb4a112d15eb3b9aac74bf25e0e39fa19b3ddd3a6879d0 \ No newline at end of file +ELASTICSEARCH_SHA=sha256:9a6443f55243f6acbfeb4a112d15eb3b9aac74bf25e0e39fa19b3ddd3a6879d0 +DYNAMODB_SHA=sha256:cf8cebd061f988628c02daff10fdb950a54478feff9c52f6ddf84710fe3c3906 \ No newline at end of file diff --git a/packages/server/src/integrations/dynamodb.ts b/packages/server/src/integrations/dynamodb.ts index 96941ebb0e..6d8ae1c1c2 100644 --- a/packages/server/src/integrations/dynamodb.ts +++ b/packages/server/src/integrations/dynamodb.ts @@ -17,7 +17,7 @@ import { import { DynamoDB } from "@aws-sdk/client-dynamodb" import { AWS_REGION } from "../constants" -interface DynamoDBConfig { +export interface DynamoDBConfig { region: string accessKeyId: string secretAccessKey: string @@ -138,9 +138,9 @@ const SCHEMA: Integration = { }, } -class DynamoDBIntegration implements IntegrationBase { +export class DynamoDBIntegration implements IntegrationBase { private config: DynamoDBConfig - private client + private client: DynamoDBDocument constructor(config: DynamoDBConfig) { this.config = config diff --git a/packages/server/src/integrations/tests/dynamodb.spec.ts b/packages/server/src/integrations/tests/dynamodb.spec.ts index 75fb84ae60..49863c9912 100644 --- a/packages/server/src/integrations/tests/dynamodb.spec.ts +++ b/packages/server/src/integrations/tests/dynamodb.spec.ts @@ -1,167 +1,149 @@ -jest.mock("@aws-sdk/lib-dynamodb", () => ({ - DynamoDBDocument: { - from: jest.fn(() => ({ - update: jest.fn(), - put: jest.fn(), - query: jest.fn(() => ({ - Items: [], - })), - scan: jest.fn(() => ({ - Items: [], - })), - delete: jest.fn(), - get: jest.fn(), - })), - }, -})) -jest.mock("@aws-sdk/client-dynamodb") -import { default as DynamoDBIntegration } from "../dynamodb" +import { Datasource } from "@budibase/types" +import { DynamoDBConfig, DynamoDBIntegration } from "../dynamodb" +import { DatabaseName, datasourceDescribe } from "./utils" -class TestConfiguration { - integration: any +const describes = datasourceDescribe({ only: [DatabaseName.DYNAMODB] }) - constructor(config: any = {}) { - this.integration = new DynamoDBIntegration.integration(config) - } -} +if (describes.length > 0) { + describe.each(describes)("DynamoDB Integration", ({ dsProvider }) => { + let tableName = "Users" + let rawDatasource: Datasource + let dynamodb: DynamoDBIntegration -describe("DynamoDB Integration", () => { - let config: any - let tableName = "Users" - - beforeEach(() => { - config = new TestConfiguration() - }) - - it("calls the create method with the correct params", async () => { - await config.integration.create({ - table: tableName, - json: { - Name: "John", - }, + beforeEach(async () => { + const ds = await dsProvider() + rawDatasource = ds.rawDatasource! + dynamodb = new DynamoDBIntegration( + rawDatasource.config! as DynamoDBConfig + ) }) - 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: {}, + it.only("calls the create method with the correct params", async () => { + await dynamodb.create({ + table: tableName, + json: { + Name: "John", + }, + }) }) - 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" + it("calls the read method with the correct params", async () => { + const indexName = "Test" - const response = await config.integration.scan({ - table: tableName, - index: indexName, - json: {}, + const response = await dynamodb.read({ + table: tableName, + index: indexName, + json: {}, + }) + expect(config.integration.client.query).toHaveBeenCalledWith({ + TableName: tableName, + IndexName: indexName, + }) + expect(response).toEqual([]) }) - expect(config.integration.client.scan).toHaveBeenCalledWith({ - TableName: tableName, - IndexName: indexName, - }) - expect(response).toEqual([]) - }) - it("calls the get method with the correct params", async () => { - await config.integration.get({ - table: tableName, - json: { + it("calls the scan method with the correct params", async () => { + const indexName = "Test" + + const response = await dynamodb.scan({ + table: tableName, + index: indexName, + json: {}, + }) + expect(config.integration.client.scan).toHaveBeenCalledWith({ + TableName: tableName, + IndexName: indexName, + }) + expect(response).toEqual([]) + }) + + 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, - }, + }) }) - expect(config.integration.client.get).toHaveBeenCalledWith({ - TableName: tableName, - Id: 123, - }) - }) - - it("calls the update method with the correct params", async () => { - await config.integration.update({ - table: tableName, - json: { + it("calls the update method with the correct params", async () => { + await dynamodb.update({ + table: tableName, + json: { + Name: "John", + }, + }) + expect(config.integration.client.update).toHaveBeenCalledWith({ + TableName: tableName, Name: "John", - }, + }) }) - expect(config.integration.client.update).toHaveBeenCalledWith({ - TableName: tableName, - Name: "John", - }) - }) - it("calls the delete method with the correct params", async () => { - await config.integration.delete({ - table: tableName, - json: { + 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", - }, + }) }) - expect(config.integration.client.delete).toHaveBeenCalledWith({ - TableName: tableName, - Name: "John", + + 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, + }) }) }) - - 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, - }) - }) -}) +} diff --git a/packages/server/src/integrations/tests/utils/dynamodb.ts b/packages/server/src/integrations/tests/utils/dynamodb.ts new file mode 100644 index 0000000000..aae6358ece --- /dev/null +++ b/packages/server/src/integrations/tests/utils/dynamodb.ts @@ -0,0 +1,41 @@ +import { Datasource, SourceName } from "@budibase/types" +import { GenericContainer, Wait } from "testcontainers" +import { testContainerUtils } from "@budibase/backend-core/tests" +import { startContainer } from "." +import { DYNAMODB_IMAGE } from "./images" +import { DynamoDBConfig } from "../../dynamodb" + +let ports: Promise + +export async function getDatasource(): Promise { + if (!ports) { + ports = startContainer( + new GenericContainer(DYNAMODB_IMAGE) + .withExposedPorts(8000) + .withWaitStrategy( + Wait.forSuccessfulCommand( + // https://stackoverflow.com/a/77373799 + `if [ "$(curl -s -o /dev/null -I -w ''%{http_code}'' http://localhost:8000)" == "400" ]; then exit 0; else exit 1; fi` + ).withStartupTimeout(60000) + ) + ) + } + + const port = (await ports).find(x => x.container === 8000)?.host + if (!port) { + throw new Error("DynamoDB port not found") + } + + const config: DynamoDBConfig = { + accessKeyId: "test", + secretAccessKey: "test", + region: "us-east-1", + endpoint: `http://127.0.0.1:${port}`, + } + + return { + type: "datasource", + source: SourceName.DYNAMODB, + config, + } +} diff --git a/packages/server/src/integrations/tests/utils/images.ts b/packages/server/src/integrations/tests/utils/images.ts index c09b130ea5..68d219ac7d 100644 --- a/packages/server/src/integrations/tests/utils/images.ts +++ b/packages/server/src/integrations/tests/utils/images.ts @@ -13,3 +13,4 @@ export const POSTGRES_LEGACY_IMAGE = `postgres:9.5.25` export const MONGODB_IMAGE = `mongo@${process.env.MONGODB_SHA}` export const MARIADB_IMAGE = `mariadb@${process.env.MARIADB_SHA}` export const ELASTICSEARCH_IMAGE = `elasticsearch@${process.env.ELASTICSEARCH_SHA}` +export const DYNAMODB_IMAGE = `amazon/dynamodb-local@${process.env.DYNAMODB_SHA}` diff --git a/packages/server/src/integrations/tests/utils/index.ts b/packages/server/src/integrations/tests/utils/index.ts index 08777cab89..138861a9e6 100644 --- a/packages/server/src/integrations/tests/utils/index.ts +++ b/packages/server/src/integrations/tests/utils/index.ts @@ -7,6 +7,7 @@ import * as mssql from "./mssql" import * as mariadb from "./mariadb" import * as oracle from "./oracle" import * as elasticsearch from "./elasticsearch" +import * as dynamodb from "./dynamodb" import { testContainerUtils } from "@budibase/backend-core/tests" import { Knex } from "knex" import TestConfiguration from "../../../tests/utilities/TestConfiguration" @@ -25,6 +26,7 @@ export enum DatabaseName { ORACLE = "oracle", SQS = "sqs", ELASTICSEARCH = "elasticsearch", + DYNAMODB = "dynamodb", } const DATASOURCE_PLUS = [ @@ -50,6 +52,7 @@ const providers: Record = { // rest [DatabaseName.ELASTICSEARCH]: elasticsearch.getDatasource, [DatabaseName.MONGODB]: mongodb.getDatasource, + [DatabaseName.DYNAMODB]: dynamodb.getDatasource, } export interface DatasourceDescribeReturnPromise { From 1040830a644d9789efc247232b2fb86bf7934f7b Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 17:43:09 +0000 Subject: [PATCH 2/4] De-mock DynamoDB tests. --- .github/workflows/budibase_ci.yml | 3 + .../src/integrations/tests/dynamodb.spec.ts | 170 ++++++------------ 2 files changed, 61 insertions(+), 112 deletions(-) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index 2e7851b338..c8bdfe9655 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -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 & diff --git a/packages/server/src/integrations/tests/dynamodb.spec.ts b/packages/server/src/integrations/tests/dynamodb.spec.ts index 49863c9912..f7aafc6932 100644 --- a/packages/server/src/integrations/tests/dynamodb.spec.ts +++ b/packages/server/src/integrations/tests/dynamodb.spec.ts @@ -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) { + return { table, json: { Item: json } } + } + + function key(json: Record) { + 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() }) }) } From 39a7234d2e3c1714d65f310c4290ce401bb85bfe Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 18:02:30 +0000 Subject: [PATCH 3/4] Prevent accidental credential misuse during tests. --- packages/server/src/integrations/dynamodb.ts | 19 ++++++------------- .../src/integrations/tests/dynamodb.spec.ts | 17 +++++++++++++++-- packages/server/src/tests/jestSetup.ts | 6 ++++++ packages/worker/src/tests/jestSetup.ts | 9 +++++++-- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/packages/server/src/integrations/dynamodb.ts b/packages/server/src/integrations/dynamodb.ts index 6d8ae1c1c2..cfaa851cea 100644 --- a/packages/server/src/integrations/dynamodb.ts +++ b/packages/server/src/integrations/dynamodb.ts @@ -14,7 +14,7 @@ import { UpdateCommandInput, DeleteCommandInput, } from "@aws-sdk/lib-dynamodb" -import { DynamoDB } from "@aws-sdk/client-dynamodb" +import { DynamoDB, DynamoDBClientConfig } from "@aws-sdk/client-dynamodb" import { AWS_REGION } from "../constants" export interface DynamoDBConfig { @@ -22,7 +22,6 @@ export interface DynamoDBConfig { accessKeyId: string secretAccessKey: string endpoint?: string - currentClockSkew?: boolean } const SCHEMA: Integration = { @@ -139,21 +138,15 @@ const SCHEMA: Integration = { } export class DynamoDBIntegration implements IntegrationBase { - private config: DynamoDBConfig + private config: DynamoDBClientConfig private client: DynamoDBDocument constructor(config: DynamoDBConfig) { - this.config = config - - // User is using a local dynamoDB endpoint, don't auth with remote - if (this.config?.endpoint?.includes("localhost")) { - // @ts-ignore - this.config = {} - } - this.config = { - ...this.config, - currentClockSkew: true, + credentials: { + accessKeyId: config.accessKeyId, + secretAccessKey: config.secretAccessKey, + }, region: config.region || AWS_REGION, endpoint: config.endpoint || undefined, } diff --git a/packages/server/src/integrations/tests/dynamodb.spec.ts b/packages/server/src/integrations/tests/dynamodb.spec.ts index f7aafc6932..e6b1ed405c 100644 --- a/packages/server/src/integrations/tests/dynamodb.spec.ts +++ b/packages/server/src/integrations/tests/dynamodb.spec.ts @@ -1,7 +1,11 @@ import { Datasource } from "@budibase/types" import { DynamoDBConfig, DynamoDBIntegration } from "../dynamodb" import { DatabaseName, datasourceDescribe } from "./utils" -import { CreateTableCommandInput, DynamoDB } from "@aws-sdk/client-dynamodb" +import { + CreateTableCommandInput, + DynamoDB, + DynamoDBClientConfig, +} from "@aws-sdk/client-dynamodb" const describes = datasourceDescribe({ only: [DatabaseName.DYNAMODB] }) @@ -38,7 +42,16 @@ if (describes.length > 0) { rawDatasource.config! as DynamoDBConfig ) - const client = new DynamoDB(rawDatasource.config as DynamoDBConfig) + const config: DynamoDBClientConfig = { + credentials: { + accessKeyId: "test", + secretAccessKey: "test", + }, + region: "us-east-1", + endpoint: rawDatasource.config!.endpoint, + } + + const client = new DynamoDB(config) await createTable(client, { TableName: table, KeySchema: [{ AttributeName: "Id", KeyType: "HASH" }], diff --git a/packages/server/src/tests/jestSetup.ts b/packages/server/src/tests/jestSetup.ts index 60cf96cb51..663f0482ab 100644 --- a/packages/server/src/tests/jestSetup.ts +++ b/packages/server/src/tests/jestSetup.ts @@ -3,6 +3,12 @@ import * as matchers from "jest-extended" import { env as coreEnv, timers } from "@budibase/backend-core" import { testContainerUtils } from "@budibase/backend-core/tests" import nock from "nock" +import AWS from "aws-sdk" + +// Prevent accidental use of real AWS credentials +AWS.config.update({ + credentialProvider: new AWS.CredentialProviderChain([]), +}) expect.extend(matchers) if (!process.env.CI) { diff --git a/packages/worker/src/tests/jestSetup.ts b/packages/worker/src/tests/jestSetup.ts index 6a98031d34..682b92e1c3 100644 --- a/packages/worker/src/tests/jestSetup.ts +++ b/packages/worker/src/tests/jestSetup.ts @@ -2,18 +2,23 @@ import { mocks, testContainerUtils } from "@budibase/backend-core/tests" import env from "../environment" import { env as coreEnv, timers } from "@budibase/backend-core" import nock from "nock" +import AWS from "aws-sdk" // mock all dates to 2020-01-01T00:00:00.000Z // use tk.reset() to use real dates in individual tests import tk from "timekeeper" +// Prevent accidental use of real AWS credentials +AWS.config.update({ + credentialProvider: new AWS.CredentialProviderChain([]), +}) + nock.disableNetConnect() nock.enableNetConnect(host => { return ( host.includes("localhost") || host.includes("127.0.0.1") || - host.includes("::1") || - host.includes("ethereal.email") // used in realEmail.spec.ts + host.includes("::1") ) }) From 9cbef4651220cd02026881d78310ad52156a6909 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 4 Mar 2025 10:26:53 +0000 Subject: [PATCH 4/4] Remove global credentials attempt, didn't work. --- packages/server/src/tests/jestSetup.ts | 6 ------ packages/worker/src/tests/jestSetup.ts | 6 ------ 2 files changed, 12 deletions(-) diff --git a/packages/server/src/tests/jestSetup.ts b/packages/server/src/tests/jestSetup.ts index 663f0482ab..60cf96cb51 100644 --- a/packages/server/src/tests/jestSetup.ts +++ b/packages/server/src/tests/jestSetup.ts @@ -3,12 +3,6 @@ import * as matchers from "jest-extended" import { env as coreEnv, timers } from "@budibase/backend-core" import { testContainerUtils } from "@budibase/backend-core/tests" import nock from "nock" -import AWS from "aws-sdk" - -// Prevent accidental use of real AWS credentials -AWS.config.update({ - credentialProvider: new AWS.CredentialProviderChain([]), -}) expect.extend(matchers) if (!process.env.CI) { diff --git a/packages/worker/src/tests/jestSetup.ts b/packages/worker/src/tests/jestSetup.ts index 682b92e1c3..77501b2f06 100644 --- a/packages/worker/src/tests/jestSetup.ts +++ b/packages/worker/src/tests/jestSetup.ts @@ -2,17 +2,11 @@ import { mocks, testContainerUtils } from "@budibase/backend-core/tests" import env from "../environment" import { env as coreEnv, timers } from "@budibase/backend-core" import nock from "nock" -import AWS from "aws-sdk" // mock all dates to 2020-01-01T00:00:00.000Z // use tk.reset() to use real dates in individual tests import tk from "timekeeper" -// Prevent accidental use of real AWS credentials -AWS.config.update({ - credentialProvider: new AWS.CredentialProviderChain([]), -}) - nock.disableNetConnect() nock.enableNetConnect(host => { return (