From 7ddfac1ece6123b39273f09b47f0dea0298d23c8 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Fri, 14 Oct 2022 21:51:59 +0530 Subject: [PATCH] feat: bruno schema definition for workspace --- docs/development.md | 14 ++++ package.json | 9 ++- packages/bruno-schema/package.json | 10 +++ packages/bruno-schema/src/common/index.js | 9 +++ packages/bruno-schema/src/index.js | 5 ++ packages/bruno-schema/src/utils/testUtils.js | 22 ++++++ packages/bruno-schema/src/workspaces/index.js | 15 ++++ .../bruno-schema/src/workspaces/index.spec.js | 72 +++++++++++++++++++ 8 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 packages/bruno-schema/package.json create mode 100644 packages/bruno-schema/src/common/index.js create mode 100644 packages/bruno-schema/src/index.js create mode 100644 packages/bruno-schema/src/utils/testUtils.js create mode 100644 packages/bruno-schema/src/workspaces/index.js create mode 100644 packages/bruno-schema/src/workspaces/index.spec.js diff --git a/docs/development.md b/docs/development.md index 7cee5677..bec8cf58 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1 +1,15 @@ ## development +```bash +# install deps +npm i + +# run next app +npm run dev --workspace=packages/bruno-app +``` + +# testing +```bash +# bruno-schema +npm test --workspace=packages/bruno-schema + +``` \ No newline at end of file diff --git a/package.json b/package.json index 78039b6d..44499a93 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,15 @@ { - "name": "bruno-workspace", + "name": "usebruno", "private": true, "workspaces": [ "packages/bruno-app", "packages/bruno-electron", "packages/bruno-tauri", + "packages/bruno-schema", "packages/bruno-testbench" - ] + ], + "devDependencies": { + "jest": "^29.2.0", + "randomstring": "^1.2.2" + } } diff --git a/packages/bruno-schema/package.json b/packages/bruno-schema/package.json new file mode 100644 index 00000000..5b8a451c --- /dev/null +++ b/packages/bruno-schema/package.json @@ -0,0 +1,10 @@ +{ + "name": "@usebruno/schema", + "main": "src/index.js", + "scripts": { + "test": "jest" + }, + "peerDependencies": { + "yup": "^0.32.11" + } +} diff --git a/packages/bruno-schema/src/common/index.js b/packages/bruno-schema/src/common/index.js new file mode 100644 index 00000000..12d6ee11 --- /dev/null +++ b/packages/bruno-schema/src/common/index.js @@ -0,0 +1,9 @@ +const Yup = require('yup'); + +const uidSchema = Yup.string() + .length(21, 'uid must be 21 characters in length') + .matches(/^[a-zA-Z0-9]*$/, 'uid must be alphanumeric'); + +module.exports = { + uidSchema +}; \ No newline at end of file diff --git a/packages/bruno-schema/src/index.js b/packages/bruno-schema/src/index.js new file mode 100644 index 00000000..a0d11a26 --- /dev/null +++ b/packages/bruno-schema/src/index.js @@ -0,0 +1,5 @@ +const { workspaceSchema} = require("./workspaces"); + +module.exports = { + workspaceSchema +}; \ No newline at end of file diff --git a/packages/bruno-schema/src/utils/testUtils.js b/packages/bruno-schema/src/utils/testUtils.js new file mode 100644 index 00000000..f4b514f4 --- /dev/null +++ b/packages/bruno-schema/src/utils/testUtils.js @@ -0,0 +1,22 @@ +const { customAlphabet } = require('nanoid'); +const { expect } = require('@jest/globals'); + +// a customized version of nanoid without using _ and - +const uuid = () => { + // https://github.com/ai/nanoid/blob/main/url-alphabet/index.js + const urlAlphabet = 'useandom26T198340PX75pxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrict'; + const customNanoId = customAlphabet (urlAlphabet, 21); + + return customNanoId(); +}; + +const validationErrorWithMessages = (...errors) => { + return expect.objectContaining({ + errors + }); +} + +module.exports = { + uuid, + validationErrorWithMessages +}; diff --git a/packages/bruno-schema/src/workspaces/index.js b/packages/bruno-schema/src/workspaces/index.js new file mode 100644 index 00000000..6e141ef6 --- /dev/null +++ b/packages/bruno-schema/src/workspaces/index.js @@ -0,0 +1,15 @@ +const Yup = require('yup'); +const { uidSchema } = require("../common"); + +const workspaceSchema = Yup.object({ + uid: uidSchema, + name: Yup.string() + .min(1, 'name must be atleast 1 characters') + .max(50, 'name must be 50 characters or less') + .required('name is required'), + collectionUids: Yup.array().of(uidSchema) +}); + +module.exports = { + workspaceSchema +}; \ No newline at end of file diff --git a/packages/bruno-schema/src/workspaces/index.spec.js b/packages/bruno-schema/src/workspaces/index.spec.js new file mode 100644 index 00000000..d3cec174 --- /dev/null +++ b/packages/bruno-schema/src/workspaces/index.spec.js @@ -0,0 +1,72 @@ +const { expect } = require('@jest/globals'); +const { uuid, validationErrorWithMessages } = require("../utils/testUtils"); +const randomstring = require("randomstring"); +const { workspaceSchema } = require("./index"); + +describe('Workspace Schema Validation', () => { + it('workspace schema must validate successfully', async () => { + const workspace = { + uid: uuid(), + name: 'My workspace' + }; + + const isValid = await workspaceSchema.validate(workspace); + expect(isValid).toBeTruthy(); + }); + + it('workspace schema must throw error upon invalid uuid length', async () => { + const workspace = { + uid: uuid() + 'junk', + name: 'My workspace' + }; + + return Promise.all([ + expect(workspaceSchema.validate(workspace)).rejects.toEqual( + validationErrorWithMessages('uid must be 21 characters in length') + ) + ]); + }); + + it('workspace schema must throw error upon invalid uuid character', async () => { + const workspace = { + uid: uuid(), + name: 'My workspace' + }; + + workspace.uid = '$' + workspace.uid.substring(1, workspace.uid.length); + + return Promise.all([ + expect(workspaceSchema.validate(workspace)).rejects.toEqual( + validationErrorWithMessages('uid must be alphanumeric') + ) + ]); + }); + + it('workspace schema must throw error when name is empty', async () => { + const workspace = { + uid: uuid() + }; + + return Promise.all([ + expect(workspaceSchema.validate(workspace)).rejects.toEqual( + validationErrorWithMessages('name is required') + ) + ]); + }); + + it('workspace schema must throw error when name has more than 50 characters', async () => { + const workspace = { + uid: uuid(), + name: randomstring.generate({ + length: 51, + charset: 'alphabetic' + }) + }; + + return Promise.all([ + expect(workspaceSchema.validate(workspace)).rejects.toEqual( + validationErrorWithMessages('name must be 50 characters or less') + ) + ]); + }); +});