UNPKG

@webda/core

Version:

Expose API with Lambda

906 lines 37.2 kB
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; }; import { suite, test } from "@testdeck/mocha"; import * as assert from "assert"; import { stub } from "sinon"; import { v4 as uuidv4 } from "uuid"; import { Ident } from "../../test/models/ident.js"; import { StoreParameters, WebdaError } from "../index.js"; import { CoreModel } from "../models/coremodel.js"; import { WebdaTest } from "../test.js"; import { HttpContext } from "../utils/httpcontext.js"; import { StoreNotFoundError, UpdateConditionFailError } from "./store.js"; /** * Fake model that refuse the half of the items */ export class PermissionModel extends CoreModel { async canAct(ctx, _action) { if (this.order % 200 < 120) { return false; } return true; } } let StoreParametersTest = class StoreParametersTest { cov() { let params = new StoreParameters({ expose: "/plop", lastUpdateField: "bz", creationDateField: "c" }, undefined); assert.deepStrictEqual(params.expose, { queryMethod: "GET", url: "/plop", restrict: {} }); assert.throws(() => new StoreParameters({ map: {} }, undefined), Error); assert.throws(() => new StoreParameters({ index: [] }, undefined), Error); } }; __decorate([ test ], StoreParametersTest.prototype, "cov", null); StoreParametersTest = __decorate([ suite ], StoreParametersTest); class StoreTest extends WebdaTest { /** * By default no testing index * @returns */ async getIndex() { return undefined; } /** * Recreate index if needed */ async recreateIndex() { } async before() { await super.before(); await this.getUserStore()?.__clean(); await this.getIdentStore()?.__clean(); await this.recreateIndex(); } getModelClass() { return Ident; } /** * Get the base of documents to query */ getQueryDocuments() { let docs = []; for (let i = 0; i < 1000; i++) { docs.push({ state: ["CA", "OR", "NY", "FL"][i % 4], states: [["CA", "OR", "NY", "FL"][i % 4], ["CA", "OR", "NY", "FL"][(i + 1) % 4]], order: i, team: { id: i % 20 }, role: i % 10 }); } return docs; } /** * Fill the Store with data to be queried */ async fillForQuery() { let userStore = this.getUserStore(); this.webda.getApplication().getModel("Webda/User").prototype.canAct = async () => true; userStore._model.prototype.canAct = async () => true; await Promise.all(this.getQueryDocuments().map(d => userStore.save(d))); return userStore; } async query() { let userStore = await this.fillForQuery(); const queries = { 'state = "CA"': 250, "team.id > 15": 200, "team.id >= 15": 250, "team.id <= 14": 750, 'state IN ["CA", "NY"]': 500, 'state IN ["CA", "NY", "NV"]': 500, 'state = "CA" AND team.id > 15': 50, "team.id < 5 OR team.id > 15": 450, "role < 5 AND team.id > 10 OR team.id > 15": 400, "role < 5 AND (team.id > 10 OR team.id > 15)": 200, 'state LIKE "C_"': 250, 'state LIKE "C__"': 0, 'state LIKE "C%"': 250, 'state != "CA"': 750, 'states CONTAINS "CA"': 500, "role = 4": 100, "": 1000 }; for (let i in queries) { assert.strictEqual((await userStore.query(i)).results.length, queries[i], `Query: ${i} should return ${queries[i]}`); } // Verify pagination system let offset; let res; let i = 0; do { res = await userStore.query(`LIMIT 100 ${offset ? 'OFFSET "' + offset + '"' : ""}`); offset = res.continuationToken; if (i++ > 9) { assert.strictEqual(res.results.length, 0, `Query: LIMIT 100 ${offset ? 'OFFSET "' + offset + '"' : ""} should return 0`); assert.strictEqual(offset, undefined); } else { assert.strictEqual(res.results.length, 100, `Query: LIMIT 100 ${offset ? 'OFFSET "' + offset + '"' : ""} should return 0`); } } while (offset !== undefined); // Verify permission issue and half pagination userStore.setModel(PermissionModel); userStore.getParameters().forceModel = true; if (userStore._cacheStore) { userStore._cacheStore.getParameters().forceModel = true; } let context = await this.newContext(); // Verify pagination system i = 0; let total = 0; let q; // To ensure we trigger slowQuery userStore.getParameters().slowQueryThreshold = 0; do { q = `team.id > 10 LIMIT 100 ${offset ? 'OFFSET "' + offset + '"' : ""}`; context.setHttpContext(new HttpContext("test.webda.io", i++ % 2 ? "GET" : "PUT", userStore.getParameters().expose.url + "?q=" + encodeURI(q), "https", 443)); context.getHttpContext().setBody({ q }); context.getParameters().q = q; // @ts-ignore await userStore.httpQuery(context); res = JSON.parse(context.getResponseBody()); offset = res.continuationToken; total += res.results.length; } while (offset !== undefined); assert.strictEqual(total, 180); q = "BAD QUERY !"; context.setHttpContext(new HttpContext("test.webda.io", "PUT", userStore.getParameters().expose.url, "https", 443)); context.getHttpContext().setBody({ q }); await assert.rejects(() => userStore["httpQuery"](context), (err) => err.getResponseCode() === 400); let mock = stub(userStore, "query").callsFake(() => { throw new Error("Plop"); }); try { await assert.rejects(() => userStore["httpQuery"](context), /Plop/); } finally { mock.restore(); } return userStore; } /** * Simplify model * @param model * @returns */ mapQueryModel(model) { return { order: model.order, teamId: model.team.id, state: model.state }; } async queryOrder() { let userStore = await this.fillForQuery(); let model = await userStore.save({ order: 996, state: "CA", team: { id: 16 } }); try { let res = await userStore.query('state = "CA" ORDER BY order DESC LIMIT 10'); assert.deepStrictEqual(res.results.map((c) => ({ state: c.state, order: c.order, teamId: c.team.id })), [ { state: "CA", order: 996, teamId: 16 }, { state: "CA", order: 996, teamId: 16 }, { state: "CA", order: 992, teamId: 12 }, { state: "CA", order: 988, teamId: 8 }, { state: "CA", order: 984, teamId: 4 }, { state: "CA", order: 980, teamId: 0 }, { state: "CA", order: 976, teamId: 16 }, { state: "CA", order: 972, teamId: 12 }, { state: "CA", order: 968, teamId: 8 }, { state: "CA", order: 964, teamId: 4 } ]); res = await userStore.query("order > 980 ORDER BY state ASC, order DESC LIMIT 10"); assert.deepStrictEqual(res.results.map((c) => ({ state: c.state, order: c.order, teamId: c.team.id })), [ { state: "CA", order: 996, teamId: 16 }, { state: "CA", order: 996, teamId: 16 }, { state: "CA", order: 992, teamId: 12 }, { state: "CA", order: 988, teamId: 8 }, { state: "CA", order: 984, teamId: 4 }, { state: "FL", order: 999, teamId: 19 }, { state: "FL", order: 995, teamId: 15 }, { state: "FL", order: 991, teamId: 11 }, { state: "FL", order: 987, teamId: 7 }, { state: "FL", order: 983, teamId: 3 } ]); } finally { await model.delete(); } } async mapper() { let identStore = this.getIdentStore(); let userStore = this.getUserStore(); let user1, ident1, ident2, user2; var eventFired = 0; var events = [ "Store.Save", "Store.Saved", "Store.Get", "Store.Delete", "Store.Deleted", "Store.Update", "Store.Updated", "Store.Query", "Store.Queried" ]; for (let evt in events) { identStore.on(events[evt], function (evt) { eventFired++; }); } assert.strictEqual(await userStore.get(undefined), undefined); user1 = (await userStore.save({ name: "test" })).getUuid(); let user = await userStore.get(user1); // Save a user and add an ident assert.notStrictEqual(user, undefined); user1 = user.getUuid(); ident1 = await identStore.save({ type: "facebook", _user: user.getUuid() }); user = await userStore.get(user1); // Verify the ident is on the user assert.notStrictEqual(user, undefined); assert.notStrictEqual(user.idents, undefined); assert.strictEqual(user.idents.length, 1); // Retrieve index to verify it is in it too let index = await this.getIndex(); // Do not force index test for store if (index) { assert.notStrictEqual(index[ident1.uuid], undefined); assert.strictEqual(index[ident1.uuid].type, "facebook"); } let lastUpdate = user.idents[0]._lastUpdate; await this.sleep(10); await identStore.incrementAttribute(ident1.uuid, "counter", 1); await user.refresh(); assert.notStrictEqual(user.idents[0]._lastUpdate, 0); this.assertLastUpdateNotEqual(user.idents[0]._lastUpdate, lastUpdate, "lastUpdate on a map after incrementAttribute"); lastUpdate = user.idents[0]._lastUpdate; await this.sleep(10); await identStore.upsertItemToCollection(ident1.uuid, "actions", { uuid: "action_1", type: "plop", date: new Date() }); await user.refresh(); assert.notStrictEqual(user.idents[0]._lastUpdate.length, 0); this.assertLastUpdateNotEqual(user.idents[0]._lastUpdate, lastUpdate, "lastUpdate on a map after upsertItemToCollection"); lastUpdate = user.idents[0]._lastUpdate; await this.sleep(10); await identStore.deleteItemFromCollection(ident1.uuid, "actions", 0, "plop", "type"); await user.refresh(); assert.notStrictEqual(user.idents[0]._lastUpdate.length, 0); this.assertLastUpdateNotEqual(user.idents[0]._lastUpdate, lastUpdate, "lastUpdate on a map after deleteItemFromCollection"); ident2 = await identStore.save({ type: "google", _user: user.uuid }); // Ensure Date is returned assert.ok(ident2._creationDate instanceof Date); assert.ok(ident2._lastUpdate instanceof Date); // Add a second ident and check it is on the user aswell user = await userStore.get(user1); assert.strictEqual(user.idents.length, 2); // Check index if (index) { await index.refresh(); assert.notStrictEqual(index[ident2.uuid], undefined); } ident2.type = "google2"; // Update ident2 to check mapper update let res = await identStore.patch({ uuid: ident2.uuid, type: "google2" }, true, null); assert.strictEqual(res.type, "google2"); assert.strictEqual(res._user.toString(), user1); // Check index if (index) { await index.refresh(); assert.strictEqual(index[ident2.uuid].type, "google2"); } user = await userStore.get(user1); assert.strictEqual(user.idents.length, 2); assert.strictEqual(user.idents[1].type, "google2"); await identStore.delete(ident1.uuid); user = await userStore.get(user1); assert.strictEqual(user.idents.length, 1); assert.strictEqual(user.idents[0].type, "google2"); // Add a second user to play user = await userStore.save({ name: "test2" }); user2 = user.uuid; // Move ident2 from user1 to user2 await identStore.patch({ _user: user.uuid, uuid: ident2.uuid }); // Check user1 has no more ident user = await userStore.get(user1); assert.strictEqual(user.idents.length, 0); // Check user2 has one ident user = await userStore.get(user2); assert.strictEqual(user.idents.length, 1); assert.strictEqual(user.idents[0].type, "google2"); // Verify you cannot update a collection from patch await userStore.patch({ idents: [] }, user2); user = await userStore.get(user2); assert.strictEqual(user.idents.length, 1); // Verify you cannot update a collection from update await userStore.update({ idents: [] }, user2); user = await userStore.get(user2); assert.strictEqual(user.idents.length, 1); assert.strictEqual(user.idents[0].type, "google2"); // Verify delete cascade with empty collection await userStore.delete(user1); user = await userStore.get(user2); assert.strictEqual(user.idents.length, 1); assert.strictEqual(user.idents[0].type, "google2"); // Verify delete cascade await userStore.delete(user2); let ident = await identStore.get(ident2.uuid); assert.strictEqual(ident.__deleted, true); // Check index if (index) { await index.refresh(); assert.strictEqual(index[ident2.uuid], undefined); assert.strictEqual(index[ident1.uuid], undefined); } assert.strictEqual(eventFired, 9); // Force sync delete - overriding the asyncDelete parameter await identStore.forceDelete(ident2.uuid); ident = await identStore.get(ident2.uuid); assert.strictEqual(ident, undefined); assert.strictEqual(eventFired, 11); } async collection() { let identStore = this.getIdentStore(); var ident; ident = await identStore.save({ test: "plop" }); await identStore.upsertItemToCollection(ident.uuid, "actions", { uuid: "action_1", type: "plop", date: new Date() }); await ident.refresh(); assert.notStrictEqual(ident.actions, undefined); assert.strictEqual(ident.actions.length, 1); await identStore.upsertItemToCollection(ident.uuid, "actions", { uuid: "action_2", type: "plop", date: new Date() }); await ident.refresh(); assert.notStrictEqual(ident.actions, undefined); assert.strictEqual(ident.actions.length, 2); await identStore.upsertItemToCollection(ident.uuid, "actions", { uuid: "action_1", type: "plop2", date: new Date() }, 0); await ident.refresh(); this.log("DEBUG", "Action", ident.actions); assert.notStrictEqual(ident.actions, undefined); assert.strictEqual(ident.actions.length, 2); assert.strictEqual(ident.actions[0].type, "plop2"); assert.strictEqual(ident.actions[0].uuid, "action_1"); await assert.rejects(() => identStore.upsertItemToCollection(ident.uuid, "actions", { uuid: "action_1", type: "plop2", date: new Date() }, 0, "plop", "type"), err => true); await assert.rejects(() => identStore.deleteItemFromCollection(ident.uuid, "actions", 0, "action_2"), err => true); await ident.refresh(); assert.strictEqual(ident.actions.length, 2); assert.strictEqual(ident.actions[0].type, "plop2"); let lastUpdate = ident._lastUpdate; await this.sleep(10); await identStore.upsertItemToCollection(ident.uuid, "actions", { uuid: "action_1", type: "plop", date: new Date() }, 0, "plop2", "type"); await ident.refresh(); this.assertLastUpdateNotEqual(ident._lastUpdate, lastUpdate, "lastUpdate after upsertItemToColletion failed"); lastUpdate = ident._lastUpdate; await this.sleep(10); await identStore.deleteItemFromCollection(ident.uuid, "actions", 0, "plop", "type"); ident = await identStore.get(ident.uuid); this.assertLastUpdateNotEqual(ident._lastUpdate, lastUpdate, "lastUpdate after deleteItemToColletion failed"); assert.notStrictEqual(ident.actions, undefined); assert.strictEqual(ident.actions.length, 1); assert.strictEqual(ident.actions[0].type, "plop"); assert.strictEqual(ident.actions[0].uuid, "action_2"); } async getAll() { let userStore = this.getUserStore(); var user1; var user3; user1 = await userStore.save({ name: "test1" }); await userStore.save({ name: "test2" }); user3 = await userStore.save({ name: "test3" }); let users = await userStore.getAll(); assert.strictEqual(users.length, 3); assert.strictEqual(users[0] instanceof userStore._model, true); assert.strictEqual(users[1] instanceof userStore._model, true); assert.strictEqual(users[2] instanceof userStore._model, true); users = await userStore.getAll([user1.uuid, user3.uuid, uuidv4()]); assert.strictEqual(users.length, 2); assert.strictEqual(users[0] instanceof userStore._model, true); assert.strictEqual(users[1] instanceof userStore._model, true); } async crud() { let identStore = this.getIdentStore(); var eventFired = 0; var events = [ "Store.Save", "Store.Saved", "Store.Get", "Store.Delete", "Store.Deleted", "Store.Update", "Store.Updated", "Store.PatchUpdate", "Store.PatchUpdated", "Store.PartialUpdated", "Store.Query", "Store.Queried" ]; for (let evt in events) { identStore.on(events[evt], function (e) { eventFired++; }); } this.log("DEBUG", "Save ident"); // Check CREATE - READ let ident1 = await identStore.save({ test: "plop", cool: "", lastUsed: new Date(), arr: [], details: { plop: "plop1", clean: undefined, yop: "pouf" } }); assert.strictEqual(eventFired, 2); assert.notStrictEqual(ident1, undefined); eventFired = 0; this.log("DEBUG", "Get ident"); let getter = await identStore.get(ident1.uuid); assert.strictEqual(eventFired, 1); eventFired = 0; assert.notStrictEqual(getter, undefined); assert.notStrictEqual(getter.lastUsed, undefined); assert.notStrictEqual(getter._lastUpdate, undefined); assert.strictEqual(getter.uuid, ident1.uuid); assert.strictEqual(getter.test, ident1.test); // Check UPDATE getter.test = "plop2"; getter.details.plop = "plop2"; getter.details.blank = ""; getter.details.bouzouf = undefined; getter.empty = []; let object; this.log("DEBUG", "Update ident"); await identStore.update(getter); assert.strictEqual(eventFired, 2); eventFired = 0; getter = {}; getter.uuid = ident1.uuid; getter.bouzouf = "test"; this.log("DEBUG", "Patch ident"); await identStore.patch(getter); assert.strictEqual(eventFired, 2); eventFired = 0; this.log("DEBUG", "Get ident to check update"); object = await identStore.get(ident1.uuid); this.log("DEBUG", "Retrieved object", object); assert.strictEqual(object.test, "plop2"); assert.strictEqual(object.details.plop, "plop2"); getter = await identStore.get(object.uuid); assert.strictEqual(eventFired, 2); assert.strictEqual(getter.test, "plop2"); await this.sleep(10); this.log("DEBUG", "Increment attribute"); await identStore.incrementAttribute(ident1.uuid, "counter", 1); let ident = await identStore.get(ident1.uuid); // Verify lastUpdate is updated too this.assertLastUpdateNotEqual(ident._lastUpdate, ident1._lastUpdate, "lastUpdate after incrementAttribute failed"); assert.strictEqual(ident.counter, 1); await identStore.incrementAttribute(ident1.uuid, "counter", 3); ident1 = await identStore.get(ident1.uuid); assert.strictEqual(ident1.counter, 4); await identStore.incrementAttributes(ident1.uuid, [ { property: "counter", value: -6 }, { property: "counter2", value: 10 } ]); let res = await identStore.exists(ident1.uuid); assert.strictEqual(res, true); // We should be able to verify with the full model await identStore.exists(ident1); assert.strictEqual(res, true); ident1 = await identStore.get(ident1.uuid); assert.strictEqual(ident1.counter, -2); // Check DELETE eventFired = 0; await identStore.forceDelete(ident1.uuid); assert.strictEqual(eventFired, 2); eventFired = 0; ident = await identStore.get(ident1.uuid); assert.strictEqual(ident, undefined); res = await identStore.exists(ident1.uuid); assert.strictEqual(res, false); } assertLastUpdateNotEqual(d1, d2, msg) { assert.notStrictEqual(d1, d2, msg); } async exists() { let store = this.getIdentStore(); let model = await store.save({}); assert.ok(await store.exists(model.getUuid())); assert.ok(await store.exists(model)); assert.ok(!(await store.exists(uuidv4()))); } async incrementAttribute() { let store = this.getIdentStore(); let model = await store.save({ counter: 0 }); await store.incrementAttribute(model.getUuid(), "counter", 3); await store.incrementAttribute(model.getUuid(), "counter2", 2); await model.refresh(); assert.strictEqual(model.counter, 3); assert.strictEqual(model.counter2, 2); await assert.rejects(() => store.incrementAttribute(uuidv4(), "counter", 1), StoreNotFoundError); } async removeAttribute() { let store = this.getIdentStore(); let model = await store.save({ counter: 0, counter2: 12, counter3: 13 }); await store.removeAttribute(model.getUuid(), "counter"); await model.refresh(); assert.strictEqual(model.counter, undefined); await assert.rejects(() => store.removeAttribute(uuidv4(), "counter"), StoreNotFoundError); await assert.rejects(() => store.removeAttribute(model.getUuid(), "counter2", 10, "counter3"), UpdateConditionFailError); await model.refresh(); assert.strictEqual(model.counter2, 12); } async setAttribute() { let store = this.getIdentStore(); let model = await store.save({ counter: 0 }); await store.setAttribute(model.getUuid(), "counter", 3); await store.setAttribute(model.getUuid(), "status", "TESTED"); await model.refresh(); assert.strictEqual(model.counter, 3); assert.strictEqual(model.status, "TESTED"); await assert.rejects(() => store.setAttribute(uuidv4(), "counter", 4), StoreNotFoundError); store.on("Store.PatchUpdate", async () => { model._lastUpdate = new Date(100); // @ts-ignore await store._update(model, model.getUuid()); }); await assert.rejects(() => store.setAttribute(model.getUuid(), "counter", 4), UpdateConditionFailError); store.removeAllListeners("Store.PatchUpdate"); store.on("Store.PatchUpdate", async () => { // @ts-ignore await store._delete(model.getUuid()); await this.sleep(1); }); await assert.rejects(() => store.setAttribute(model.getUuid(), "counter", 4), err => err instanceof StoreNotFoundError || err instanceof UpdateConditionFailError); await assert.rejects(() => store.setAttribute(uuidv4(), "counter", 4), err => err instanceof StoreNotFoundError || err instanceof UpdateConditionFailError); } async deleteAsync() { let store = this.getIdentStore(); let model = await store.save({ counter: 1 }); // Delete with condition await assert.rejects(() => store.delete(model.getUuid(), 4, "counter"), UpdateConditionFailError); await store.delete(model.getUuid(), 1, "counter"); // Test without condition model = await store.save({ counter: 2 }); await store.delete(model); // Deleting a non-existing object should be ignored await store.forceDelete(uuidv4()); } async delete() { // UserStore is not supposed to be async let store = this.getUserStore(); let model = await store.save({ counter: 1 }); // Delete with condition await assert.rejects(() => store.delete(model.getUuid(), 4, "counter"), UpdateConditionFailError); await store.delete(model.getUuid(), 1, "counter"); // Test without condition model = await store.save({ counter: 2 }); await store.delete(model); // Deleting a non-existing object should be ignored await store.forceDelete(uuidv4()); } async deleteConcurrent() { let store = this.getUserStore(); let model = await store.save({ counter: 1 }); store.addListener("Store.Delete", async () => { await store.incrementAttribute(model.getUuid(), "counter", 1); }); await assert.rejects(() => store.delete(model.getUuid(), 1, "counter"), UpdateConditionFailError); store.removeAllListeners(); await store.delete(model.getUuid(), 2, "counter"); } async conditionUpdate() { let store = this.getIdentStore(); let model = await store.save({ counter: 1 }); assert.ok(await store.conditionalPatch(model.getUuid(), { plop: 12, counter: 2 }, "counter", 1)); assert.strictEqual((await store.get(model.getUuid())).plop, 12); assert.ok(!(await store.conditionalPatch(model.getUuid(), { plop: 13 }, "counter", 1))); assert.strictEqual((await store.get(model.getUuid())).plop, 12); // @ts-ignore stub(store, "_patch").callsFake(() => { throw new Error("Fake Error"); }); await assert.rejects(() => store.conditionalPatch(model.getUuid(), { plop: 12, counter: 2 }, "counter", 1), /Fake Error/); } async update(delay = 1) { let store = this.getIdentStore(); let model = await store.save({ counter: 1 }); model.saveUpdateCompat = true; await store.save(model, await this.newContext()); model.saveInnerMethod = true; model.setContext(await this.newContext()); await model.save(); let model2 = await store.get(model.getUuid()); store.on("Store.Update", async () => { model2._lastUpdate = new Date(100); // @ts-ignore await store._update(model2, model2.getUuid()); }); model.plop = "yop"; // Delete with condition await assert.rejects(() => store.update(model), UpdateConditionFailError); store.removeAllListeners("Store.Update"); store.on("Store.Update", async () => { // @ts-ignore await store._delete(model.getUuid()); await this.sleep(delay); }); await assert.rejects(() => store.update(model), err => err instanceof StoreNotFoundError || err instanceof UpdateConditionFailError); await assert.rejects(() => store.update({ uuid: uuidv4(), test: true }), err => err instanceof StoreNotFoundError || err instanceof UpdateConditionFailError); } async upsertItem() { let store = this.getIdentStore(); this.log("DEBUG", "Save empty logs array"); let model = await store.save({ logs: [] }); let ps = []; this.log("DEBUG", "Upsert 10 lines"); for (let i = 0; i < 10; i++) { ps.push(store.upsertItemToCollection(model.getUuid(), "logs", `line${i}`)); } await Promise.all(ps); await model.refresh(); assert.strictEqual(model.logs.length, 10); // Depending on the implementation it can be swallowed by the backend this.log("DEBUG", "Upsert on unknown doc"); await assert.rejects(() => store.upsertItemToCollection(uuidv4(), "logs", `line`), err => err instanceof StoreNotFoundError || err instanceof UpdateConditionFailError); this.log("DEBUG", "Delete on unknown doc"); await assert.rejects(() => store.deleteItemFromCollection(uuidv4(), "logs", 0, undefined, undefined), err => err instanceof StoreNotFoundError || err instanceof UpdateConditionFailError); } async put() { const store = this.getIdentStore(); const uuid = store.getWebda().getUuid(); if (await store.exists(uuid)) { await store.delete(uuid); } await store.put(uuid, { test: true }); // Verify put acts like a upsert await store.put(uuid, { test: false }); } async httpCRUD(url = "/users") { let eventFired; let userStore = this.getUserStore(); let ctx, executor; await userStore.__clean(); ctx = await this.newContext({}); ctx.session.login("PLOP", "fake_ident"); executor = this.getExecutor(ctx, "test.webda.io", "POST", url, { type: "CRUD", uuid: "PLOP", displayName: "Coucou" }); assert.notStrictEqual(executor, undefined); await executor.execute(ctx); ctx.body = undefined; assert.strictEqual((await userStore.getAll()).length, 1); await this.getExecutor(ctx, "test.webda.io", "GET", `${url}/PLOP`).execute(ctx); assert.notStrictEqual(ctx.getResponseBody(), undefined); assert.strictEqual(ctx.getResponseBody().indexOf("_lastUpdate") >= 0, true); executor = this.getExecutor(ctx, "test.webda.io", "POST", url, { type: "CRUD2", uuid: "PLOP", displayName: "Coucou 2" }); await assert.rejects(executor.execute(ctx), (err) => err.getResponseCode() === 409); // Verify the none overide of UUID await this.execute(ctx, "test.webda.io", "PUT", `${url}/PLOP`, { type: "CRUD2", additional: "field", uuid: "PLOP2", user: "fake_user", displayName: "Coucou 3", roles: [] }); let user = await userStore.get("PLOP"); assert.strictEqual(user.getUuid(), "PLOP"); assert.strictEqual(user.type, "CRUD2"); assert.strictEqual(user.additional, "field"); assert.strictEqual(user.user, "fake_user"); // Add a role to the user user.roles.push("plop"); await user.save(); user = await userStore.get("PLOP"); assert.deepStrictEqual(user.roles, ["plop"]); ctx.resetResponse(); // Check PATH await this.execute(ctx, "test.webda.io", "PATCH", `${url}/PLOP`, { type: "CRUD3", uuid: "PLOP2", _testor: "_ should not be update by client" }); user = await userStore.get("PLOP"); assert.strictEqual(user.uuid, "PLOP"); assert.strictEqual(user.type, "CRUD3"); assert.strictEqual(user.additional, "field"); assert.strictEqual(user._testor, undefined); assert.deepStrictEqual(user.roles, ["plop"]); executor = this.getExecutor(ctx, "test.webda.io", "PUT", `${url}/PLOP`, { type: "CRUD3", uuid: "PLOP2", _testor: "_ should not be update by client", displayName: "yep" }); await executor.execute(ctx); user = await userStore.get("PLOP"); assert.strictEqual(user.uuid, "PLOP"); assert.strictEqual(user.type, "CRUD3"); assert.strictEqual(user.additional, undefined); assert.strictEqual(user._testor, undefined); assert.deepStrictEqual(user.roles, undefined); await this.getExecutor(ctx, "test.webda.io", "DELETE", `${url}/PLOP`).execute(ctx); eventFired = 0; executor = this.getExecutor(ctx, "test.webda.io", "GET", `${url}/PLOP`); await assert.rejects(() => executor.execute(ctx), WebdaError.NotFound); eventFired++; executor = this.getExecutor(ctx, "test.webda.io", "DELETE", `${url}/PLOP`); await assert.rejects(() => executor.execute(ctx), WebdaError.NotFound); eventFired++; executor = this.getExecutor(ctx, "test.webda.io", "PUT", `${url}/PLOP`); await assert.rejects(() => executor.execute(ctx), WebdaError.NotFound); eventFired++; assert.strictEqual(eventFired, 3); } async modelActions(url = "/idents") { let identStore = this.getIdentStore(); assert.notStrictEqual(identStore.getModel(), undefined); let eventFired = 0; let executor, ctx; identStore.on("Store.Action", evt => { eventFired++; }); identStore.on("Store.Actioned", evt => { eventFired++; }); ctx = await this.newContext({ type: "CRUD", uuid: "PLOP" }); executor = this.getExecutor(ctx, "test.webda.io", "PUT", `${url}/coucou/plop`); assert.notStrictEqual(executor, undefined); await assert.rejects(executor.execute(ctx), WebdaError.NotFound); await identStore.save({ uuid: "coucou" }); await executor.execute(ctx); // Our fake action is pushing true to _plop assert.strictEqual(JSON.parse(ctx.getResponseBody())._plop, true); assert.strictEqual(eventFired, 2); assert.notStrictEqual(this.getExecutor(ctx, "test.webda.io", "POST", `${url}/coucou/yop`), null); executor = this.getExecutor(ctx, "test.webda.io", "GET", `${url}/coucou/yop`); assert.notStrictEqual(executor, null); // Test with action returning the result instead of writing it ctx.resetResponse(); await executor.execute(ctx); assert.strictEqual(ctx.getResponseBody(), "youpi"); } } __decorate([ test ], StoreTest.prototype, "query", null); __decorate([ test ], StoreTest.prototype, "queryOrder", null); __decorate([ test ], StoreTest.prototype, "mapper", null); __decorate([ test ], StoreTest.prototype, "collection", null); __decorate([ test ], StoreTest.prototype, "getAll", null); __decorate([ test ], StoreTest.prototype, "crud", null); __decorate([ test ], StoreTest.prototype, "exists", null); __decorate([ test ], StoreTest.prototype, "incrementAttribute", null); __decorate([ test ], StoreTest.prototype, "removeAttribute", null); __decorate([ test ], StoreTest.prototype, "setAttribute", null); __decorate([ test ], StoreTest.prototype, "deleteAsync", null); __decorate([ test ], StoreTest.prototype, "delete", null); __decorate([ test ], StoreTest.prototype, "conditionUpdate", null); __decorate([ test ], StoreTest.prototype, "update", null); __decorate([ test ], StoreTest.prototype, "upsertItem", null); __decorate([ test ], StoreTest.prototype, "put", null); export { StoreTest }; //# sourceMappingURL=store.spec.js.map