diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/pybind/mgr/dashboard/frontend/cypress/integration/ui | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/pybind/mgr/dashboard/frontend/cypress/integration/ui')
16 files changed, 599 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/api-docs.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/api-docs.e2e-spec.ts new file mode 100644 index 000000000..52994859e --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/api-docs.e2e-spec.ts @@ -0,0 +1,15 @@ +import { ApiDocsPageHelper } from '../ui/api-docs.po'; + +describe('Api Docs Page', () => { + const apiDocs = new ApiDocsPageHelper(); + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + apiDocs.navigateTo(); + }); + + it('should show the API Docs description', () => { + cy.get('.renderedMarkdown').first().contains('This is the official Ceph REST API'); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/api-docs.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/api-docs.po.ts new file mode 100644 index 000000000..c7a8d222d --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/api-docs.po.ts @@ -0,0 +1,5 @@ +import { PageHelper } from '../page-helper.po'; + +export class ApiDocsPageHelper extends PageHelper { + pages = { index: { url: '#/api-docs', id: 'cd-api-docs' } }; +} diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/dashboard.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/dashboard.e2e-spec.ts new file mode 100644 index 000000000..9cb84480b --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/dashboard.e2e-spec.ts @@ -0,0 +1,124 @@ +import { IscsiPageHelper } from '../block/iscsi.po'; +import { HostsPageHelper } from '../cluster/hosts.po'; +import { MonitorsPageHelper } from '../cluster/monitors.po'; +import { OSDsPageHelper } from '../cluster/osds.po'; +import { PageHelper } from '../page-helper.po'; +import { PoolPageHelper } from '../pools/pools.po'; +import { DaemonsPageHelper } from '../rgw/daemons.po'; +import { DashboardPageHelper } from './dashboard.po'; + +describe('Dashboard Main Page', () => { + const dashboard = new DashboardPageHelper(); + const daemons = new DaemonsPageHelper(); + const hosts = new HostsPageHelper(); + const osds = new OSDsPageHelper(); + const pools = new PoolPageHelper(); + const monitors = new MonitorsPageHelper(); + const iscsi = new IscsiPageHelper(); + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + dashboard.navigateTo(); + }); + + describe('Check that all hyperlinks on info cards lead to the correct page and fields exist', () => { + it('should ensure that all linked info cards lead to correct page', () => { + const expectationMap = { + Monitors: 'Monitors', + OSDs: 'OSDs', + Hosts: 'Hosts', + 'Object Gateways': 'Daemons', + 'iSCSI Gateways': 'Overview', + Pools: 'Pools' + }; + + for (const [linkText, breadcrumbText] of Object.entries(expectationMap)) { + cy.location('hash').should('eq', '#/dashboard'); + dashboard.clickInfoCardLink(linkText); + dashboard.expectBreadcrumbText(breadcrumbText); + dashboard.navigateBack(); + } + }); + + it('should verify that info cards exist on dashboard in proper order', () => { + // Ensures that info cards are all displayed on the dashboard tab while being in the proper + // order, checks for card title and position via indexing into a list of all info cards. + const order = [ + 'Cluster Status', + 'Hosts', + 'Monitors', + 'OSDs', + 'Managers', + 'Object Gateways', + 'Metadata Servers', + 'iSCSI Gateways', + 'Raw Capacity', + 'Objects', + 'PG Status', + 'Pools', + 'PGs per OSD', + 'Client Read/Write', + 'Client Throughput', + 'Recovery Throughput', + 'Scrubbing' + ]; + + for (let i = 0; i < order.length; i++) { + dashboard.infoCard(i).should('contain.text', order[i]); + } + }); + + it('should verify that info card group titles are present and in the right order', () => { + cy.location('hash').should('eq', '#/dashboard'); + dashboard.infoGroupTitle(0).should('eq', 'Status'); + dashboard.infoGroupTitle(1).should('eq', 'Capacity'); + dashboard.infoGroupTitle(2).should('eq', 'Performance'); + }); + }); + + it('Should check that dashboard cards have correct information', () => { + interface TestSpec { + cardName: string; + regexMatcher?: RegExp; + pageObject: PageHelper; + } + const testSpecs: TestSpec[] = [ + { cardName: 'Object Gateways', regexMatcher: /(\d+)\s+total/, pageObject: daemons }, + { cardName: 'Monitors', regexMatcher: /(\d+)\s+\(quorum/, pageObject: monitors }, + { cardName: 'Hosts', regexMatcher: /(\d+)\s+total/, pageObject: hosts }, + { cardName: 'OSDs', regexMatcher: /(\d+)\s+total/, pageObject: osds }, + { cardName: 'Pools', pageObject: pools }, + { cardName: 'iSCSI Gateways', regexMatcher: /(\d+)\s+total/, pageObject: iscsi } + ]; + for (let i = 0; i < testSpecs.length; i++) { + const spec = testSpecs[i]; + dashboard.navigateTo(); + + dashboard.infoCardBodyText(spec.cardName).then((infoCardBodyText: string) => { + let dashCount = 0; + + if (spec.regexMatcher) { + const match = infoCardBodyText.match(new RegExp(spec.regexMatcher)); + expect(match).to.length.gt( + 1, + `Regex ${spec.regexMatcher} did not find a match for card with name ` + + `${spec.cardName}` + ); + dashCount = Number(match[1]); + } else { + dashCount = Number(infoCardBodyText); + } + + spec.pageObject.navigateTo(); + spec.pageObject.getTableCount('total').then((tableCount) => { + expect(tableCount).to.eq( + dashCount, + `Text of card "${spec.cardName}" and regex "${spec.regexMatcher}" resulted in ${dashCount} ` + + `but did not match table count ${tableCount}` + ); + }); + }); + } + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/dashboard.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/dashboard.po.ts new file mode 100644 index 000000000..42d63ef44 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/dashboard.po.ts @@ -0,0 +1,31 @@ +import { PageHelper } from '../page-helper.po'; + +export class DashboardPageHelper extends PageHelper { + pages = { index: { url: '#/dashboard', id: 'cd-dashboard' } }; + + infoGroupTitle(index: number) { + return cy.get('.info-group-title').its(index).text(); + } + + clickInfoCardLink(cardName: string) { + cy.get(`cd-info-card[cardtitle="${cardName}"]`).contains('a', cardName).click(); + } + + infoCard(indexOrTitle: number | string) { + cy.get('cd-info-card').as('infoCards'); + + if (typeof indexOrTitle === 'number') { + return cy.get('@infoCards').its(indexOrTitle); + } else { + return cy.contains('cd-info-card a', indexOrTitle).parent().parent().parent().parent(); + } + } + + infoCardBodyText(infoCard: string) { + return this.infoCard(infoCard).find('.card-text').text(); + } + + infoCardBody(infoCard: string) { + return this.infoCard(infoCard).find('.card-text'); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/language.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/language.e2e-spec.ts new file mode 100644 index 000000000..ccf16c2b5 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/language.e2e-spec.ts @@ -0,0 +1,20 @@ +import { LanguagePageHelper } from './language.po'; + +describe('Shared pages', () => { + const language = new LanguagePageHelper(); + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + language.navigateTo(); + }); + + it('should check default language', () => { + language.getLanguageBtn().should('contain.text', 'English'); + }); + + it('should check all available languages', () => { + language.getLanguageBtn().click(); + language.getAllLanguages().should('have.length', 1).should('contain.text', 'English'); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/language.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/language.po.ts new file mode 100644 index 000000000..80e21ba1e --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/language.po.ts @@ -0,0 +1,15 @@ +import { PageHelper } from '../page-helper.po'; + +export class LanguagePageHelper extends PageHelper { + pages = { + index: { url: '#/dashboard', id: 'cd-dashboard' } + }; + + getLanguageBtn() { + return cy.get('cd-language-selector a').first(); + } + + getAllLanguages() { + return cy.get('cd-language-selector button'); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/login.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/login.e2e-spec.ts new file mode 100644 index 000000000..29c9e9e10 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/login.e2e-spec.ts @@ -0,0 +1,17 @@ +import { LoginPageHelper } from './login.po'; + +describe('Login page', () => { + const login = new LoginPageHelper(); + + it('should login and navigate to dashboard page', () => { + login.navigateTo(); + login.doLogin(); + }); + + it('should logout when clicking the button', () => { + login.navigateTo(); + login.doLogin(); + + login.doLogout(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/login.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/login.po.ts new file mode 100644 index 000000000..d4d2c6921 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/login.po.ts @@ -0,0 +1,22 @@ +import { PageHelper } from '../page-helper.po'; + +export class LoginPageHelper extends PageHelper { + pages = { + index: { url: '#/login', id: 'cd-login' }, + dashboard: { url: '#/dashboard', id: 'cd-dashboard' } + }; + + doLogin() { + cy.get('[name=username]').type('admin'); + cy.get('#password').type('admin'); + cy.get('[type=submit]').click(); + cy.get('cd-dashboard').should('exist'); + } + + doLogout() { + cy.get('cd-identity a').click(); + cy.contains('cd-identity span', 'Sign out').click(); + cy.get('cd-login').should('exist'); + cy.location('hash').should('eq', '#/login'); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/navigation.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/navigation.e2e-spec.ts new file mode 100644 index 000000000..fee2d2db9 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/navigation.e2e-spec.ts @@ -0,0 +1,24 @@ +import { NavigationPageHelper } from './navigation.po'; + +describe('Shared pages', () => { + const shared = new NavigationPageHelper(); + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + shared.navigateTo(); + }); + + it('should display the vertical menu by default', () => { + shared.getVerticalMenu().should('not.have.class', 'active'); + }); + + it('should hide the vertical menu', () => { + shared.getMenuToggler().click(); + shared.getVerticalMenu().should('have.class', 'active'); + }); + + it('should navigate to the correct page', () => { + shared.checkNavigations(shared.navigations); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/navigation.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/navigation.po.ts new file mode 100644 index 000000000..a7ecf3af0 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/navigation.po.ts @@ -0,0 +1,69 @@ +import { PageHelper } from '../page-helper.po'; + +export class NavigationPageHelper extends PageHelper { + pages = { + index: { url: '#/dashboard', id: 'cd-dashboard' } + }; + + navigations = [ + { menu: 'NFS', component: 'cd-error' }, + { + menu: 'Object Gateway', + submenus: [ + { menu: 'Daemons', component: 'cd-rgw-daemon-list' }, + { menu: 'Users', component: 'cd-rgw-user-list' }, + { menu: 'Buckets', component: 'cd-rgw-bucket-list' } + ] + }, + { menu: 'Dashboard', component: 'cd-dashboard' }, + { + menu: 'Cluster', + submenus: [ + { menu: 'Hosts', component: 'cd-hosts' }, + { menu: 'Physical Disks', component: 'cd-error' }, + { menu: 'Monitors', component: 'cd-monitor' }, + { menu: 'Services', component: 'cd-error' }, + { menu: 'OSDs', component: 'cd-osd-list' }, + { menu: 'Configuration', component: 'cd-configuration' }, + { menu: 'CRUSH map', component: 'cd-crushmap' }, + { menu: 'Manager Modules', component: 'cd-mgr-module-list' }, + { menu: 'Logs', component: 'cd-logs' }, + { menu: 'Monitoring', component: 'cd-prometheus-tabs' } + ] + }, + { menu: 'Pools', component: 'cd-pool-list' }, + { + menu: 'Block', + submenus: [ + { menu: 'Images', component: 'cd-error' }, + { menu: 'Mirroring', component: 'cd-mirroring' }, + { menu: 'iSCSI', component: 'cd-iscsi' } + ] + }, + { menu: 'File Systems', component: 'cd-cephfs-list' } + ]; + + getVerticalMenu() { + return cy.get('nav[id=sidebar]'); + } + + getMenuToggler() { + return cy.get('[aria-label="toggle sidebar visibility"]'); + } + + checkNavigations(navs: any) { + // The nfs-ganesha, RGW, and block/rbd status requests are mocked to ensure that this method runs in time + cy.intercept('/ui-api/nfs-ganesha/status', { fixture: 'nfs-ganesha-status.json' }); + cy.intercept('/ui-api/rgw/status', { fixture: 'rgw-status.json' }); + cy.intercept('/ui-api/block/rbd/status', { fixture: 'block-rbd-status.json' }); + + navs.forEach((nav: any) => { + cy.contains('.simplebar-content li.nav-item a', nav.menu).click(); + if (nav.submenus) { + this.checkNavigations(nav.submenus); + } else { + cy.get(nav.component).should('exist'); + } + }); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/notification.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/notification.e2e-spec.ts new file mode 100644 index 000000000..2ee73a706 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/notification.e2e-spec.ts @@ -0,0 +1,59 @@ +import { PoolPageHelper } from '../pools/pools.po'; +import { NotificationSidebarPageHelper } from './notification.po'; + +describe('Notification page', () => { + const notification = new NotificationSidebarPageHelper(); + const pools = new PoolPageHelper(); + const poolName = 'e2e_notification_pool'; + + before(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + pools.navigateTo('create'); + pools.create(poolName, 8); + pools.edit_pool_pg(poolName, 4, false); + }); + + after(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + pools.navigateTo(); + pools.delete(poolName); + }); + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + pools.navigateTo(); + }); + + it('should open notification sidebar', () => { + notification.getSidebar().should('not.be.visible'); + notification.open(); + notification.getSidebar().should('be.visible'); + }); + + it('should display a running task', () => { + notification.getToast().should('not.exist'); + + // Check that running task is shown. + notification.open(); + notification.getTasks().contains(poolName).should('exist'); + + // Delete pool after task is complete (otherwise we get an error). + notification.getTasks().contains(poolName, { timeout: 300000 }).should('not.exist'); + }); + + it('should have notifications', () => { + notification.open(); + notification.getNotifications().should('have.length.gt', 0); + }); + + it('should clear notifications', () => { + notification.getToast().should('not.exist'); + notification.open(); + notification.getNotifications().should('have.length.gt', 0); + notification.getClearNotficationsBtn().should('be.visible'); + notification.clearNotifications(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/notification.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/notification.po.ts new file mode 100644 index 000000000..12c424e35 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/notification.po.ts @@ -0,0 +1,45 @@ +import { PageHelper } from '../page-helper.po'; + +export class NotificationSidebarPageHelper extends PageHelper { + getNotificatinoIcon() { + return cy.get('cd-notifications a'); + } + + getSidebar() { + return cy.get('cd-notifications-sidebar'); + } + + getTasks() { + return this.getSidebar().find('.card.tc_task'); + } + + getNotifications() { + return this.getSidebar().find('.card.tc_notification'); + } + + getClearNotficationsBtn() { + return this.getSidebar().find('button.btn-block'); + } + + getCloseBtn() { + return this.getSidebar().find('button.close'); + } + + open() { + this.getNotificatinoIcon().click(); + this.getSidebar().should('be.visible'); + } + + clearNotifications() { + // It can happen that although notifications are cleared, by the time we check the notifications + // amount, another notification can appear, so we check it more than once (if needed). + this.getClearNotficationsBtn().click(); + this.getNotifications() + .should('have.length.gte', 0) + .then(($elems) => { + if ($elems.length > 0) { + this.clearNotifications(); + } + }); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/role-mgmt.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/role-mgmt.e2e-spec.ts new file mode 100644 index 000000000..c3f325dbb --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/role-mgmt.e2e-spec.ts @@ -0,0 +1,37 @@ +import { RoleMgmtPageHelper } from './role-mgmt.po'; + +describe('Role Management page', () => { + const roleMgmt = new RoleMgmtPageHelper(); + const role_name = 'e2e_role_mgmt_role'; + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + roleMgmt.navigateTo(); + }); + + describe('breadcrumb tests', () => { + it('should check breadcrumb on roles tab on user management page', () => { + roleMgmt.expectBreadcrumbText('Roles'); + }); + + it('should check breadcrumb on role creation page', () => { + roleMgmt.navigateTo('create'); + roleMgmt.expectBreadcrumbText('Create'); + }); + }); + + describe('role create, edit & delete test', () => { + it('should create a role', () => { + roleMgmt.create(role_name, 'An interesting description'); + }); + + it('should edit a role', () => { + roleMgmt.edit(role_name, 'A far more interesting description'); + }); + + it('should delete a role', () => { + roleMgmt.delete(role_name); + }); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/role-mgmt.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/role-mgmt.po.ts new file mode 100644 index 000000000..1cc3630a4 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/role-mgmt.po.ts @@ -0,0 +1,40 @@ +import { PageHelper } from '../page-helper.po'; + +export class RoleMgmtPageHelper extends PageHelper { + pages = { + index: { url: '#/user-management/roles', id: 'cd-role-list' }, + create: { url: '#/user-management/roles/create', id: 'cd-role-form' } + }; + + create(name: string, description: string) { + this.navigateTo('create'); + // Waits for data to load + cy.contains('grafana'); + + // fill in fields + cy.get('#name').type(name); + cy.get('#description').type(description); + + // Click the create button and wait for role to be made + cy.get('[data-cy=submitBtn]').click(); + cy.get('.breadcrumb-item.active').should('not.have.text', 'Create'); + + this.getFirstTableCell(name).should('exist'); + } + + edit(name: string, description: string) { + this.navigateEdit(name); + // Waits for data to load + cy.contains('grafana'); + + // fill in fields with new values + cy.get('#description').clear().type(description); + + // Click the edit button and check new values are present in table + cy.get('[data-cy=submitBtn]').click(); + cy.get('.breadcrumb-item.active').should('not.have.text', 'Edit'); + + this.getFirstTableCell(name).should('exist'); + this.getFirstTableCell(description).should('exist'); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/user-mgmt.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/user-mgmt.e2e-spec.ts new file mode 100644 index 000000000..92dc77212 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/user-mgmt.e2e-spec.ts @@ -0,0 +1,37 @@ +import { UserMgmtPageHelper } from './user-mgmt.po'; + +describe('User Management page', () => { + const userMgmt = new UserMgmtPageHelper(); + const user_name = 'e2e_user_mgmt_user'; + + beforeEach(() => { + cy.login(); + Cypress.Cookies.preserveOnce('token'); + userMgmt.navigateTo(); + }); + + describe('breadcrumb tests', () => { + it('should check breadcrumb on users tab of user management page', () => { + userMgmt.expectBreadcrumbText('Users'); + }); + + it('should check breadcrumb on user creation page', () => { + userMgmt.navigateTo('create'); + userMgmt.expectBreadcrumbText('Create'); + }); + }); + + describe('user create, edit & delete test', () => { + it('should create a user', () => { + userMgmt.create(user_name, 'cool_password', 'Jeff', 'realemail@realwebsite.com'); + }); + + it('should edit a user', () => { + userMgmt.edit(user_name, 'cool_password_number_2', 'Geoff', 'w@m'); + }); + + it('should delete a user', () => { + userMgmt.delete(user_name); + }); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/user-mgmt.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/user-mgmt.po.ts new file mode 100644 index 000000000..fb2b79129 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/cypress/integration/ui/user-mgmt.po.ts @@ -0,0 +1,39 @@ +import { PageHelper } from '../page-helper.po'; + +export class UserMgmtPageHelper extends PageHelper { + pages = { + index: { url: '#/user-management/users', id: 'cd-user-list' }, + create: { url: '#/user-management/users/create', id: 'cd-user-form' } + }; + + create(username: string, password: string, name: string, email: string) { + this.navigateTo('create'); + + // fill in fields + cy.get('#username').type(username); + cy.get('#password').type(password); + cy.get('#confirmpassword').type(password); + cy.get('#name').type(name); + cy.get('#email').type(email); + + // Click the create button and wait for user to be made + cy.get('[data-cy=submitBtn]').click(); + this.getFirstTableCell(username).should('exist'); + } + + edit(username: string, password: string, name: string, email: string) { + this.navigateEdit(username); + + // fill in fields with new values + cy.get('#password').clear().type(password); + cy.get('#confirmpassword').clear().type(password); + cy.get('#name').clear().type(name); + cy.get('#email').clear().type(email); + + // Click the edit button and check new values are present in table + const editButton = cy.get('[data-cy=submitBtn]'); + editButton.click(); + this.getFirstTableCell(email).should('exist'); + this.getFirstTableCell(name).should('exist'); + } +} |