diff --git a/cypress/e2e/group/groupMembers.feature b/cypress/e2e/group/groupMembers.feature new file mode 100644 index 00000000..6f7a5ff8 --- /dev/null +++ b/cypress/e2e/group/groupMembers.feature @@ -0,0 +1,20 @@ +@release +Feature: Group - To show members in a group + + As a teacher I want to see the members in a group + + @stable_test + Scenario: As a teacher I can manage a group of type class from external systems + Given I am logged in as a 'teacher1_nbc' at 'nbc' + When I go to administration page + And I go to new class administration page + Then I see the new class administration page + And I can see the group 'Cypress-Test-Group' with source 'moin.schule' + And the group 'Cypress-Test-Group' has a manage button + When I click the manage group button + Then I can see the manage group page + And I can see the manage group page title + And I can see the group member table + And I can see the 'Lehrkraft' with name 'Herzog' + And I can see the infobox + And I can see the infotext diff --git a/cypress/e2e/group/showGroupsAndClassesInTable.feature b/cypress/e2e/group/showGroupsAndClassesInTable.feature new file mode 100644 index 00000000..faca0496 --- /dev/null +++ b/cypress/e2e/group/showGroupsAndClassesInTable.feature @@ -0,0 +1,83 @@ +@release +Feature: Group - To show groups and classes in one table with respective functionality + + As a teacher I want to see all groups and classes belonging to my school. + + @stable_test + Scenario: As a pre-condition teacher adds a class to school + Given I am logged in as a 'teacher1_nbc' at 'nbc' + When I go to administration page + And I go to class administration + And I click on add class + And I click on the confirm button + And I confirm managing the class + Then I see the new class administration page + + @stable_test + Scenario: As a teacher i can see all classes and groups of my school on the new class administration page. + Given I see the new class administration page + Then I can see the page title + And I can see the group 'Cypress-Test-Group' with source 'moin.schule' + And I can see the class '1' without source + And the group 'Cypress-Test-Group' has a manage button + And the class '1' has 4 enabled action items + + @stable_test + Scenario: As a teacher i can manage my classes + Given I see the new class administration page + When I click the manage button + Then I can see the manage classes page + When I click the cancel manage class button + Then I can see the cancel modal + When I click the confirmation button on the cancel modal + Then I see the new class administration page + When I click the manage button + And I confirm managing the class + Then I see the new class administration page + + @stable_test + Scenario: As a teacher i can edit my classes + Given I see the new class administration page + When I click the edit button + Then I can see the edit classes page + When I click the cancel edit class button + Then I can see the cancel modal + When I click the confirmation button on the cancel modal + Then I see the new class administration page + When I click the edit button + When I click in the name suffix text element + Then I can click on the save changes button + And I see the new class administration page + + @stable_test + Scenario: As a teacher i can upgrade my upgradable classes + Given I see the new class administration page + When I click the create successor button + Then I can see the create successor page + When I click the cancel create successor button + Then I can see the cancel modal + When I click the confirmation button on the cancel modal + Then I see the new class administration page + When I click the create successor button + And I confirm creating the successor + And I confirm managing the class + Then I see the new class administration page + And the create successor button of the original class is disabled + + @stable_test + Scenario: As a teacher i can delete my classes + Given I see the new class administration page + When I click the delete button + Then I can see the delete modal + When I click the cancel button on the delete modal + Then I see the new class administration page + When I click the delete button + And I click the confirmation button on the delete modal + Then I see the new class administration page + + @stable_test + Scenario: As a post-condition teacher deletes the successor class and logs out + Given I see the new class administration page + When I click the delete button + And I click the confirmation button on the delete modal + Then I see the new class administration page diff --git a/cypress/support/pages/admin/pageAdministration.js b/cypress/support/pages/admin/pageAdministration.js index addbe8a1..ffe9cca8 100644 --- a/cypress/support/pages/admin/pageAdministration.js +++ b/cypress/support/pages/admin/pageAdministration.js @@ -29,6 +29,7 @@ class Management { static #teacherAdministrationNavigationButton = '[data-testid="Lehrkräfte"]' static #courseAdministrationNavigationButton = '[data-testid="Kurse"]' static #classAdministrationNavigationButton = '[data-testid="Klassen"]' + static #newClassAdministrationNavigationButton = '[data-testid="administrate_classes_new"]' static #teamAdministrationNavigationButton = '[data-testid="Teams"]' static #schoolAdministrationNavigationButton = '[data-testid="Schule"]' static #studentTeamCheckbox = '[data-testid="student_team_checkbox"]' @@ -124,6 +125,11 @@ class Management { cy.url().should('include', '/administration/classes') } + navigateToNewClassAdministration() { + cy.get(Management.#newClassAdministrationNavigationButton).click() + cy.url().should('include', '/administration/groups/classes') + } + navigateToTeamAdministration() { cy.get(Management.#teamAdministrationNavigationButton).eq(1).click() cy.url().should('include', '/administration/teams') diff --git a/cypress/support/pages/group/pageGroups.js b/cypress/support/pages/group/pageGroups.js new file mode 100644 index 00000000..4e5ca272 --- /dev/null +++ b/cypress/support/pages/group/pageGroups.js @@ -0,0 +1,196 @@ +'use strict' + +class Groups { + static #createClass = '[data-testid="createClass"]'; + static #confirmClassCreate = '[data-testid="confirmClassCreate"]'; + static #manageConfirm = '[data-testid="manage-confirm"]'; + static #classTitleNew = '[data-testid="admin-class-title"]'; + static #classTableNew = '[data-testid="admin-class-table"]'; + static #manageClassButton = '[data-testid="legacy-class-table-manage-btn"]'; + static #cancelModal = '[data-testid="modal_content"]'; + static #editClassButton = '[data-testid="class-table-edit-btn"]'; + static #createSuccessorButton = '[data-testid="class-table-successor-btn"]'; + static #deleteClassButton = '[data-testid="class-table-delete-btn"]'; + static #deleteDialog = '.v-dialog--active'; + static #deleteDialogCancel = '[data-testid="dialog-cancel"]'; + static #deleteDialogConfirm = '[data-testid="dialog-confirm"]'; + static #adminGroupTitle = '[data-testid="admin-class-title"]'; + static #groupMemberTable = '[data-testid="class-members-table"]'; + static #classMemberInfoBox = '[data-testid="class-members-info-box"]'; + static #classMemberInfoBoxText = '[data-testid="class-members-info-box-text"]'; + static #manageGroupButton = '[data-testid="class-table-members-manage-btn"]'; + + clickCreateClass() { + cy.get(Groups.#createClass) + .click(); + } + + clickConfirmCreateClass() { + cy.get(Groups.#confirmClassCreate) + .click(); + } + + clickConfirmManageClass() { + cy.get(Groups.#manageConfirm) + .click(); + } + + clickCancelButton() { + cy.get('.btn-cancel') + .click(); + } + + clickManageClassButton() { + cy.get(Groups.#manageClassButton) + .first().click(); + } + + clickConfirmButton() { + cy.get('.historyback') + .click(); + } + + clickEditClassButton() { + cy.get(Groups.#editClassButton) + .first().click(); + } + + clickNameSuffixField() { + cy.get('[name=classsuffix]') + .click(); + } + + clickCreateSuccessorButton() { + cy.get(Groups.#createSuccessorButton) + .first().click(); + } + + clickSaveChangesButton() { + cy.get('.btn-primary') + .eq(0) + .should('not.be.disabled') + .click(); + } + + clickConfirmSuccessor() { + cy.get('.btn-primary') + .eq(0) + .click(); + } + + clickDeleteButton() { + cy.get(Groups.#deleteClassButton) + .first().click(); + } + + clickCancelDeleteDialogButton() { + cy.get(Groups.#deleteDialogCancel) + .click(); + } + + clickConfirmDeleteDialogButton() { + cy.get(Groups.#deleteDialogConfirm) + .click(); + } + + isNewClassAdministrationPage() { + cy.url().should('include', '/administration/groups/classes'); + } + + isManageClassPage() { + cy.url().should('include', '/administration/classes'); + cy.url().should('include', '/manage'); + } + + isEditClassPage() { + cy.url().should('include', '/administration/classes'); + cy.url().should('include', '/edit'); + } + + isCancelModal() { + cy.get(Groups.#cancelModal).should('exist'); + } + + isCreateSuccessorPage() { + cy.url().should('include', '/administration/classes'); + cy.url().should('include', '/createSuccessor'); + } + + seeNewClassPageTitle() { + cy.get(Groups.#classTitleNew).should('exist'); + } + + isSuccessorButtonDisabled() { + cy.get(Groups.#createSuccessorButton) + .first().should('have.class', 'v-btn--disabled'); + } + + isDeleteDialog() { + cy.get(Groups.#deleteDialog) + .should('be.visible'); + } + + newClassTableContainsClass(className, sourceName) { + const classNameData = cy.get(Groups.#classTableNew).find('td').contains(className); + + classNameData.should('be.visible'); + classNameData.siblings('td').eq(0).should(($td) => { + expect($td.text().trim()).to.equal(sourceName); + }); + } + + groupsHaveAManageButton(groupName) { + const classNameData = cy.get(Groups.#classTableNew).find('td').contains(groupName); + + classNameData.siblings('td').eq(2).find('a[data-testid="class-table-members-manage-btn"]') + .should('exist'); + } + + classesHave4ActiveActionItems(className) { + const classNameData = cy.get(Groups.#classTableNew).find('td').contains(className); + + const buttons = classNameData.siblings('td').eq(2).find('a, button'); + + buttons.should('have.length', 4); + buttons.each(($btn) => { + cy.wrap($btn).should('not.be.disabled'); + }) + } + + seeManageGroupPage(){ + cy.url().should('include', '/administration/groups/classes/'); + } + + seeManageGroupPageTitle() { + cy.get(Groups.#adminGroupTitle).should('be.visible') + } + + seeGroupMemberTable() { + cy.get(Groups.#groupMemberTable).should('be.visible') + } + + seeGroupMemberTableContainsMember(role, lastName){ + const groupMemberData = cy.get(Groups.#groupMemberTable).find('td').contains(lastName); + + groupMemberData.should('be.visible'); + groupMemberData.siblings('td').eq(1).should(($td) => { + expect($td.text().trim()).to.equal(role); + }); + } + + seeClassMemberInfoBox() { + cy.get(Groups.#classMemberInfoBox).should('be.visible') + } + + seeClassMemberInfoBoxText() { + cy.get(Groups.#classMemberInfoBoxText).should('be.visible') + } + + clickManageGroupButton(){ + cy.get(Groups.#manageGroupButton) + .first().click(); + } + +} + +export default Groups diff --git a/cypress/support/step_definition/group/commonGroupSteps.spec.js b/cypress/support/step_definition/group/commonGroupSteps.spec.js new file mode 100644 index 00000000..54e49b31 --- /dev/null +++ b/cypress/support/step_definition/group/commonGroupSteps.spec.js @@ -0,0 +1,51 @@ +const { When, Then } = require('@badeball/cypress-cucumber-preprocessor') +import Groups from '../../pages/group/pageGroups' +import Management from '../../pages/admin/pageAdministration'; + + +const groups = new Groups(); +const management = new Management(); + +When('I go to class administration', () => { + management.navigateToClassAdministration(); +}) + +When('I go to new class administration page', () => { + management.navigateToNewClassAdministration(); +}) + +When('I click on add class', () => { + groups.clickCreateClass(); +}) + +When('I click on the confirm button', () => { + groups.clickConfirmCreateClass(); +}) + +When('I confirm managing the class', () => { + groups.clickConfirmManageClass(); +}) + +Then('I see the new class administration page', () => { + groups.isNewClassAdministrationPage(); +}) + +Then('I can see the page title', () => { + groups.seeNewClassPageTitle(); +}) + +Then('I can see the group {string} with source {string}', (groupName, systemName) => { + groups.newClassTableContainsClass(groupName, systemName); +}) + +Then('I can see the class {string} without source', (className) => { + groups.newClassTableContainsClass(className, ""); +}) + +Then('the group {string} has a manage button', (groupName) => { + groups.groupsHaveAManageButton(groupName); +}) + +Then('the class {string} has 4 enabled action items', (className) => { + groups.classesHave4ActiveActionItems(className); +}) diff --git a/cypress/support/step_definition/group/manageGroups.spec.js b/cypress/support/step_definition/group/manageGroups.spec.js new file mode 100644 index 00000000..9dfd79fe --- /dev/null +++ b/cypress/support/step_definition/group/manageGroups.spec.js @@ -0,0 +1,32 @@ +import Groups from "../../pages/group/pageGroups"; +import {Then, When} from "@badeball/cypress-cucumber-preprocessor"; + +const groups = new Groups(); + +When('I click the manage group button', () => { + groups.clickManageGroupButton(); +}) + +Then('I can see the manage group page', () => { + groups.seeManageGroupPage(); +}) + +Then('I can see the manage group page title', () => { + groups.seeManageGroupPageTitle() +}) + +Then('I can see the group member table', () => { + groups.seeGroupMemberTable() +}) + +Then('I can see the {string} with name {string}', (role, lastName) => { + groups.seeGroupMemberTableContainsMember(role, lastName) +}) + +Then('I can see the infobox', () => { + groups.seeClassMemberInfoBox() +}) + +Then('I can see the infotext', () => { + groups.seeClassMemberInfoBoxText() +}) diff --git a/cypress/support/step_definition/group/showGroupsAndClassesInTableSteps.spec.js b/cypress/support/step_definition/group/showGroupsAndClassesInTableSteps.spec.js new file mode 100644 index 00000000..30e29a22 --- /dev/null +++ b/cypress/support/step_definition/group/showGroupsAndClassesInTableSteps.spec.js @@ -0,0 +1,79 @@ +const { When, Then } = require('@badeball/cypress-cucumber-preprocessor') +import Groups from '../../pages/group/pageGroups'; + +const groups = new Groups() + +When('I click the manage button', () => { + groups.clickManageClassButton(); +}) + +Then('I can see the manage classes page', () => { + groups.isManageClassPage(); +}) + +When('I click the cancel manage class button', () => { + groups.clickCancelButton(); +}) + +Then('I can see the cancel modal', () => { + groups.isCancelModal(); +}) + +When('I click the confirmation button on the cancel modal', () => { + groups.clickConfirmButton(); +}) + +When('I click the edit button', () => { + groups.clickEditClassButton(); +}) + +Then('I can see the edit classes page', () => { + groups.isEditClassPage(); +}) + +When('I click the cancel edit class button', () => { + groups.clickCancelButton(); +}) + +When('I click in the name suffix text element', () => { + groups.clickNameSuffixField(); +}) + +Then('I can click on the save changes button', () => { + groups.clickSaveChangesButton(); +}) + +When('I click the create successor button', () => { + groups.clickCreateSuccessorButton(); +}) + +Then('I can see the create successor page', () => { + groups.isCreateSuccessorPage(); +}) + +When('I click the cancel create successor button', () => { + groups.clickCancelButton(); +}) + +When('I confirm creating the successor', () => { + groups.clickConfirmSuccessor(); +}) +Then('the create successor button of the original class is disabled', () => { + groups.isSuccessorButtonDisabled(); +}) + +When('I click the delete button', () => { + groups.clickDeleteButton(); +}) + +Then('I can see the delete modal', () => { + groups.isDeleteDialog(); +}) + +When('I click the cancel button on the delete modal', () => { + groups.clickCancelDeleteDialogButton(); +}) + +When('I click the confirmation button on the delete modal', () => { + groups.clickConfirmDeleteDialogButton(); +})