Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ jobs:
steps:
- checkout
- run: yarn
- run: yarn build
- run: yarn test

test_with_db:
Expand All @@ -20,6 +21,7 @@ jobs:
steps:
- checkout
- run: yarn
- run: yarn build
- run: yarn test

workflows:
Expand Down
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
lib/
renovate.json
tsconfig.json
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.idea/
coverage/
node_modules/
lib/
temp
yarn.lock
*.log
Expand Down
7 changes: 6 additions & 1 deletion jest-dynamodb-config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
module.exports = {
/**
* @type {import('./lib/types').Config}
*/
const config = {
tables: [
{
TableName: `files`,
Expand All @@ -16,3 +19,5 @@ module.exports = {
port: 8000,
options: ['-sharedDb'],
};

module.exports = config;
8 changes: 2 additions & 6 deletions jest-preset.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
const {resolve} = require('path');
const preset = require('./lib');

module.exports = {
globalSetup: resolve(__dirname, './setup.js'),
globalTeardown: resolve(__dirname, './teardown.js'),
testEnvironment: resolve(__dirname, './environment.js'),
};
module.exports = preset;
27 changes: 18 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,25 @@
"url": "shelf.io"
},
"files": [
"environment.js",
"jest-preset.js",
"setup.js",
"teardown.js",
"wait-for-localhost.js"
"lib"
],
"scripts": {
"build": "rm -rf lib/ && yarn build:types && babel src --out-dir lib --ignore '**/*.test.ts' --extensions '.ts'",
"build:types": "tsc --emitDeclarationOnly --declaration --isolatedModules false --declarationDir lib",
"coverage": "jest --coverage",
"lint": "eslint . --ext .js,.ts,.json --fix",
"lint:ci": "eslint . --ext .js,.ts,.json",
"test": "export ENVIRONMENT=local && jest ."
"prepack": "yarn build",
"test": "export ENVIRONMENT=local && jest tests",
"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch"
},
"lint-staged": {
"*.{html,md,yml}": [
"prettier --write"
],
"*.{js,json}": [
"*.{ts,js,json}": [
"eslint --fix"
]
},
Expand All @@ -53,10 +55,17 @@
"dynamodb-local": "0.0.31"
},
"devDependencies": {
"@shelf/babel-config": "1.0.2",
"@shelf/eslint-config": "2.18.0",
"@babel/cli": "7.18.9",
"@babel/core": "7.18.9",
"@shelf/babel-config": "1.2.0",
"@shelf/eslint-config": "2.22.0",
"@shelf/prettier-config": "1.0.0",
"eslint": "8.20.0",
"@shelf/tsconfig": "0.0.8",
"@types/aws-sdk": "2.7.0",
"@types/cwd": "^0.10.0",
"@types/jest": "28.1.3",
"@types/node": "16",
"eslint": "8.21.0",
"husky": "8.0.1",
"jest": "28.1.3",
"lint-staged": "13.0.3",
Expand Down
73 changes: 0 additions & 73 deletions setup.js

This file was deleted.

11 changes: 8 additions & 3 deletions environment.js → src/environment.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/* eslint-disable no-console */
const {TestEnvironment} = require('jest-environment-node');
import type {EnvironmentContext} from '@jest/environment';
import type {JestEnvironmentConfig} from '@jest/environment';
import {TestEnvironment} from 'jest-environment-node';

const debug = require('debug')('jest-dynamodb');

module.exports = class DynamoDBEnvironment extends TestEnvironment {
constructor(config) {
super(config);
constructor(config: JestEnvironmentConfig, context: EnvironmentContext) {
super(config, context);
}

async setup() {
Expand All @@ -19,7 +22,9 @@ module.exports = class DynamoDBEnvironment extends TestEnvironment {
await super.teardown();
}

// @ts-ignore
runScript(script) {
// @ts-ignore
return super.runScript(script);
}
};
9 changes: 9 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {resolve} from 'path';

export * from './types';

export default {
globalSetup: resolve(__dirname, './setup.js'),
globalTeardown: resolve(__dirname, './teardown.js'),
testEnvironment: resolve(__dirname, './environment.js'),
};
91 changes: 91 additions & 0 deletions src/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import type {ListTablesCommandOutput} from '@aws-sdk/client-dynamodb/dist-types/commands/ListTablesCommand';
import type {argValues} from 'dynamodb-local';
import DynamoDbLocal from 'dynamodb-local';
import {resolve} from 'path';
import cwd from 'cwd';
import {DynamoDB} from '@aws-sdk/client-dynamodb';
import type {CreateTableCommandInput} from '@aws-sdk/client-dynamodb';
import type {Config} from './types';
import waitForLocalhost from './utils/wait-for-localhost';

const debug = require('debug')('jest-dynamodb');

const DEFAULT_PORT = 8000;
const DEFAULT_HOST = 'localhost';
const DEFAULT_OPTIONS: argValues[] = ['-sharedDb'];

export default async function () {
const {
tables: newTables,
clientConfig,
installerConfig,
port: port = DEFAULT_PORT,
hostname: hostname = DEFAULT_HOST,
options: options = DEFAULT_OPTIONS,
} = await getConfig();

const dynamoDB = new DynamoDB({
endpoint: `http://${hostname}:${port}`,
tls: false,
region: 'local-env',
credentials: {
accessKeyId: 'fakeMyKeyId',
secretAccessKey: 'fakeSecretAccessKey',
},
...clientConfig,
});

global.__DYNAMODB_CLIENT__ = dynamoDB;

try {
const promises: (Promise<ListTablesCommandOutput> | Promise<void>)[] = [
dynamoDB.listTables({}),
];

if (!global.__DYNAMODB__) {
promises.push(waitForLocalhost(port, hostname));
}

const [TablesList] = await Promise.all(promises);
const tableNames = TablesList?.TableNames;

if (tableNames) {
await deleteTables(dynamoDB, tableNames);
}
} catch (err) {
// eslint-disable-next-line no-console
debug(`fallback to launch DB due to ${err}`);

if (installerConfig) {
DynamoDbLocal.configureInstaller(installerConfig);
}

if (!global.__DYNAMODB__) {
debug('spinning up a local ddb instance');

global.__DYNAMODB__ = await DynamoDbLocal.launch(port, null, options);
debug(`dynamodb-local started on port ${port}`);

await waitForLocalhost(port, hostname);
}
}
debug(`dynamodb-local is ready on port ${port}`);

await createTables(dynamoDB, newTables);
}

function createTables(dynamoDB: DynamoDB, tables: CreateTableCommandInput[]) {
return Promise.all(tables.map(table => dynamoDB.createTable(table)));
}

function deleteTables(dynamoDB: DynamoDB, tableNames: string[]) {
return Promise.all(tableNames.map(tableName => dynamoDB.deleteTable({TableName: tableName})));
}

async function getConfig(): Promise<Config> {
const path = process.env.JEST_DYNAMODB_CONFIG || resolve(cwd(), 'jest-dynamodb-config.js');
const config = require(path);
debug('config:', config);

return typeof config === 'function' ? await config() : config;
}
11 changes: 8 additions & 3 deletions teardown.js → src/teardown.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const DynamoDbLocal = require('dynamodb-local');
import DynamoDbLocal from 'dynamodb-local';
import type {JestArgs} from './types';

const debug = require('debug')('jest-dynamodb');

module.exports = async function (jestArgs) {
module.exports = async function (jestArgs: JestArgs) {
// eslint-disable-next-line no-console
debug('Teardown DynamoDB');

Expand All @@ -14,6 +16,9 @@ module.exports = async function (jestArgs) {
} else {
const dynamoDB = global.__DYNAMODB_CLIENT__;
const {TableNames: tableNames} = await dynamoDB.listTables({});
await Promise.all(tableNames.map(tableName => dynamoDB.deleteTable({TableName: tableName})));

if (tableNames?.length) {
await Promise.all(tableNames.map(tableName => dynamoDB.deleteTable({TableName: tableName})));
}
}
};
Loading