@webda/aws
Version:
Webda AWS Services implementation
339 lines • 12.6 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var DynamoDBTest_1;
import { BatchWriteItemCommand, DescribeTableCommand, DynamoDB, DynamoDBClient, ScanCommand } from "@aws-sdk/client-dynamodb";
import { suite, test } from "@testdeck/mocha";
import { Ident, UpdateConditionFailError, getCommonJS } from "@webda/core";
import { StoreTest } from "@webda/core/lib/stores/store.spec.js";
import { WorkerOutput } from "@webda/workout";
import * as assert from "assert";
import { mockClient } from "aws-sdk-client-mock";
import path from "path";
import * as sinon from "sinon";
import { checkLocalStack, defaultCreds } from "../index.spec.js";
import { DynamoStore, DynamoStoreParameters } from "./dynamodb.js";
const { __dirname } = getCommonJS(import.meta.url);
let DynamoDBTest = DynamoDBTest_1 = class DynamoDBTest extends StoreTest {
async before() {
process.env.AWS_ACCESS_KEY_ID = defaultCreds.accessKeyId;
process.env.AWS_SECRET_ACCESS_KEY = defaultCreds.secretAccessKey;
process.env.AWS_DEFAULT_REGION = "us-east-1";
await checkLocalStack();
this.buildWebda();
await DynamoDBTest_1.install("webda-test-idents");
await DynamoDBTest_1.install("webda-test-users");
await super.before();
}
async tweakApp(app) {
super.tweakApp(app);
app.addService("test/awsevents", (await import(path.join(__dirname, ..."../../test/moddas/awsevents.js".split("/")))).AWSEventsHandler);
}
getIdentStore() {
return this.getService("Idents");
}
getUserStore() {
return this.getService("Users");
}
getModelClass() {
return Ident;
}
async queryOrder() {
// Disable default ordering query as it is not possible with Dynamo
}
static async install(TableName, GlobalSecondaryIndexes, attrs = []) {
var dynamodb = new DynamoDB({
endpoint: "http://localhost:4566",
credentials: defaultCreds,
region: "us-east-1"
});
try {
await dynamodb.describeTable({
TableName
});
}
catch (err) {
if (err.name === "ResourceNotFoundException") {
let createTable = {
TableName,
ProvisionedThroughput: {
ReadCapacityUnits: 5,
WriteCapacityUnits: 5
},
GlobalSecondaryIndexes,
KeySchema: [
{
AttributeName: "uuid",
KeyType: "HASH"
}
],
AttributeDefinitions: [
{
AttributeName: "uuid",
AttributeType: "S"
},
...attrs
]
};
let table = dynamodb.createTable(createTable);
return table;
}
}
}
async fillForQuery() {
await DynamoDBTest_1.install("webda-test-query", [
{
IndexName: "States",
KeySchema: [
{
AttributeName: "state",
KeyType: "HASH"
},
{
AttributeName: "order",
KeyType: "RANGE"
}
],
Projection: { ProjectionType: "ALL" },
ProvisionedThroughput: {
ReadCapacityUnits: 5,
WriteCapacityUnits: 5
}
}
], [
{
AttributeName: "state",
AttributeType: "S"
},
{
AttributeName: "order",
AttributeType: "N"
}
]);
let store = new DynamoStore(this.webda, "queryStore", {
table: "webda-test-query",
globalIndexes: {
States: {
key: "state",
sort: "order"
}
},
expose: {
url: "/none"
},
credentials: defaultCreds,
endpoint: "http://localhost:4566",
region: "us-east-1"
});
store.resolve();
await store.init();
if ((await store.getAll()).length < 1000) {
await Promise.all(this.getQueryDocuments().map(d => store.save(d)));
}
return store;
}
async query() {
// Run default query
let store = await super.query();
let res = await store.query('state = "CA" AND order < 100 ORDER BY team.id ASC, order DESC');
assert.strictEqual(res.results.shift().order, 96);
let set = ["CA"];
for (let i = 1; i < 150; i++) {
set.push(i.toString(16));
}
assert.strictEqual((await store.query(`state IN [${set.map(e => `"${e}"`).join(",")}]`)).results.length, 250);
// Add more test here
return store;
}
async dateHandling() {
let userStore = this.getUserStore();
await userStore.save({
uuid: "testUpdate",
subobject: {
empty: "",
t: {
plop: ""
},
date: new Date()
}
});
let user = await userStore.get("testUpdate");
assert.notStrictEqual(user.date, {});
}
bodyCleaning() {
//var parse = require("./data/to_clean.json");
let identStore = this.getIdentStore();
let ident = new Ident();
ident.load({
arr: [
{
value: "",
test: "oki"
},
{
value: ""
},
{
value: "Test"
}
],
sub: {
value: ""
},
__store: identStore
}, true);
let clean = identStore._cleanObject(ident);
assert.strictEqual(clean.sub.value, undefined);
assert.strictEqual(clean.__store, undefined);
assert.strictEqual(clean.arr instanceof Array, true);
assert.strictEqual(clean.arr[0].value, undefined);
assert.strictEqual(clean.arr[1].value, undefined);
assert.notStrictEqual(clean.arr[2].value, undefined);
}
ARNPolicy() {
let userStore = this.getService("Users");
userStore.getParameters().region = "eu-west-1";
assert.strictEqual(userStore.getARNPolicy("666").Resource[0], "arn:aws:dynamodb:eu-west-1:666:table/webda-test-users");
userStore.getParameters().region = undefined;
assert.strictEqual(userStore.getARNPolicy("777").Resource[0], "arn:aws:dynamodb:us-east-1:777:table/webda-test-users");
userStore.getParameters().CloudFormationSkip = true;
assert.deepStrictEqual(userStore.getCloudFormation(undefined), {});
}
async patchSkip() {
let userStore = this.getService("Users");
let s = sinon.spy(userStore._client, "update");
try {
await userStore._patch({ uuid: "test" }, "test");
assert.strictEqual(s.callCount, 0);
}
finally {
s.restore();
}
}
async deleteWithCondition() {
await assert.rejects(() => this.getService("Users")._delete("nop", new Date(), "p"), UpdateConditionFailError);
}
params() {
assert.throws(() => new DynamoStoreParameters({}, this.getService("Users")), /Need to define a table at least/);
}
async errors() {
let stubs = [];
try {
const faultyMethod = () => {
throw new Error("Unknown");
};
let userStore = this.getService("Users");
await assert.rejects(() => userStore._upsertItemToCollection("plop2", "test", "plop", 1, 2, "", new Date()), /Item not found plop2 Store/);
stubs = ["update", "delete", "put"].map(method => {
// @ts-ignore
return sinon.stub(userStore._client, method).callsFake(faultyMethod);
});
stubs.push(sinon.stub(userStore._client, "scan").callsFake((p, c) => {
// @ts-ignore
throw new Error("Unknown");
}));
await assert.rejects(() => userStore._removeAttribute("plop", "test"), /Unknown/);
await assert.rejects(() => userStore._deleteItemFromCollection("plop", "test", 1, "plop", 2, new Date()), /Unknown/);
await assert.rejects(() => userStore._upsertItemToCollection("plop", "test", "plop", 1, 2, "", new Date()), /Unknown/);
await assert.rejects(() => userStore._delete("plop"), /Unknown/);
await assert.rejects(() => userStore._patch({ t: "l" }, "plop"), /Unknown/);
await assert.rejects(() => userStore._update({ t: "l" }, "plop"), /Unknown/);
await assert.rejects(() => userStore._scan([]), /Unknown/);
await assert.rejects(() => userStore._incrementAttributes("plop", [{ property: "t", value: 1 }], new Date()), /Unknown/);
}
finally {
stubs.forEach(s => s.restore());
}
}
async patch() {
let userStore = this.getService("Users");
let stub = sinon.stub(userStore._client, "update").callsFake(() => {
let err = new Error();
// @ts-ignore
err.code = "ConditionalCheckFailedException";
throw err;
});
try {
assert.rejects(() => userStore._patch({ t: "l" }, "plop"), UpdateConditionFailError);
}
finally {
stub.restore();
}
}
async copyTable() {
const mock = mockClient(DynamoDBClient);
try {
mock.on(DescribeTableCommand).resolves({
Table: {
ItemCount: 50
}
});
const results = [];
let output = new WorkerOutput();
for (let i = 0; i < 50; i++) {
results.push({ Item: { S: `Title ${i}` } });
}
mock.on(ScanCommand).callsFake(async (p) => {
let offset = 0;
let LastEvaluatedKey;
if (p.ExclusiveStartKey) {
offset = parseInt(p.ExclusiveStartKey.year.N);
}
if (offset + 35 < results.length) {
LastEvaluatedKey = { year: { N: (offset + 35).toString() } };
}
return {
Items: results.slice(offset, 35),
LastEvaluatedKey
};
});
mock.on(BatchWriteItemCommand).resolves({});
let userStore = this.getService("users");
await DynamoStore.copyTable(output, "table1", "table2");
}
finally {
mock.restore();
}
}
};
__decorate([
test
], DynamoDBTest.prototype, "queryOrder", null);
__decorate([
test
], DynamoDBTest.prototype, "query", null);
__decorate([
test
], DynamoDBTest.prototype, "dateHandling", null);
__decorate([
test
], DynamoDBTest.prototype, "bodyCleaning", null);
__decorate([
test
], DynamoDBTest.prototype, "ARNPolicy", null);
__decorate([
test
], DynamoDBTest.prototype, "patchSkip", null);
__decorate([
test
], DynamoDBTest.prototype, "deleteWithCondition", null);
__decorate([
test
], DynamoDBTest.prototype, "params", null);
__decorate([
test
], DynamoDBTest.prototype, "errors", null);
__decorate([
test
], DynamoDBTest.prototype, "patch", null);
__decorate([
test
], DynamoDBTest.prototype, "copyTable", null);
DynamoDBTest = DynamoDBTest_1 = __decorate([
suite
], DynamoDBTest);
export { DynamoDBTest };
//# sourceMappingURL=dynamodb.spec.js.map