diff --git a/cypress.json b/cypress.json index a2fe63de9b..245acfe53c 100644 --- a/cypress.json +++ b/cypress.json @@ -1,10 +1,11 @@ { - "baseUrl": "http://localhost:3000", + "baseUrl": "http://localhost:3000/", "defaultCommandTimeout": 13000, "pageLoadTimeout": 600000, "viewportWidth": 1980, "viewportHeight": 1000, "video": false, "retries": 2, - "screenshotOnRunFailure": false + "screenshotOnRunFailure": false, + "numTestsKeptInMemory": 5 } diff --git a/cypress/integration/common/_pre_configurations.js b/cypress/integration/common/_pre_configurations.js new file mode 100644 index 0000000000..b7f00210cb --- /dev/null +++ b/cypress/integration/common/_pre_configurations.js @@ -0,0 +1,93 @@ + +// Cypress test suite: project pre-configurations +// + +import { loginPage, projectsPage } from "../../support/page_objects/navigation" +import { mainPage } from "../../support/page_objects/mainpage" +import { staticProjects, roles } from "../../support/page_objects/projectConstants" + +describe(`Project pre-configurations`, () => { + + it('Admin SignUp', ()=> { + cy.waitForSpinners(); + cy.signinOrSignup(roles.owner.credentials) + cy.wait(2000) + }) + + const createProject = (proj) => { + it(`Create ${proj.basic.name} project`, () => { + + // click home button + mainPage.toolBarTopLeft(mainPage.HOME).click() + // create requested project + projectsPage.createProject( proj.basic, proj.config ) + }) + } + + createProject(staticProjects.sampleREST) + createProject(staticProjects.sampleGQL) + createProject(staticProjects.externalREST) + createProject(staticProjects.externalGQL) +}) + +describe('Static user creations (different roles)', () => { + + beforeEach(()=> { + loginPage.signIn(roles.owner.credentials) + projectsPage.openProject(staticProjects.sampleREST.basic.name) + }) + + const addUser = (user) => { + it(`RoleType: ${user.name}`, () => { + mainPage.addNewUserToProject(user.credentials, user.name) + }) + } + + addUser(roles.creator) + addUser(roles.editor) + addUser(roles.commenter) + addUser(roles.viewer) +}) + +describe('Static users- add to other static projects', () => { + + const addUserToProject = (proj) => { + it(`Add users to ${proj.basic.name}`, () => { + loginPage.signIn(roles.owner.credentials) + projectsPage.openProject(proj.basic.name) + + mainPage.addExistingUserToProject(roles.creator.credentials.username, roles.creator.name) + mainPage.addExistingUserToProject(roles.editor.credentials.username, roles.editor.name) + mainPage.addExistingUserToProject(roles.commenter.credentials.username, roles.commenter.name) + mainPage.addExistingUserToProject(roles.viewer.credentials.username, roles.viewer.name) + }) + } + + addUserToProject(staticProjects.sampleGQL) + addUserToProject(staticProjects.externalREST) + addUserToProject(staticProjects.externalGQL) +}) + + + +/** + * @copyright Copyright (c) 2021, Xgene Cloud Ltd + * + * @author Raju Udava + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ \ No newline at end of file diff --git a/cypress/integration/user_role_spec.js b/cypress/integration/user_role_spec.js index 44273bb675..e024c0e365 100644 --- a/cypress/integration/user_role_spec.js +++ b/cypress/integration/user_role_spec.js @@ -38,63 +38,6 @@ const roles = { } -// add new user to specified role -// -const addUser = (userCred, role) => { - - let linkText - - // click on New User button, feed details - cy.get('button:contains("New User")').first().click() - cy.get('label:contains(Email)').next('input').type(userCred.username).trigger('input') - cy.get('label:contains(Select User roles)').click() - - // opt-in requested role & submit - // note that, 'editor' is set by default - // - cy.getActiveMenu().contains(role).click() - cy.getActiveMenu().contains('editor').click() - cy.get('.mdi-menu-down').click() - cy.get('.nc-invite-or-save-btn').click() - - // get URL, invoke - cy.getActiveModal().find('.v-alert').then(($obj) => { - linkText = $obj.text() - cy.log(linkText) - - cy.visit(linkText) - }) - - // SignUp is taken care under userRoleCreation() - // wait for some time to ensure screen is loaded - // - cy.wait(2000) -} - - -const userRoleCreation = (roleType) => { - it(`User creation: ${roleType}`, () => { - - loginPage.signIn(roles.owner.credentials) - projectsPage.openProject('sakilaDb') - - // Team & Auth tab is open by default - // - addUser(roles[roleType].credentials, roleType) - - // Redirected to new URL, feed details - // - cy.get('input[type="text"]').type(roles[roleType].credentials.username) - cy.get('input[type="password"]').type(roles[roleType].credentials.password) - cy.get('button:contains("SIGN UP")').click() - - cy.url({ timeout: 6000 }).should('contain', '#/project') - cy.wait(1000) - - projectsPage.openProject('sakilaDb') - }) -} - describe('Test project creation, user creation', () => { let projectName = '' diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 9eae51efa1..96814986a8 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -37,7 +37,10 @@ Cypress.Commands.add('waitForSpinners', () => { }) cy.get('#nuxt-loading', {timeout: 10_0000}).should('have.length', 0) }) -Cypress.Commands.add('signinOrSignup', () => { + + +Cypress.Commands.add('signinOrSignup', (_args) => { + const args = Object.assign({username: 'user@nocodb.com', password: 'Password123.'}, _args) // signin/signup cy.get('body').then(($body) => { @@ -49,21 +52,21 @@ Cypress.Commands.add('signinOrSignup', () => { cy.wait(8000); cy.get('body').trigger('mousemove'); cy.contains('Let\'s Begin').click(); - cy.get('input[type="text"]', {timeout: 12000}).type('user@nocodb.com'); - cy.get('input[type="password"]').type('Password123.'); + cy.get('input[type="text"]', { timeout: 12000 }).type(args.username); + cy.get('input[type="password"]').type(args.password); cy.get('button:contains("SIGN UP")').click() // handle signin } else { - cy.get('input[type="text"]').type('user@nocodb.com'); - cy.get('input[type="password"]').type('Password123.'); + cy.get('input[type="text"]', { timeout: 12000 }).type(args.username); + cy.get('input[type="password"]').type(args.password); cy.get('button:contains("SIGN IN")').click() } } - }) }) }); + // for opening/creating a rest project Cypress.Commands.add('openOrCreateRestProject', (_args) => { const args = Object.assign({new: false}, _args) diff --git a/cypress/support/page_objects/mainPage.js b/cypress/support/page_objects/mainPage.js index 394e717b6b..94c3797374 100644 --- a/cypress/support/page_objects/mainPage.js +++ b/cypress/support/page_objects/mainPage.js @@ -26,18 +26,11 @@ export class _mainPage { } toolBarTopLeft(toolBarItem) { - - cy.get('header.v-toolbar').eq(0).find('a').then((obj) => { - cy.wrap(obj).eq(toolBarItem).click() - }) + return cy.get('header.v-toolbar').eq(0).find('a').eq(toolBarItem) } toolBarTopRight(toolBarItem) { - - cy.get('header.v-toolbar').eq(0).find('button').then((obj) => { - cy.wrap(obj).eq(toolBarItem).click() - cy.wait(500) - }) + return cy.get('header.v-toolbar').eq(0).find('button').eq(toolBarItem) } @@ -47,6 +40,64 @@ export class _mainPage { else return cy.get('.nc-nav-drawer').find('.v-list > .v-list-item').eq(item) } + + + // add new user to specified role + // + addNewUserToProject = (userCred, roleType) => { + + let linkText + + // click on New User button, feed details + cy.get('button:contains("New User")').first().click() + cy.get('label:contains("Email")').next('input').type(userCred.username).trigger('input') + cy.get('label:contains("Select User roles")').click() + + // opt-in requested role & submit + // note that, 'editor' is set by default + // + cy.getActiveMenu().contains(roleType).click() + cy.getActiveMenu().contains('editor').click() + cy.get('.mdi-menu-down').click() + cy.get('.nc-invite-or-save-btn').click() + + // get URL, invoke + cy.getActiveModal().find('.v-alert').then(($obj) => { + linkText = $obj.text() + cy.log(linkText) + + cy.visit(linkText) + + cy.wait(3000) + + // Redirected to new URL, feed details + // + cy.get('input[type="text"]').type(userCred.username) + cy.get('input[type="password"]').type(userCred.password) + cy.get('button:contains("SIGN UP")').click() + + cy.url({ timeout: 6000 }).should('contain', '#/project') + cy.wait(1000) + }) + } + + addExistingUserToProject = (emailId, role) => { + + cy.get('.v-list-item:contains("Team & Auth")').click() + cy.get(`tr:contains(${emailId})`).find('.mdi-plus', {timeout: 2000}).click() + cy.get(`tr:contains(${emailId})`).find('.mdi-pencil-outline', {timeout: 2000}).click() + + cy.get('label:contains(Select User roles)').click() + + // opt-in requested role & submit + // note that, 'editor' is set by default + // + cy.getActiveMenu().contains(role).click() + cy.getActiveMenu().contains('editor').click() + cy.get('.mdi-menu-down').click() + cy.get('.nc-invite-or-save-btn').click() + cy.wait(1000) + } } diff --git a/cypress/support/page_objects/navigation.js b/cypress/support/page_objects/navigation.js index a05d7f8a91..35a69115b4 100644 --- a/cypress/support/page_objects/navigation.js +++ b/cypress/support/page_objects/navigation.js @@ -57,15 +57,6 @@ export class _loginPage { /////////////////////////////////////////////////////////// // Projects page -// DB type -const NC_DB_NONE = 0 -const NC_DB_EXISTING = 1 - -// API type -const NC_REST = 0 -const NC_GQL = 1 - - export class _projectsPage { // Project creation options @@ -106,7 +97,7 @@ export class _projectsPage { // click on "New Project" cy.get(':nth-child(5) > .v-btn').click() - if (NC_DB_NONE == projectData.dbType) { + if ('none' == projectData.dbType) { // Subsequent form, select (+ Create) option cy.get('.nc-create-xc-db-project').click({ force: true }) @@ -115,7 +106,7 @@ export class _projectsPage { cy.get('.nc-metadb-project-name').type(projectName) // Radio button: defaults to NC_REST - if (NC_GQL == projectData.apiType) { + if ('GQL' == projectData.apiType) { cy.contains('GRAPHQL APIs').closest('label').click(); } @@ -127,6 +118,8 @@ export class _projectsPage { return projectName } + + // dbType == 'external' else { // Subsequent form, select (+ Create by connection to external database) option @@ -137,7 +130,7 @@ export class _projectsPage { cy.contains('Enter Project Name').parent().find('input').clear().type(projectName) // Radio button: defaults to NC_REST - if (NC_GQL == projectData.apiType) { + if ('GQL' == projectData.apiType) { cy.contains('GRAPHQL APIs').closest('label').click(); } diff --git a/cypress/support/page_objects/projectConstants.js b/cypress/support/page_objects/projectConstants.js index 24d5cabc48..0827ebaf87 100644 --- a/cypress/support/page_objects/projectConstants.js +++ b/cypress/support/page_objects/projectConstants.js @@ -1,9 +1,65 @@ export const defaultDbParams = { - databaseType: 0, + databaseType: 0, // MySQL hostAddress: 'localhost', portNumber: '3306', username: 'root', password: 'password', databaseName: 'sakila' +} + +// database +// validation details +// advSettings: left navigation bar (audit, metadata, auth, transient view modes) +// editSchema: create table, add/update/delete column +// editData: add/ update/ delete row, cell contents +// editComment: add comment +// shareView: right navigation bar (share options) +export const roles = { + owner: { + name: 'owner', + credentials: { username: 'user@nocodb.com', password: 'Password123.' }, + validations: { advSettings: true, editSchema: true, editData: true, editComment: true, shareView: true } + }, + creator: { + name: 'creator', + credentials: { username: 'creator@nocodb.com', password: 'Password123.' }, + validations: { advSettings: true, editSchema: true, editData: true, editComment: true, shareView: true } + }, + editor: { + name: 'editor', + credentials: { username: 'editor@nocodb.com', password: 'Password123.' }, + validations: { advSettings: false, editSchema: false, editData: true, editComment: true, shareView: false } + }, + commenter: { + name: 'commenter', + credentials: { username: 'commenter@nocodb.com', password: 'Password123.' }, + validations: { advSettings: false, editSchema: false, editData: false, editComment: true, shareView: false } + }, + viewer: { + name: 'viewer', + credentials: { username: 'viewer@nocodb.com', password: 'Password123.' }, + validations: { advSettings: false, editSchema: false, editData: false, editComment: false, shareView: false } + } +} + +// default projects +// +export const staticProjects = { + sampleREST: { + basic: { dbType: 'none', apiType: 'REST', name: 'sampleREST' }, + config: {} + }, + sampleGQL: { + basic: { dbType: 'none', apiType: 'GQL', name: 'sampleGQL' }, + config: {} + }, + externalREST: { + basic: { dbType: 'external', apiType: 'REST', name: 'externalREST' }, + config: defaultDbParams + }, + externalGQL: { + basic: { dbType: 'external', apiType: 'GQL', name: 'externalGQL' }, + config: defaultDbParams + } } \ No newline at end of file