import { hasOperationName } from '../../../support/graphql'; const me = require('../../../fixtures/me.join-class.json'); const { getMinimalMe } = require('../../../support/helpers'); const MeQuery = getMinimalMe({}); const { me: teacher } = MeQuery; const members = [ { id: 'VXNlck5vZGU6Mw==', firstName: 'Otis', lastName: 'Milburn', }, { id: 'VXNlck5vZGU6NA==', firstName: 'Maeve', lastName: 'Wiley', }, ]; describe('School Class Management', () => { beforeEach(() => { cy.setup(); }); it('should join class', () => { const name = 'KF1A'; let selectedClassName = 'Moordale'; const getSelectedClassWithName = () => ({ id: 'selectedClassId', name: selectedClassName, }); cy.mockGraphqlOps({ operations: { MeQuery: () => ({ me: { ...teacher, selectedClass: getSelectedClassWithName(), }, }), // JoinClass() { // // fixme: is this necessary? the cache somehow does not seem to do anything for the MeQuery // let schoolClass = { // id, // name, // // __typename // }; // // localMe.me.schoolClasses.edges.push({ // // node: schoolClass, // // __typename: 'SchoolClassNodeEdge' // // }); // return { // joinClass: { // success: true, // schoolClass // } // } // }, JoinClass() { selectedClassName = name; return { joinClass: { success: true, schoolClass: getSelectedClassWithName(), }, }; }, MySchoolClassQuery: () => ({ me: { ...teacher, selectedClass: getSelectedClassWithName(), }, }), }, }); cy.visit('/me/profile'); cy.get('[data-cy=header-user-widget]').within(() => { cy.get('[data-cy=user-widget-avatar]').click(); }); cy.get('[data-cy=class-selection]').click(); cy.get('[data-cy=class-selection-entry]').should('have.length', 1); cy.get('[data-cy=class-selection]').click(); cy.get('[data-cy=join-class-link]').click(); cy.get('[data-cy=join-form-input]').type('XXXX'); cy.get('[data-cy=join-form-confirm]').click(); cy.get('[data-cy=group-list-name]').should('contain', name); cy.get('[data-cy=current-class-name]').should('contain', name); cy.get('[data-cy=header-user-widget]').within(() => { cy.get('[data-cy=user-widget-avatar]').click(); }); cy.get('[data-cy=class-selection]').click(); cy.get('[data-cy=class-selection-entry]').should('have.length', 2); }); it('should leave and re-join class', () => { cy.mockGraphqlOps({ operations: { MeQuery, AddRemoveMember: { addRemoveMember: { success: true, }, }, MySchoolClassQuery: { me: { ...teacher, }, }, }, }); cy.visit('/me/my-class'); cy.get('[data-cy=active-member]').should('have.length', 2); cy.get('[data-cy=inactive-class-members-list]').should('not.exist'); cy.get('[data-cy=remove-from-class]').first().click(); cy.get('[data-cy=modal-save-button]').click(); cy.getByDataCy('active-member').should('have.length', 1); cy.getByDataCy('inactive-member').should('have.length', 1); cy.get('[data-cy=add-to-class]').first().click(); cy.getByDataCy('active-member').should('have.length', 2); cy.get('[data-cy=inactive-class-members-list]').should('not.exist'); }); it('should display old classes', () => { let oldClasses = me.me.schoolClasses; let OldClassesQuery = { me: { ...me.me, oldClasses, }, }; cy.mockGraphqlOps({ operations: { MeQuery: me, OldClassesQuery, }, }); cy.visit('/me/old-classes'); cy.get('[data-cy=old-class-item]').should('have.length', 1); }); }); describe('Teacher Class Management', () => { beforeEach(() => { cy.setup(); }); it('changes class name', () => { let className = 'Gotta have class'; const { me: teacher } = getMinimalMe({}); let localMe = { me: teacher, }; cy.mockGraphqlOps({ operations: { MeQuery: localMe, MySchoolClassQuery: { me: { ...teacher, }, }, UpdateSchoolClass: { updateSchoolClass: { success: true, schoolClass: { name: className, }, }, }, }, }); cy.visit('/me/my-class'); cy.get('[data-cy=edit-group-name-link]').click(); cy.get('[data-cy=edit-name-input] input').type('{selectall}{backspace}').type(className); cy.get('[data-cy=modal-save-button]').click(); cy.get('[data-cy=group-list-name]').should('contain', className); }); it('removes student, then leaves class, then rejoins', () => { const myId = btoa('PrivateUserNode:1'); const memberId = btoa('GroupMemberNode:1'); let classMembers = [{ ...teacher, id: myId, isMe: true, isTeacher: true }, ...members]; let me = () => ({ ...teacher, id: memberId, selectedClass: { name: 'Just some class', id: 'selectedClassId', readOnly: false, members: classMembers, }, }); cy.mockGraphqlOps({ operations: { MeQuery: { me: me(), }, AddRemoveMember: { addRemoveMember: { success: true, }, }, MySchoolClassQuery: { me: me(), }, }, }); cy.visit('/me/my-class'); cy.getByDataCy('active-member').should('have.length', 3); cy.getByDataCy('remove-from-class').first().click(); cy.getByDataCy('deactivate-person-modal').should('exist'); cy.getByDataCy('modal-body-text').should('contain', 'deaktivieren'); cy.getByDataCy('modal-save-button').click(); cy.getByDataCy('active-member').should('have.length', 2); cy.getByDataCy('leave-group').click(); cy.getByDataCy('deactivate-person-modal').should('exist'); cy.getByDataCy('modal-body-text').should('contain', 'verlassen'); cy.getByDataCy('modal-save-button').click(); cy.getByDataCy('active-member').should('have.length', 1); cy.getByDataCy('rejoin-class').click(); cy.getByDataCy('active-member').should('have.length', 2); }); it('creates a new class', () => { const name = 'Hill Valley'; let selectedClass = teacher.selectedClass; const schoolClasses = [teacher.selectedClass]; const me = () => ({ ...teacher, selectedClass, schoolClasses, }); cy.mockGraphqlOps({ operations: { MeQuery: () => ({ me: me(), }), MySchoolClassQuery: () => ({ me: me(), }), }, }); cy.intercept('POST', '/api/graphql', (req) => { if (hasOperationName(req, 'CreateSchoolClass')) { const schoolClass = { __typename: 'SchoolClassNode', id: 'newSchoolClassId', name, readOnly: false, }; schoolClasses.push(schoolClass); selectedClass = schoolClass; req.reply({ data: { createSchoolClass: { result: schoolClass, }, }, }); } }); cy.visit('/me/my-class'); cy.get('h1').should('exist'); cy.get('[data-cy=header-user-widget]').within(() => { cy.get('[data-cy=user-widget-avatar]').click(); }); cy.get('[data-cy=class-selection]').click(); cy.get('[data-cy=class-selection-entry]').should('have.length', 1); cy.get('[data-cy=create-class-link]').click(); cy.get('[data-cy=join-form-input]').type(name); cy.get('[data-cy=join-form-confirm]').click(); cy.get('[data-cy=close-profile-sidebar-link]').click(); cy.get('[data-cy=group-list-name]').should('contain', name); cy.get('[data-cy=current-class-name]').should('contain', name); cy.get('[data-cy=header-user-widget]').within(() => { cy.get('[data-cy=user-widget-avatar]').click(); }); cy.get('[data-cy=class-selection]').click(); cy.get('[data-cy=class-selection-entry]').should('have.length', 2); }); it('tries to create a new class with duplicate name', () => { const name = 'Hill Billy Valley'; const oldName = 'Some stupid class'; let selectedClass = teacher.selectedClass; selectedClass.name = oldName; const schoolClasses = [teacher.selectedClass]; const me = () => ({ ...teacher, selectedClass, schoolClasses, }); cy.mockGraphqlOps({ operations: { MeQuery: () => ({ me: me(), }), MySchoolClassQuery: () => ({ me: me(), }), }, }); // since recently, graphql requests can be intercepted by cypress cy.intercept('POST', '/api/graphql', (req) => { if (hasOperationName(req, 'CreateSchoolClass')) { req.reply({ data: { createSchoolClass: { result: { __typename: 'DuplicateName', reason: 'Dieser Name wird bereits verwendet.', }, }, }, }); } }); cy.visit('/me/my-class'); cy.get('h1').should('exist'); cy.getByDataCy('group-list-name').should('contain', oldName); cy.get('[data-cy=header-user-widget]').within(() => { cy.get('[data-cy=user-widget-avatar]').click(); }); cy.get('[data-cy=class-selection]').click(); cy.get('[data-cy=class-selection-entry]').should('have.length', 1); cy.get('[data-cy=create-class-link]').click(); cy.get('[data-cy=join-form-input]').type(name); cy.get('[data-cy=join-form-confirm]').click(); cy.getByDataCy('join-form-input-error').should('contain', 'Dieser Name wird bereits verwendet.'); }); });