From 76a170b50b57f3824ca4c5df33c9acc551cd92a3 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 14 Jul 2021 09:37:49 +1000 Subject: [PATCH] Added a simple UI cypress test, improvements to ui menu --- frontend/package.json | 10 +-- frontend/src/components/NavMenu.tsx | 60 +++++++++++++++ frontend/src/components/SiteWrapper.tsx | 53 +------------ frontend/yarn.lock | 19 ++--- .../integration/api/SetupPhase.spec.js | 10 +-- .../cypress/integration/ui/SetupLogin.spec.js | 20 +++++ test/cypress/support/commands.js | 74 +++++++++++++------ 7 files changed, 151 insertions(+), 95 deletions(-) create mode 100644 frontend/src/components/NavMenu.tsx create mode 100644 test/cypress/integration/ui/SetupLogin.spec.js diff --git a/frontend/package.json b/frontend/package.json index 826f11b4..c549c7fd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -47,7 +47,7 @@ "styled-components": "5.3.0", "tabler-icons-react": "^1.35.0", "tabler-react": "^2.0.0-alpha.1", - "tabler-react-typescript": "^0.0.4", + "tabler-react-typescript": "0.0.5", "typescript": "^4.3.5" }, "scripts": { @@ -83,10 +83,10 @@ ], "coverageThreshold": { "global": { - "branches": 1, - "functions": 1, - "lines": 1, - "statements": 1 + "branches": 0, + "functions": 0, + "lines": 0, + "statements": 0 } } } diff --git a/frontend/src/components/NavMenu.tsx b/frontend/src/components/NavMenu.tsx new file mode 100644 index 00000000..b8889072 --- /dev/null +++ b/frontend/src/components/NavMenu.tsx @@ -0,0 +1,60 @@ +import React from "react"; + +import { + Book, + DeviceDesktop, + Home, + Lock, + Settings, + Shield, + Users, +} from "tabler-icons-react"; +import { Navigation } from "tabler-react-typescript"; + +function NavMenu() { + return ( + , + to: "/", + }, + { + title: "Hosts", + icon: , + to: "/hosts", + }, + { + title: "Access Lists", + icon: , + to: "/access-lists", + }, + { + title: "Certificates", + icon: , + to: "/certificates", + }, + { + title: "Users", + icon: , + to: "/users", + }, + { + title: "Audit Log", + icon: , + to: "/audit-log", + }, + { + title: "Settings", + icon: , + to: "/settings", + }, + ]} + /> + ); +} + +export { NavMenu }; diff --git a/frontend/src/components/SiteWrapper.tsx b/frontend/src/components/SiteWrapper.tsx index 2ed10229..6f9c5a4c 100644 --- a/frontend/src/components/SiteWrapper.tsx +++ b/frontend/src/components/SiteWrapper.tsx @@ -3,17 +3,10 @@ import React, { ReactNode } from "react"; import { Footer } from "components"; import { useAuthState, useUserState } from "context"; import styled from "styled-components"; -import { - Book, - DeviceDesktop, - Home, - Lock, - Settings, - Shield, - Users, -} from "tabler-icons-react"; import { Avatar, Dropdown, Navigation } from "tabler-react-typescript"; +import { NavMenu } from "./NavMenu"; + const StyledContainer = styled.div` padding-bottom: 30px; `; @@ -45,52 +38,14 @@ function SiteWrapper({ children }: Props) { user.roles.includes("admin") ? "Administrator" : "Standard User" } profileItems={[ - Set status, - Profile & account, - Feedback, + Profile settings, , - Settings, Logout , ]} /> - , - active: true, - }, - { - title: "Hosts", - icon: , - }, - { - title: "Access Lists", - icon: , - }, - { - title: "Certificates", - icon: , - }, - { - title: "Users", - icon: , - }, - { - title: "Audit Log", - icon: , - }, - { - title: "Settings", - icon: , - }, - ]} - /> - +
{children} diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 67cc88a6..00c25f43 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1829,13 +1829,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/classnames@^2.2.11": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.3.1.tgz#3c2467aa0f1a93f1f021e3b9bcf938bd5dfdc0dd" - integrity sha512-zeOWb0JGBoVmlQoznvqXbE0tEC/HONsnoUNH19Hc96NFsTAwTXbTqb8FMYkru1F/iqp7a18Ws3nWJvtA1sHD1A== - dependencies: - classnames "*" - "@types/eslint@^7.2.6": version "7.2.6" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.6.tgz#5e9aff555a975596c03a98b59ecd103decc70c3c" @@ -3646,7 +3639,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@*, classnames@^2.2.6: +classnames@^2.2.6: version "2.3.1" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== @@ -11784,13 +11777,13 @@ tabler-icons-react@^1.35.0: resolved "https://registry.yarnpkg.com/tabler-icons-react/-/tabler-icons-react-1.35.0.tgz#b4e7f8da632314d002aa5e34931f2f824395b77c" integrity sha512-WiJ+dYQ71HCsxKAQpCfPrFVwSfqE6CByYFjq9Gzikmp2RijJBsNpj0sE/T5G0H+nERS9odjAWJoSryvr4FymFg== -tabler-react-typescript@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/tabler-react-typescript/-/tabler-react-typescript-0.0.4.tgz#b40ee7faef743f5d5af6cdf098d3376cdb71989e" - integrity sha512-l/OoB4zQ3+u4xVxARw+1HqaHO13wDYlQIvjFyvs6Sdk7Vdys0sAc/EzN9hxWg5ywRNM+mGwt5+fVHXiuYAcD7g== +tabler-react-typescript@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/tabler-react-typescript/-/tabler-react-typescript-0.0.5.tgz#ab14ebada6f0524e13e3c6e60d2739a0f34f617d" + integrity sha512-PIov0LMSZWQzQ0OnlyITTzVdgBOKuc6HzgNLttP6Uz3/evGDBFl/Owl7wcP6niy7varzx4SttzFNXfJyhC3zcg== dependencies: - "@types/classnames" "^2.2.11" classnames "^2.2.6" + react-router-dom "^5.2.0" tabler-react@^2.0.0-alpha.1: version "2.0.0-alpha.1" diff --git a/test/cypress/integration/api/SetupPhase.spec.js b/test/cypress/integration/api/SetupPhase.spec.js index 71189ffc..9c9f3dca 100644 --- a/test/cypress/integration/api/SetupPhase.spec.js +++ b/test/cypress/integration/api/SetupPhase.spec.js @@ -3,19 +3,15 @@ describe('Setup Phase', () => { before(() => { - cy.task('backendApiDelete', { - path: '/api/users' - }).then((data) => { - expect(data).to.have.property('result', true); - }); + cy.resetUsers(); }); - it('Should not be able to get a token', function() { + it('Should NOT be able to get a token', function() { cy.task('backendApiPost', { path: '/api/tokens', data: { type: 'password', - identity: 'jc@jc21.com', + identity: 'cypress@example.com', secret: 'changeme' }, returnOnError: true diff --git a/test/cypress/integration/ui/SetupLogin.spec.js b/test/cypress/integration/ui/SetupLogin.spec.js new file mode 100644 index 00000000..42eec942 --- /dev/null +++ b/test/cypress/integration/ui/SetupLogin.spec.js @@ -0,0 +1,20 @@ +/// + +describe('UI Setup and Login', () => { + + // Clear the users before runing this test + before(() => { + cy.resetUsers(); + }); + + it('Should be able to setup a new user', function() { + cy.visit('/'); + cy.get('input[name="name"]').type('Cypress McGee'); + cy.get('input[name="nickname"]').type('Cypress'); + cy.get('input[name="email"]').type('cypress@example.com'); + cy.get('input[name="password"]').type('changeme'); + cy.get('form button:first').click(); + cy.get('.navbar-nav .avatar').should('be.visible'); + }); + +}); diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js index b4395358..2884ccab 100644 --- a/test/cypress/support/commands.js +++ b/test/cypress/support/commands.js @@ -28,7 +28,18 @@ Cypress.Commands.add('validateSwaggerSchema', (method, code, path, data) => { }).should('equal', null); }); -Cypress.Commands.add('getToken', () => { +/** + * @param {object} defaultUser + * @param {object} defaultAuth +*/ +Cypress.Commands.add('getToken', (defaultUser, defaultAuth) => { + if (typeof defaultAuth === 'object' && defaultAuth) { + if (!defaultUser) { + defaultUser = {}; + } + defaultUser.auth = defaultAuth; + } + cy.task('backendApiGet', { path: '/api/', }).then((data) => { @@ -38,40 +49,52 @@ Cypress.Commands.add('getToken', () => { if (!data.result.setup) { cy.log('Setup = false'); // create a new user - cy.createInitialUser().then(() => { - return cy.getToken(); + cy.createInitialUser(defaultUser).then(() => { + return cy.getToken(defaultUser); }); } else { + let auth = { + type: 'password', + identity: 'cypress@example.com', + secret: 'changeme', + }; + + if (typeof defaultUser === 'object' && defaultUser && typeof defaultUser.auth === 'object' && defaultUser.auth) { + auth = Object.assign({}, auth, defaultUser.auth); + } + cy.log('Setup = true'); // login with existing user cy.task('backendApiPost', { path: '/api/tokens', - data: { - type: 'password', - identity: 'jc@jc21.com', - secret: 'changeme' - } - }).then(res => { + data: auth, + }).then((res) => { cy.wrap(res.result.token); }); } }); }); -Cypress.Commands.add('createInitialUser', () => { +Cypress.Commands.add('createInitialUser', (defaultUser) => { + let user = { + name: 'Cypress McGee', + nickname: 'Cypress', + email: 'cypress@example.com', + roles: [], + is_disabled: false, + auth: { + type: 'password', + secret: 'changeme' + } + }; + + if (typeof defaultUser === 'object' && defaultUser) { + user = Object.assign({}, user, defaultUser); + } + return cy.task('backendApiPost', { path: '/api/users', - data: { - name: 'Jamie Curnow', - nickname: 'James', - email: 'jc@jc21.com', - roles: [], - is_disabled: false, - auth: { - type: 'password', - secret: 'changeme' - } - } + data: user, }).then((data) => { // Check the swagger schema: cy.validateSwaggerSchema('post', 201, '/users', data); @@ -80,3 +103,12 @@ Cypress.Commands.add('createInitialUser', () => { cy.wrap(data.result); }); }); + +Cypress.Commands.add('resetUsers', () => { + cy.task('backendApiDelete', { + path: '/api/users' + }).then((data) => { + expect(data).to.have.property('result', true); + cy.wrap(data.result); + }); +});