
Security News
AGENTS.md Gains Traction as an Open Format for AI Coding Agents
AGENTS.md is a fast-growing open format giving AI coding agents a shared, predictable way to understand project setup, style, and workflows.
@shelf/jest-dynamodb
Advanced tools
Jest preset to run DynamoDB Local
$ yarn add @shelf/jest-dynamodb --dev
Make sure java
runtime available for running DynamoDBLocal.jar
jest.config.js
module.exports = {
preset: '@shelf/jest-dynamodb',
};
jest-dynamodb-config.js
object[]
true
Array of createTable params.
number
false
Port number. The default port number is 8000
.
string
false
Hostname. The default hostname is localhost
.
string[]
false
Additional arguments for dynamodb-local. The default value is ['-sharedDb']
.
object
false
Constructor params of DynamoDB client.
Type: {installPath?: string, downloadUrl?: string}
Required: false
installPath
defines the location where dynamodb-local is installed or will be installed.
downloadUrl
defines the url of dynamodb-local package.
The default value is defined at https://github.com/rynop/dynamodb-local/blob/2e6c1cb2edde4de0dc51a71c193c510b939d4352/index.js#L16-L19
You can set up tables as an object:
Whole list of config properties can be found here
/**
* @type {import('@shelf/jest-dynamodb/lib').Config}')}
*/
const config = {
tables: [
{
TableName: `files`,
KeySchema: [{AttributeName: 'id', KeyType: 'HASH'}],
AttributeDefinitions: [{AttributeName: 'id', AttributeType: 'S'}],
ProvisionedThroughput: {ReadCapacityUnits: 1, WriteCapacityUnits: 1},
},
// etc
],
port: 8000,
};
module.exports = config;
Or as an async function (particularly useful when resolving DynamoDB setup dynamically from serverless.yml
):
module.exports = async () => {
const serverless = new (require('serverless'))();
// If using monorepo where DynamoDB serverless.yml is in another directory
// const serverless = new (require('serverless'))({ servicePath: '../../../core/data' });
await serverless.init();
const service = await serverless.variables.populateService();
const resources = service.resources.filter(r => Object.keys(r).includes('Resources'))[0];
const tables = Object.keys(resources)
.map(name => resources[name])
.filter(r => r.Type === 'AWS::DynamoDB::Table')
.map(r => r.Properties);
return {
tables,
port: 8000,
};
};
Or read table definitions from a CloudFormation template (example handles a !Sub on TableName, i.e. TableName: !Sub "${env}-users" ):
const yaml = require('js-yaml');
const fs = require('fs');
const {CLOUDFORMATION_SCHEMA} = require('cloudformation-js-yaml-schema');
module.exports = async () => {
const cf = yaml.load(fs.readFileSync('../cf-templates/example-stack.yaml', 'utf8'), {
schema: CLOUDFORMATION_SCHEMA,
});
var tables = [];
Object.keys(cf.Resources).forEach(item => {
tables.push(cf.Resources[item]);
});
tables = tables
.filter(r => r.Type === 'AWS::DynamoDB::Table')
.map(r => {
let table = r.Properties;
if (typeof r.TableName === 'object') {
table.TableName = table.TableName.data.replace('${env}', 'test');
}
delete table.TimeToLiveSpecification; //errors on dynamo-local
return table;
});
return {
tables,
port: 8000,
};
};
const {DocumentClient} = require('aws-sdk/clients/dynamodb');
const isTest = process.env.JEST_WORKER_ID;
const config = {
convertEmptyValues: true,
...(isTest && {
endpoint: 'localhost:8000',
sslEnabled: false,
region: 'local-env',
credentials: {
accessKeyId: 'fakeMyKeyId',
secretAccessKey: 'fakeSecretAccessKey',
},
}),
};
const ddb = new DocumentClient(config);
const {DynamoDB} = require('@aws-sdk/client-dynamodb');
const {DynamoDBDocument} = require('@aws-sdk/lib-dynamodb');
const isTest = process.env.JEST_WORKER_ID;
const ddb = DynamoDBDocument.from(
new DynamoDB({
...(isTest && {
endpoint: 'http://localhost:8000',
region: 'local-env',
credentials: {
accessKeyId: 'fakeMyKeyId',
secretAccessKey: 'fakeSecretAccessKey',
},
}),
}),
{
marshallOptions: {
convertEmptyValues: true,
},
}
);
it('should insert item into table', async () => {
await ddb.put({TableName: 'files', Item: {id: '1', hello: 'world'}}).promise();
const {Item} = await ddb.get({TableName: 'files', Key: {id: '1'}}).promise();
expect(Item).toEqual({
id: '1',
hello: 'world',
});
});
By default the jest-dynamodb-config.js
is read from cwd
directory, but this might not be suitable for monorepos with nested jest projects with nested jest.config.*
files nested in subdirectories.
If your jest-dynamodb-config.js
file is not located at {cwd}/jest-dynamodb-config.js
or you are using nested jest projects
, you can define the environment variable JEST_DYNAMODB_CONFIG
with the absolute path of the respective jest-dynamodb-config.js
file.
JEST_DYNAMODB_CONFIG
in nested project// src/nested/project/jest.config.js
const path = require('path');
// Define path of project level config - extension not required as file will be imported via `require(process.env.JEST_DYNAMODB_CONFIG)`
process.env.JEST_DYNAMODB_CONFIG = path.resolve(__dirname, './jest-dynamodb-config');
module.exports = {
preset: '@shelf/jest-dynamodb'
displayName: 'nested-project',
};
Perhaps something is using your port specified in jest-dynamodb-config.js
.
See https://www.josephso.dev/using-jest-dynamodb-in-apple-silicon-platform-workaround/#community-build
$ git checkout master
$ yarn version
$ yarn publish
$ git push origin master --tags
MIT © Shelf
FAQs
Run your tests using Jest & DynamoDB local
The npm package @shelf/jest-dynamodb receives a total of 27,535 weekly downloads. As such, @shelf/jest-dynamodb popularity was classified as popular.
We found that @shelf/jest-dynamodb demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 59 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
AGENTS.md is a fast-growing open format giving AI coding agents a shared, predictable way to understand project setup, style, and workflows.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.