From 2d4b339a7fb30958dde58d4cd1962b75e96afb34 Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Thu, 2 Dec 2021 13:56:40 -0300 Subject: [PATCH 01/10] Updates Memo validation schema --- .../data/schemas/entities-schemas/memo.json | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/firebase/src/core/data/schemas/entities-schemas/memo.json b/firebase/src/core/data/schemas/entities-schemas/memo.json index be3252e3..bee47233 100644 --- a/firebase/src/core/data/schemas/entities-schemas/memo.json +++ b/firebase/src/core/data/schemas/entities-schemas/memo.json @@ -5,20 +5,54 @@ "description": "Properties of a Memo.", "type": "object", "properties": { - "id": { "type": "string" }, + "uniqueId": { "type": "string" }, "question": { "type": "array", - "items": { "type": "object" }, + "items": { + "type": "object", + "properties": { + "insert": { "type": "string" }, + "attributes": { + "type": "object", + "minProperties": 1, + "properties": { + "bold": { "type": "boolean" }, + "underline": { "type": "boolean" }, + "italic": { "type": "boolean" }, + "code-block": { "type": "boolean" } + }, + "additionalProperties": false + } + }, + "required": [ "insert" ] + }, "minItems": 1 }, "answer": { "type": "array", - "items": { "type": "object" }, + "items": { + "type": "object", + "properties": { + "insert": { "type": "string" }, + "attributes": { + "type": "object", + "minProperties": 1, + "properties": { + "bold": { "type": "boolean" }, + "underline": { "type": "boolean" }, + "italic": { "type": "boolean" }, + "code-block": { "type": "boolean" } + }, + "additionalProperties": false + } + }, + "required": [ "insert" ] + }, "minItems": 1 } }, "required": [ - "id", + "uniqueId", "question", "answer" ] From 8cd170fc52a7e2c8c5f09dae0fde99f5908d20c3 Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Thu, 2 Dec 2021 13:57:35 -0300 Subject: [PATCH 02/10] Updates Memo entity --- firebase/src/core/domain/models/memo.ts | 32 ++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/firebase/src/core/domain/models/memo.ts b/firebase/src/core/domain/models/memo.ts index 6a40ce4a..1b166f05 100644 --- a/firebase/src/core/domain/models/memo.ts +++ b/firebase/src/core/domain/models/memo.ts @@ -1,16 +1,36 @@ import { defaultMaxStringLength, validate } from "#utils/validate"; import * as Joi from "joi"; +interface MemoContent { + insert: string; + attributes?: { + bold?: boolean; + italic?: boolean; + underline?: boolean; + codeBlock?: boolean; + }; +} + export interface Memo { - readonly id: string; - readonly question: Record[]; - readonly answer: Record[]; + readonly uniqueId: string; + readonly question: MemoContent[]; + readonly answer: MemoContent[]; } +const memoContentValidationSchema = Joi.object({ + insert: Joi.string().max(defaultMaxStringLength).required(), + attributes: Joi.object({ + bold: Joi.boolean(), + italic: Joi.boolean(), + underline: Joi.boolean(), + codeBlock: Joi.boolean(), + }).min(1), +}); + export const memoValidationSchema = Joi.object({ - id: Joi.string().max(defaultMaxStringLength).required(), - question: Joi.array().items(Joi.object()).min(1).required(), - answer: Joi.array().items(Joi.object()).min(1).required(), + uniqueId: Joi.string().max(defaultMaxStringLength).required(), + question: Joi.array().items(memoContentValidationSchema).min(1).required(), + answer: Joi.array().items(memoContentValidationSchema).min(1).required(), }); export function validateMemo(memo: Memo): void { From 34052b86d350a21c0308d1fb4df332f1a519cb8b Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Thu, 2 Dec 2021 13:57:58 -0300 Subject: [PATCH 03/10] Moves `ajv` to base `package.json` --- firebase/package-lock.json | 1 + firebase/package.json | 1 + firebase/src/core/package-lock.json | 85 ++--------------------------- firebase/src/core/package.json | 1 - 4 files changed, 6 insertions(+), 82 deletions(-) diff --git a/firebase/package-lock.json b/firebase/package-lock.json index b97487d3..be6b41a2 100644 --- a/firebase/package-lock.json +++ b/firebase/package-lock.json @@ -13,6 +13,7 @@ "@types/sinon": "^10.0.x", "@typescript-eslint/eslint-plugin": "^4.32.x", "@typescript-eslint/parser": "^4.32.x", + "ajv": "^8.8.2", "eslint": "^7.32.x", "eslint-config-prettier": "^8.3.x", "eslint-plugin-prettier": "^4.0.x", diff --git a/firebase/package.json b/firebase/package.json index 3a7c3c14..f25ceb2a 100644 --- a/firebase/package.json +++ b/firebase/package.json @@ -40,6 +40,7 @@ "@types/sinon": "^10.0.x", "@typescript-eslint/eslint-plugin": "^4.32.x", "@typescript-eslint/parser": "^4.32.x", + "ajv": "^8.8.2", "eslint": "^7.32.x", "eslint-config-prettier": "^8.3.x", "eslint-plugin-prettier": "^4.0.x", diff --git a/firebase/src/core/package-lock.json b/firebase/src/core/package-lock.json index a4d2ecc5..c273295f 100644 --- a/firebase/src/core/package-lock.json +++ b/firebase/src/core/package-lock.json @@ -6,7 +6,6 @@ "": { "name": "memo-core", "dependencies": { - "ajv": "^8.6.x", "firebase-admin": "^9.11.x", "firebase-functions": "^3.16.x", "joi": "^17.4.x" @@ -531,21 +530,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "optional": true }, - "node_modules/ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -950,7 +934,8 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true }, "node_modules/fast-text-encoding": { "version": "1.0.3", @@ -1415,11 +1400,6 @@ "bignumber.js": "^9.0.0" } }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", @@ -1863,14 +1843,6 @@ "pump": "^3.0.0" } }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, "node_modules/qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", @@ -1924,14 +1896,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -2233,14 +2197,6 @@ "node": ">= 0.8" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2872,17 +2828,6 @@ } } }, - "ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -3204,7 +3149,8 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true }, "fast-text-encoding": { "version": "1.0.3", @@ -3561,11 +3507,6 @@ "bignumber.js": "^9.0.0" } }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", @@ -3937,11 +3878,6 @@ "pump": "^3.0.0" } }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", @@ -3980,11 +3916,6 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "optional": true }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" - }, "retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -4222,14 +4153,6 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/firebase/src/core/package.json b/firebase/src/core/package.json index 4130697f..337503b9 100644 --- a/firebase/src/core/package.json +++ b/firebase/src/core/package.json @@ -6,7 +6,6 @@ "main": "dist/src/core/index.js", "private": true, "dependencies": { - "ajv": "^8.6.x", "firebase-admin": "^9.11.x", "firebase-functions": "^3.16.x", "joi": "^17.4.x" From 8e8bbf7247edb484b8167628d5b7b0927cd1482c Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Thu, 2 Dec 2021 13:58:07 -0300 Subject: [PATCH 04/10] Adds debug launch action --- firebase/.vscode/launch.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/firebase/.vscode/launch.json b/firebase/.vscode/launch.json index 290872af..bedf92e8 100644 --- a/firebase/.vscode/launch.json +++ b/firebase/.vscode/launch.json @@ -29,5 +29,14 @@ // "'${workspaceRoot}/node_modules/mocha/bin/_mocha -r ts-node/register -r tsconfig-paths/register --file \"${workspaceRoot}/test/firebase-rules/setup.ts\" --recursive \"${workspaceRoot}/test/firebase-rules/**/*.spec.ts\" --no-timeouts --exit'" // ] // }, + { + "name": "Debug current test file", + "type": "node", + "protocol": "inspector", + "request": "launch", + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "stopOnEntry": false, + "args": ["-r", "ts-node/register", "-r", "tsconfig-paths/register", "${workspaceRoot}/${relativeFile}"] + } ] } \ No newline at end of file From c1e54ed22e95c06b332ea61425fed3c6bba008b1 Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Thu, 2 Dec 2021 13:58:19 -0300 Subject: [PATCH 05/10] Adds `Memo` schema tests --- firebase/test/core/data/schemas/memo.spec.ts | 127 +++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 firebase/test/core/data/schemas/memo.spec.ts diff --git a/firebase/test/core/data/schemas/memo.spec.ts b/firebase/test/core/data/schemas/memo.spec.ts new file mode 100644 index 00000000..5cc50b43 --- /dev/null +++ b/firebase/test/core/data/schemas/memo.spec.ts @@ -0,0 +1,127 @@ +import Ajv2020 from "ajv/dist/2020"; +import { SchemaValidator } from "#data/schemas/schema-validator"; +import { doesNotThrow, throws } from "assert"; +import SerializationError from "#faults/errors/serialization-error"; + +describe("Memo Schema Validation", () => { + const validator = new SchemaValidator(new Ajv2020()); + const allowedProperties = ["bold", "italic", "underline", "code-block"]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let rawMemo: any; + + beforeEach(() => { + rawMemo = { + uniqueId: "any", + question: [ + { + insert: "Question string", + }, + ], + answer: [ + { + insert: "Answer string", + }, + ], + }; + }); + + it("should validate raw memo structure", () => { + doesNotThrow(() => validator.validateObject("memo", rawMemo)); + }); + + it("should throw when question id is not present", () => { + delete rawMemo.uniqueId; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + describe("Question - ", () => { + it("should throw when question is not present", () => { + delete rawMemo.question; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should throw when question content is not present", () => { + delete rawMemo.question[0].insert; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should throw when question is empty", () => { + rawMemo.question = []; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should throw when question has incorrect type", () => { + rawMemo.question = true; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + }); + + describe("Answer - ", () => { + it("should throw when answer is not present", () => { + delete rawMemo.answer; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should throw when answer content is not present", () => { + delete rawMemo.answer[0].insert; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should throw when answer is empty", () => { + delete rawMemo.answer; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should throw when answer has incorrect type", () => { + rawMemo.answer = true; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + }); + + describe("Attributes - ", () => { + it("should accept allowed properties", () => { + rawMemo.question[0]!.attributes = {}; + rawMemo.answer[0]!.attributes = {}; + + for (const property of allowedProperties) { + rawMemo.question[0]!.attributes = { ...rawMemo.question[0]!.attributes, [property]: true }; + rawMemo.answer[0]!.attributes = { ...rawMemo.answer[0]!.attributes, [property]: true }; + + doesNotThrow(() => validator.validateObject("memo", rawMemo)); + } + }); + + it("should deny not allowed question attribute", () => { + rawMemo.question[0]!.attributes = { foo: "bar" }; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should deny not allowed answer attribute", () => { + rawMemo.answer[0]!.attributes = { foo: "bar" }; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should deny empty question attributes", () => { + rawMemo.question[0]!.attributes = {}; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + + it("should deny empty answer attributes", () => { + rawMemo.question[0]!.attributes = {}; + + throws(() => validator.validateObject("memo", rawMemo), SerializationError); + }); + }); +}); From 7ff621ab1794679b83bf8ad8753e31521db78a74 Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Fri, 3 Dec 2021 14:01:27 -0300 Subject: [PATCH 06/10] Updates `memo` schema tests adding `rawMemo` builder function --- firebase/test/core/data/schemas/memo.spec.ts | 64 ++++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/firebase/test/core/data/schemas/memo.spec.ts b/firebase/test/core/data/schemas/memo.spec.ts index 5cc50b43..b0d03a5e 100644 --- a/firebase/test/core/data/schemas/memo.spec.ts +++ b/firebase/test/core/data/schemas/memo.spec.ts @@ -6,30 +6,16 @@ import SerializationError from "#faults/errors/serialization-error"; describe("Memo Schema Validation", () => { const validator = new SchemaValidator(new Ajv2020()); const allowedProperties = ["bold", "italic", "underline", "code-block"]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let rawMemo: any; - - beforeEach(() => { - rawMemo = { - uniqueId: "any", - question: [ - { - insert: "Question string", - }, - ], - answer: [ - { - insert: "Answer string", - }, - ], - }; - }); it("should validate raw memo structure", () => { + const rawMemo = _newRawMemo(); + doesNotThrow(() => validator.validateObject("memo", rawMemo)); }); it("should throw when question id is not present", () => { + const rawMemo = _newRawMemo(); + delete rawMemo.uniqueId; throws(() => validator.validateObject("memo", rawMemo), SerializationError); @@ -37,24 +23,32 @@ describe("Memo Schema Validation", () => { describe("Question - ", () => { it("should throw when question is not present", () => { + const rawMemo = _newRawMemo(); + delete rawMemo.question; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should throw when question content is not present", () => { + const rawMemo = _newRawMemo(); + delete rawMemo.question[0].insert; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should throw when question is empty", () => { + const rawMemo = _newRawMemo(); + rawMemo.question = []; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should throw when question has incorrect type", () => { + const rawMemo = _newRawMemo(); + rawMemo.question = true; throws(() => validator.validateObject("memo", rawMemo), SerializationError); @@ -63,24 +57,32 @@ describe("Memo Schema Validation", () => { describe("Answer - ", () => { it("should throw when answer is not present", () => { + const rawMemo = _newRawMemo(); + delete rawMemo.answer; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should throw when answer content is not present", () => { + const rawMemo = _newRawMemo(); + delete rawMemo.answer[0].insert; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should throw when answer is empty", () => { + const rawMemo = _newRawMemo(); + delete rawMemo.answer; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should throw when answer has incorrect type", () => { + const rawMemo = _newRawMemo(); + rawMemo.answer = true; throws(() => validator.validateObject("memo", rawMemo), SerializationError); @@ -89,6 +91,7 @@ describe("Memo Schema Validation", () => { describe("Attributes - ", () => { it("should accept allowed properties", () => { + const rawMemo = _newRawMemo(); rawMemo.question[0]!.attributes = {}; rawMemo.answer[0]!.attributes = {}; @@ -101,27 +104,52 @@ describe("Memo Schema Validation", () => { }); it("should deny not allowed question attribute", () => { + const rawMemo = _newRawMemo(); + rawMemo.question[0]!.attributes = { foo: "bar" }; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should deny not allowed answer attribute", () => { + const rawMemo = _newRawMemo(); + rawMemo.answer[0]!.attributes = { foo: "bar" }; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should deny empty question attributes", () => { + const rawMemo = _newRawMemo(); + rawMemo.question[0]!.attributes = {}; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); it("should deny empty answer attributes", () => { + const rawMemo = _newRawMemo(); + rawMemo.question[0]!.attributes = {}; throws(() => validator.validateObject("memo", rawMemo), SerializationError); }); }); }); + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function _newRawMemo(): any { + return { + id: "any", + question: [ + { + insert: "Question string", + }, + ], + answer: [ + { + insert: "Answer string", + }, + ], + }; +} From ed6b905f67473684454783365ded498548b20ebb Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Fri, 3 Dec 2021 14:01:38 -0300 Subject: [PATCH 07/10] Rename debug test launch name --- firebase/.vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebase/.vscode/launch.json b/firebase/.vscode/launch.json index bedf92e8..2fff6bda 100644 --- a/firebase/.vscode/launch.json +++ b/firebase/.vscode/launch.json @@ -30,7 +30,7 @@ // ] // }, { - "name": "Debug current test file", + "name": "Debug test in window", "type": "node", "protocol": "inspector", "request": "launch", From 177582ef01f7add18249d15a8c881d59abaa9237 Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Fri, 3 Dec 2021 14:02:55 -0300 Subject: [PATCH 08/10] Renames `uniqueId` back to `id` --- firebase/src/core/domain/models/memo.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firebase/src/core/domain/models/memo.ts b/firebase/src/core/domain/models/memo.ts index 1b166f05..c064380c 100644 --- a/firebase/src/core/domain/models/memo.ts +++ b/firebase/src/core/domain/models/memo.ts @@ -12,7 +12,7 @@ interface MemoContent { } export interface Memo { - readonly uniqueId: string; + readonly id: string; readonly question: MemoContent[]; readonly answer: MemoContent[]; } @@ -28,7 +28,7 @@ const memoContentValidationSchema = Joi.object({ }); export const memoValidationSchema = Joi.object({ - uniqueId: Joi.string().max(defaultMaxStringLength).required(), + id: Joi.string().max(defaultMaxStringLength).required(), question: Joi.array().items(memoContentValidationSchema).min(1).required(), answer: Joi.array().items(memoContentValidationSchema).min(1).required(), }); From 6988b81ae144621f1ea0541ba3a769ae3b8530fb Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Fri, 3 Dec 2021 16:35:43 -0300 Subject: [PATCH 09/10] Renames missing `uniqueId` instance --- firebase/src/core/data/schemas/entities-schemas/memo.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firebase/src/core/data/schemas/entities-schemas/memo.json b/firebase/src/core/data/schemas/entities-schemas/memo.json index bee47233..dcccec67 100644 --- a/firebase/src/core/data/schemas/entities-schemas/memo.json +++ b/firebase/src/core/data/schemas/entities-schemas/memo.json @@ -5,7 +5,7 @@ "description": "Properties of a Memo.", "type": "object", "properties": { - "uniqueId": { "type": "string" }, + "id": { "type": "string" }, "question": { "type": "array", "items": { @@ -52,7 +52,7 @@ } }, "required": [ - "uniqueId", + "id", "question", "answer" ] From b77170d4c6dcfc6528ef8ab86a12cba31688f864 Mon Sep 17 00:00:00 2001 From: Guilherme Girotto Date: Fri, 3 Dec 2021 16:37:18 -0300 Subject: [PATCH 10/10] Renames `Memo` quill validation schema --- firebase/src/core/domain/models/memo.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firebase/src/core/domain/models/memo.ts b/firebase/src/core/domain/models/memo.ts index c064380c..b380b0f3 100644 --- a/firebase/src/core/domain/models/memo.ts +++ b/firebase/src/core/domain/models/memo.ts @@ -17,7 +17,7 @@ export interface Memo { readonly answer: MemoContent[]; } -const memoContentValidationSchema = Joi.object({ +const memoQuillValidationSchema = Joi.object({ insert: Joi.string().max(defaultMaxStringLength).required(), attributes: Joi.object({ bold: Joi.boolean(), @@ -29,8 +29,8 @@ const memoContentValidationSchema = Joi.object({ export const memoValidationSchema = Joi.object({ id: Joi.string().max(defaultMaxStringLength).required(), - question: Joi.array().items(memoContentValidationSchema).min(1).required(), - answer: Joi.array().items(memoContentValidationSchema).min(1).required(), + question: Joi.array().items(memoQuillValidationSchema).min(1).required(), + answer: Joi.array().items(memoQuillValidationSchema).min(1).required(), }); export function validateMemo(memo: Memo): void {