Fix some cypress tests

This commit is contained in:
Ramon Wenger 2022-10-26 17:00:34 +02:00
parent 6b4cff9760
commit 3f07a91d5c
46 changed files with 144 additions and 4204 deletions

View File

@ -2,26 +2,52 @@ import module from '../../../fixtures/module.minimal';
import {getMinimalMe} from '../../../support/helpers';
import {hasOperationName} from '../../../support/graphql';
let snapshotTitle;
let deleteSuccess;
let page;
const moduleWithSnapshots = {
...module,
snapshots: [
{
id: 'U25hcHNob3ROb2RlOjQ=',
title: 'Old Title',
created: '2020-01-01',
mine: true,
shared: false,
creator: 'me',
},
{
id: 'U25hcHNob3ROb2RlOjU=',
title: 'Shared snapshot',
created: '2020-01-02',
mine: false,
shared: true,
creator: 'someone else',
},
],
};
const mockDeleteSnapshot = (success) => {
cy.intercept('POST', '/api/graphql', (req) => {
if (hasOperationName(req, 'DeleteSnapshot')) {
let result;
if (success) {
result = {
message: 'yay!',
__typename: 'Success'
};
message: 'yay!',
__typename: 'Success',
};
} else {
result = {
reason: 'Not the owner',
__typename: 'NotOwner'
__typename: 'NotOwner',
};
}
req.reply({
data: {
deleteSnapshot: {
result
}
result,
},
},
});
@ -42,7 +68,7 @@ const mockUpdateSnapshot = (title) => {
} else {
snapshot = {
__typename: 'NotOwner',
reason: 'Not the owner'
reason: 'Not the owner',
};
}
req.reply({
@ -57,10 +83,57 @@ const mockUpdateSnapshot = (title) => {
};
// wait for the specified amount of requests in the test, so they don't spill over to the next test
const waitNTimes = (n) => {
for (let i = 0; i < n; i++) {
cy.wait('@graphqlRequest');
}
};
describe('Snapshot', () => {
const operations = isTeacher => ({
operations: {
UpdateSnapshot: {
updateSnapshot: {
snapshot() {
let result;
if (snapshotTitle) {
result = {
__typename: 'SnapshotNode',
id: 'U25hcHNob3ROb2RlOjQ=',
title: snapshotTitle,
};
} else {
result = {
__typename: 'NotOwner',
reason: 'Not the owner',
};
}
return result;
},
},
},
DeleteSnapshot: {
deleteSnapshot: {
result() {
let result;
if (deleteSuccess) {
result = {
message: 'yay!',
__typename: 'Success',
};
} else {
result = {
reason: 'Not the owner',
__typename: 'NotOwner',
};
}
return result;
},
},
},
MeQuery: getMinimalMe({isTeacher}),
ModuleDetailsQuery: {
module,
@ -77,6 +150,11 @@ describe('Snapshot', () => {
},
},
UpdateLastModule: {},
ModuleEditModeQuery: {
module: {
slug: module.slug,
},
},
ModuleSnapshotsQuery: {
module: {
...module,
@ -103,18 +181,21 @@ describe('Snapshot', () => {
SnapshotDetail: {
snapshot: {
chapters: [],
module: {}
}
module: {},
},
},
ApplySnapshot: {
applySnapshot: {
success: true
}
}
success: true,
},
},
},
});
beforeEach(() => {
snapshotTitle = false;
deleteSuccess = false;
page = moduleWithSnapshots;
cy.setup();
});
@ -122,6 +203,7 @@ describe('Snapshot', () => {
cy.mockGraphqlOps(operations(true));
cy.visit('module/miteinander-reden/');
cy.getByDataCy('snapshot-menu').should('be.visible');
waitNTimes(4);
});
it('Menu is not visible for student', () => {
@ -130,6 +212,7 @@ describe('Snapshot', () => {
cy.getByDataCy('module-title').should('be.visible');
cy.getByDataCy('snapshot-menu').should('not.exist');
waitNTimes(3);
});
it('Creates Snapshot', () => {
@ -141,6 +224,7 @@ describe('Snapshot', () => {
cy.getByDataCy('snapshot-list').should('exist').within(() => {
cy.get('.snapshots__snapshot').should('have.length', 1);
});
waitNTimes(7);
});
it('Applies Snapshot', () => {
@ -152,28 +236,33 @@ describe('Snapshot', () => {
cy.getByDataCy('module-title').should('exist');
cy.getByDataCy('snapshot-header').should('not.exist');
waitNTimes(9);
});
it('Renames Snapshot', () => {
cy.mockGraphqlOps(operations(true));
const newTitle = 'New Title';
mockUpdateSnapshot(newTitle);
snapshotTitle = newTitle;
// mockUpdateSnapshot(newTitle);
cy.visit('module/miteinander-reden/snapshots');
cy.getByDataCy('snapshot-link').should('have.text', 'Old Title');
cy.getByDataCy('rename-snapshot-button').click();
cy.getByDataCy('edit-name-input').clear().type(newTitle);
cy.getByDataCy('modal-save-button').click();
cy.getByDataCy('snapshot-link').should('have.text', 'New Title');
waitNTimes(5);
});
it('Deletes Snapshot', () => {
cy.mockGraphqlOps(operations(true));
mockDeleteSnapshot(true);
deleteSuccess = true;
// mockDeleteSnapshot(true);
cy.visit('module/miteinander-reden/snapshots');
cy.getByDataCy('snapshot-entry').should('have.length', 1);
cy.getByDataCy('delete-snapshot-button').click();
cy.getByDataCy('modal-save-button').click();
cy.getByDataCy('snapshot-entry').should('have.length', 0);
waitNTimes(6);
});
it('Displays the Snapshot list correcly', () => {
@ -188,5 +277,9 @@ describe('Snapshot', () => {
cy.getByDataCy('snapshot-link').should('have.text', 'Shared snapshot');
cy.getByDataCy('delete-snapshot-button').should('not.exist');
cy.getByDataCy('rename-snapshot-button').should('not.exist');
waitNTimes(4);
});
afterEach(() => {
});
});

View File

@ -2,6 +2,7 @@ import {getMinimalMe} from '../../../support/helpers';
const SELECTED_CLASS_ID = 'selectedClassId';
const slug = 'some-room';
const getOperations = ({readOnly, classReadOnly}) => {
const {me} = getMinimalMe({readOnly, classReadOnly, isTeacher: true});
return {
@ -18,7 +19,7 @@ const getOperations = ({readOnly, classReadOnly}) => {
RoomEntriesQuery: {
room: {
id: 'roomId',
slug: '',
slug,
title: 'room title',
entryCount: 3,
appearance: 'blue',
@ -32,7 +33,7 @@ const getOperations = ({readOnly, classReadOnly}) => {
{
node: {
id: 'entryId',
slug: '',
slug: 'room-entry-slug',
title: 'entry title',
contents: [],
author: {
@ -58,7 +59,7 @@ const checkRoomReadOnly = ({editable, readOnly, classReadOnly = false}) => {
});
const exist = editable ? 'exist' : 'not.exist';
cy.visit('room/some-room');
cy.visit(`room/${slug}`);
cy.get('.room-entry').should('exist');
cy.getByDataCy('add-room-entry-button').should(exist);
cy.getByDataCy('room-actions').should(exist);

View File

@ -10,6 +10,11 @@ export default {
chapters: [],
topic: {
title: 'A Topic Mock Title',
description: 'A Topic Mock Description'
}
description: 'A Topic Mock Description',
slug: 'a-topic-slug'
},
slug: 'a-module-slug',
solutionsEnabled: false,
bookmark: null,
__typename: 'ModuleNode'
};

View File

@ -1,72 +0,0 @@
// todo: reenable with a script that does the mutations, or with a workaround for fetch request checking in cypress
describe('Solutions', () => {
// todo: mock all the graphql queries and mutations
// todo: enable again
// // it('does not display the solution at first, then displays them after clicking', () => {
// // cy.viewport('macbook-15');
// // cy.login('ross.geller', 'test');
// //
// // cy.visit('/module/lohn-und-budget');
// // });
//
it('toggles the solution as teacher, then the student can display it', () => {
// cy.exec("python ../server/manage.py hidesolutions");
// cy.startGraphQLCapture();
// cy.route('POST', '/api/graphql/').as('graphQL');
// // does not work with cypress yet, because of the fetch api
// // https://github.com/cypress-io/cypress/issues/95
// // cy.get('[data-cy=toggle-enable-solutions]').within(() => {
// // cy.get('input[type=checkbox]').uncheck({force: true});
// // // cy.wait(2000);
// // cy.wait('@graphQL');
// // });
// // cy.logout();
// cy.viewport('macbook-15');
//
// cy.visit('/module/lohn-und-budget');
// cy.login('rachel.green', 'test');
// cy.get('[data-cy=module-title]').should('be.visible');
// cy.get('[data-cy=toggle-enable-solutions]')
// .should('not.exist');
// cy.get('[data-cy=solution]').should('not.exist');
//
// cy.visit('/survey/U3VydmV5Tm9kZTox');
//
// cy.get('.survey__page').should('exist');
// cy.get('[data-cy=solution]').should('not.exist');
// cy.get('.close-button').click();
//
// cy.logout();
//
// cy.visit('/module/lohn-und-budget');
// cy.login('ross.geller, 'test');
// cy.get('[data-cy=toggle-enable-solutions]').click();
// cy.waitFor('UpdateSolutionVisibility');
// cy.get('[data-cy=toggle-enable-solutions]').within(() => {
// cy.get('input[type=checkbox]').should('be.checked');
// });
//
// cy.logout();
//
// cy.visit('/module/lohn-und-budget');
// cy.login('rachel.green', 'test');
// // cy.get('[data-cy=solution]').should('exist');
// cy.get('[data-cy=solution]').first()
// .should('contain', 'anzeigen')
// .should('not.contain', 'Lösungssatz')
// .then($solution => {
// cy.wrap($solution).within(() => {
// cy.get('[data-cy=show-solution]').click();
// });
// cy.wrap($solution)
// .should('contain', 'Lösungssatz')
// .should('contain', 'ausblenden');
// });
//
// cy.visit('/survey/U3VydmV5Tm9kZTox');
//
// cy.get('.survey__page').should('exist');
// cy.get('[data-cy=solution]').should('exist');
});
});

View File

@ -1,63 +0,0 @@
describe('The Login Page', () => {
// it('login and redirect to main page', () => {
// const username = 'test';
// const password = 'test';
//
// cy.visit('/beta-login');
// cy.login(username, password, true);
// cy.assertStartPage();
// });
it('user sees error message if username is omitted', () => {
const username = '';
const password = 'test';
cy.visit('/beta-login');
cy.login(username, password);
cy.get('[data-cy=email-local-errors]').contains('E-Mail ist ein Pflichtfeld');
});
it('user sees error message if password is omitted', () => {
const username = 'test';
const password = '';
cy.visit('/beta-login');
cy.login(username, password);
cy.get('[data-cy=password-local-errors]').contains('Passwort ist ein Pflichtfeld');
});
it('user sees error message if credentials are invalid', () => {
const username = 'test';
const password = '12345';
cy.visit('/beta-login');
cy.login(username, password);
cy.get('[data-cy=login-error]').contains('Die E-Mail oder das Passwort ist falsch. Bitte versuchen Sie nochmals.');
});
it('logs out then logs in again', () => {
const user = 'rachel.green';
const pw = 'test';
cy.viewport('macbook-15');
cy.apolloLogin(user, pw);
cy.visit('/me/my-class');
cy.get('[data-cy=header-user-widget]').should('exist').within(() => {
cy.get('[data-cy=user-widget-avatar]').should('exist').click();
});
cy.get('[data-cy=logout]').click();
cy.get('[data-cy=oauth-login]').should('exist').within(() => {
cy.visit('/beta-login');
});
cy.login(user, pw);
cy.get('[data-cy=header-user-widget]').should('exist').within(() => {
cy.get('[data-cy=user-widget-avatar]').should('exist').click();
});
cy.get('.profile-sidebar').should('be.visible');
});
});

View File

@ -1,75 +0,0 @@
import { GraphQLError } from 'graphql';
import {assertStartPage} from '../../../support/helpers';
const schema = require('../../../fixtures/schema.json');
const redeemCoupon = coupon => {
if (coupon !== '') {
cy.get('[data-cy="coupon-input"]').type(coupon);
}
cy.get('[data-cy="coupon-button"]').click();
};
describe('Email Verification', () => {
beforeEach(() => {
cy.server();
});
it('forwards to homepage if confirmation key is correct', () => {
cy.viewport('macbook-15');
cy.mockGraphql({
schema: schema,
operations: {
Coupon: {
coupon: {
success: true
}
},
}
});
cy.apolloLogin('rachel.green', 'test');
cy.visit('/license-activation');
redeemCoupon('12345asfd');
assertStartPage();
});
it('displays error if input is missing', () => {
cy.viewport('macbook-15');
cy.apolloLogin('rachel.green', 'test');
cy.visit('/license-activation');
redeemCoupon('');
cy.get('[data-cy="coupon-local-errors"]').contains('Coupon-Code ist ein Pflichtfeld');
});
it('displays error if coupon input is wrong', () => {
cy.viewport('macbook-15');
cy.mockGraphql({
schema: schema,
operations: {
Coupon: new GraphQLError('invalid_coupon')
}
});
cy.apolloLogin('rachel.green', 'test');
cy.visit('/license-activation');
redeemCoupon('12345asfd');
cy.get('[data-cy="coupon-remote-errors"]').contains('Der angegebene Coupon-Code ist ungültig.');
});
it('displays error if an error occures', () => {
cy.viewport('macbook-15');
cy.mockGraphql({
schema: schema,
operations: {
Coupon: new GraphQLError('unknown_error')
}
});
cy.apolloLogin('rachel.green', 'test');
cy.visit('/license-activation');
redeemCoupon('12345asfd');
cy.get('[data-cy="coupon-remote-errors"]').contains('Es ist ein Fehler aufgetreten. Bitte versuchen Sie es nochmals oder kontaktieren Sie den Administrator.');
});
});

View File

@ -1,64 +0,0 @@
describe('Assignments', () => {
const studentSubmission = {
id: 'submission-id',
text: '',
document: '',
assignment: {},
submissionFeedback: {
id: 'feedback-id',
text: '',
final: false,
},
};
const operations = {
ModulesQuery: {},
AssignmentWithSubmissions: {
assignment: {
title: 'Ein Auftragstitel',
solution: '<p>Eine Lösung</p>',
assignment: '<p>Ein <b>Auftrag</b></p>',
submissions: [studentSubmission],
},
},
MeQuery: {
me: {},
},
ModuleDetailsQuery: {},
StudentSubmissions: {
studentSubmission,
},
UpdateSubmissionFeedback({input: {submissionFeedback}}) {
return {
updateSubmissionFeedback: {
successful: true,
updatedSubmissionFeedback: submissionFeedback,
},
};
},
};
beforeEach(() => {
cy.setup();
cy.mockGraphqlOps({
operations,
});
});
it('it does not display HTML tags', () => {
cy.visit('/module/lohn-und-budget/submissions/QXNzaWdubWVudE5vZGU6MQ==');
cy.getByDataCy('assignment-main-text').should('have.text', 'Ein Auftrag');
cy.getByDataCy('assignment-solution').should('have.text', 'Eine Lösung');
});
it('gives feedback as teacher (with Emojis 🧐)', () => {
const finalText = 'This is a feedback 🖐️';
cy.visit('/submission/submission-id');
cy.getByDataCy('submission-textarea').type('This is a feedback ');
cy.getByDataCy('emoji-button').should('have.length', 9).first().click();
cy.getByDataCy('submission-textarea').should('have.value', finalText);
cy.getByDataCy('submission-form-submit').click();
cy.getByDataCy('submission-form-submit').should('not.exist');
});
});

View File

@ -1,194 +0,0 @@
import {getMinimalMe} from '../../support/helpers';
import minimalModule from '../../fixtures/module.minimal';
const {me: minimalMe} = getMinimalMe({});
describe('Bookmarks', () => {
beforeEach(() => {
cy.setup();
cy.mockGraphqlOps({
operations: {
MeQuery: {
me: minimalMe
},
ModuleDetailsQuery: {
module: {
...minimalModule,
slug: 'my-module-slug',
chapters: [
{
title: 'My super Chapter',
contentBlocks: [
{
contents: [
{
type: 'text_block',
value: {
text: 'Das folgende Interview'
},
id: "df8212ee-3e82-49fa-977e-c4b60789163e"
}
]
}
]
}
]
}
},
InstrumentQuery: {
instrument: {
contents: [
{
type: 'text_block',
value: {
text: 'Hallo Sam'
},
id: "df8212ee-3e82-49fa-977e-c4b60789163e"
}
]
}
},
UpdateLastModule: {},
UpdateContentBookmark: {
updateContentBookmark: {
success: true
}
},
UpdateModuleBookmark: {
updateModuleBookmark: {
success: true
}
},
UpdateInstrumentBookmark: {
updateModuleBookmark: {
success: true
}
},
UpdateChapterBookmark: {
updateChapterBookmark: {
success: true
}
},
AddNote: ({input: {note}}) => ({
addNote: {
note
}
}),
UpdateNote: ({input: {note}}) => ({
updateNote: {
note
}
})
}
});
});
it('should bookmark instrument', () => {
cy.visit('/instrument/an-instrument');
cy.getByDataCy('content-component').first().as('contentComponent');
cy.get('@contentComponent').within(() => {
cy.get('.bookmark-actions__bookmark').click();
cy.get('.bookmark-actions__add-note').click();
});
cy.get('[data-cy=bookmark-note]').within(() => {
cy.get('.skillbox-input').type('Hallo Velo');
});
cy.get('[data-cy=modal-save-button]').click();
cy.get('@contentComponent').within(() => {
cy.get('.bookmark-actions__edit-note').click();
});
cy.get('[data-cy=bookmark-note]').within(() => {
cy.get('.skillbox-input').clear().type('Hello Bike');
});
cy.get('[data-cy=modal-save-button]').click();
});
it('should bookmark module', () => {
cy.visit('/module/lohn-und-budget/');
cy.getByDataCy('module-bookmark-actions').as('moduleBookmark');
cy.get('@moduleBookmark').within(() => {
cy.getByDataCy('bookmark-action').click();
cy.getByDataCy('add-note-action').click();
});
cy.get('[data-cy=bookmark-note]').within(() => {
cy.get('.skillbox-input').type('Hallo Velo');
});
cy.get('[data-cy=modal-save-button]').click();
cy.get('@moduleBookmark').within(() => {
cy.getByDataCy('edit-note-action').click();
});
cy.get('[data-cy=bookmark-note]').within(() => {
cy.get('.skillbox-input').clear().type('Hello Bike');
});
cy.get('[data-cy=modal-save-button]').click();
});
it('should bookmark chapter', () => {
cy.visit('/module/lohn-und-budget/');
cy.getByDataCy('chapter-bookmark-actions').as('chapterBookmark');
cy.get('@chapterBookmark').within(() => {
cy.getByDataCy('bookmark-action').click();
cy.getByDataCy('add-note-action').click();
});
cy.get('[data-cy=bookmark-note]').within(() => {
cy.get('.skillbox-input').type('Hallo Velo');
});
cy.get('[data-cy=modal-save-button]').click();
cy.get('@chapterBookmark').within(() => {
cy.getByDataCy('edit-note-action').click();
});
cy.get('[data-cy=bookmark-note]').within(() => {
cy.get('.skillbox-input').clear().type('Hello Bike');
});
cy.get('[data-cy=modal-save-button]').click();
});
it('should bookmark content block', () => {
cy.visit('/module/lohn-und-budget/');
cy.getByDataCy('content-component').contains('Das folgende Interview').parent().parent().as('interviewContent');
cy.get('@interviewContent').within(() => {
cy.get('.bookmark-actions__bookmark').click();
cy.get('.bookmark-actions__add-note').click();
});
cy.get('[data-cy=bookmark-note]').within(() => {
cy.get('.skillbox-input').type('Hallo Velo');
});
cy.get('[data-cy=modal-save-button]').click();
cy.get('@interviewContent').within(() => {
cy.get('.bookmark-actions__edit-note').click();
});
cy.get('[data-cy=bookmark-note]').within(() => {
cy.get('.skillbox-input').clear().type('Hello Bike');
});
cy.get('[data-cy=modal-save-button]').click();
});
});

View File

@ -1,27 +0,0 @@
describe('Instruments Page', () => {
beforeEach(() => {
cy.setup();
});
it('opens the instruments page', () => {
// cy.mockGraphqlOps({
// operations: {
// MeQuery: {},
// InstrumentQuery: {
// instrument: {
// title: 'A Guitar',
// intro: 'Money for Nothing',
// contents: ''
// // id: ID!
// // bookmarks: [InstrumentBookmarkNode]
// // type: InstrumentTypeNode
// }
// },
// },
// });
cy.visit('instrument/blabliblablub');
cy.getByDataCy('instrument-title').should('exist').should('contain', 'A Guitar');
cy.getByDataCy('instrument-intro').should('exist').should('contain', 'Money for Nothing');
});
});

View File

@ -1,140 +0,0 @@
const LANGUAGE_COMMUNICATION = 'LANGUAGE_COMMUNICATION';
const LANGUAGE_COMMUNICATION_VALUE = 'Sprache & Kommunikation';
const SOCIETY = 'SOCIETY';
const SOCIETY_VALUE = 'Gesellschaft';
const INTERDISCIPLINARY = 'INTERDISCIPLINARY';
const INTERDISCIPLINARY_VALUE = 'Überfachliche Instrumente';
describe('Instruments Page', () => {
beforeEach(() => {
cy.setup();
const languageCategory = {
name: LANGUAGE_COMMUNICATION_VALUE,
id: LANGUAGE_COMMUNICATION,
foreground: '#000000',
background: '#00ffff',
};
const societyCategory = {
name: SOCIETY_VALUE,
id: SOCIETY,
foreground: '#ffffff',
background: '#000fff',
};
const ANALYSE = 'analyse';
const ARGUMENTATION = 'argumentation';
const ETHIK = 'ethik';
const analyse = {
name: 'Analyse',
category: languageCategory,
type: ANALYSE,
id: ANALYSE
};
const argumentation = {
name: 'Argumentation',
category: languageCategory,
type: ARGUMENTATION,
id: ARGUMENTATION
};
const ethik = {
name: 'Ethik',
category: societyCategory,
type: ETHIK,
id: ETHIK
};
cy.mockGraphqlOps({
operations: {
MeQuery: {},
InstrumentsQuery: {
instruments: [
{
type: analyse,
title: 'Instrument: Analyse',
slug: 'analyse',
},
{
type: argumentation,
title: 'Instrument: Argumentation',
slug: 'argumentation',
},
{
type: ethik,
title: 'Instrument: Ethik',
slug: 'ethik',
},
],
},
InstrumentCategoriesQuery: {
instrumentCategories: [
{
name: 'Sprache & Kommunikation',
id: LANGUAGE_COMMUNICATION,
types: [
analyse,
argumentation,
{
name: 'Beschreibung',
category: languageCategory,
type: 'beschreibung',
},
],
},
{
name: SOCIETY_VALUE,
id: SOCIETY,
types: [
ethik,
{
name: 'Identität und Sozialisation',
category: societyCategory,
type: 'identitt-und-sozialisation',
},
],
},
{
name: INTERDISCIPLINARY_VALUE,
id: INTERDISCIPLINARY,
types: [],
},
],
},
},
});
});
it('opens the instruments page', () => {
cy.visit('instruments/');
cy.getByDataCy('instrument').should('have.length', 3);
cy.contains(LANGUAGE_COMMUNICATION_VALUE).click();
cy.getByDataCy('instrument').should('have.length', 2);
cy.contains(SOCIETY_VALUE).click();
cy.getByDataCy('instrument').should('have.length', 1);
cy.contains(INTERDISCIPLINARY_VALUE).click();
cy.getByDataCy('instrument').should('have.length', 0);
cy.contains('Analyse').click();
cy.getByDataCy('instrument').should('have.length', 1);
cy.contains('Ethik').click();
cy.getByDataCy('instrument').should('have.length', 1);
cy.getByDataCy('filter-all-instruments').click();
cy.getByDataCy('instrument').should('have.length', 3);
});
it('shows the correct instrument label', () => {
cy.visit('instruments/');
cy.getByDataCy('instrument').first().within(() => {
cy.getByDataCy('instrument-subheader').should('contain', 'Instrumente - Sprache & Kommunikation');
});
});
});

View File

@ -1,75 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
import minimalModule from '../../../fixtures/module.minimal';
const {me: minimalMe} = getMinimalMe({});
describe('Instruments on Module page', () => {
beforeEach(() => {
console.log('setting up');
cy.setup();
cy.mockGraphqlOps({
operations: {
UpdateLastModule: {
updateLastModule: {
success: true,
},
},
MeQuery: {
me: minimalMe,
},
ModuleDetailsQuery: {
module: {
...minimalModule,
slug: 'module-with-instrument',
chapters: [
{
title: 'Some Chapter',
contentBlocks: [
{
'type': 'instrument',
instrumentCategory: {
id: 'category-id',
name: 'Sprache & Kommunikation'
},
'title': 'Das Interview',
'contents': [
{
'type': 'basic_knowledge',
'value': {
'description': '<p>Ein Interview dient dazu, durch Befragung Informationen zu ermitteln. Bei journalistischen Interviews werden oft Expertinnen und Experten befragt, aber auch Personen.</p>',
},
},
],
},
{
'type': 'normal',
'title': 'Normaler Block',
instrumentCategory: null,
'contents': [
{
type: 'text_block',
value: {
text: 'Some text, not an instrument'
}
}
]
}
],
},
],
},
},
},
});
});
it('shows the correct instrument label', () => {
cy.visit('module/module-with-instrument');
cy.getByDataCy('content-block').first().within(() => {
cy.getByDataCy('instrument-label').should('contain', 'Instrumente - Sprache & Kommunikation');
});
cy.getByDataCy('content-block').eq(1).within(() => {
cy.getByDataCy('instrument-label').should('not.exist');
});
// also check that other content blocks don't have the label
});
});

View File

@ -1,74 +0,0 @@
import {getModules, getMinimalMe} from '../../../support/helpers';
describe('Apply module visibility', () => {
const schoolClasses = [
{
name: 'FLID2018a',
id: btoa('SchoolClassNode:1')
},
{
name: 'Andere Klasse',
id: btoa('SchoolClassNode:2')
},
];
const {me: minimalMe} = getMinimalMe({});
const me = {
...minimalMe,
schoolClasses
};
// name: '[\'FLID2018a\', \'Andere Klasse\']'
const operations = {
MeQuery: {
me
},
ModulesQuery: getModules,
UpdateSettings: {
updateSettings: {
success: true,
},
},
MySchoolClassQuery: {
me,
},
UpdateLastModule: {
updateLastModule: {
success: true,
},
},
SyncModuleVisibility: {
syncModuleVisibility: {
success: true,
},
},
ModuleDetailsQuery: {
module: {
id: 'some-module-id'
}
}
};
beforeEach(() => {
cy.setup();
});
it('clicks through the UI', () => {
cy.mockGraphqlOps({
operations
});
// go to module
cy.visit('/module/lohn-und-budget');
cy.selectClass('Andere Klasse');
// click on settings
cy.getByDataCy('module-settings-button').click();
// click on select button
cy.getByDataCy('select-school-class-button').click();
// select schoolclass
cy.getByDataCy('school-class-visibility-dropdown').select('FLID2018a');
// save changes
cy.getByDataCy('save-visibility-button').click();
cy.getByDataCy('module-title').should('exist');
});
});

View File

@ -1,77 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
// const operations = {
// MeQuery: getMinimalMe({isTeacher: false}),
// };
const MeQuery = getMinimalMe();
describe('Content Blocks', () => {
const slug = 'some-module';
const assignment = {
id: 'abc',
title: 'Some assignment',
assignment: 'Please write down your thoughts',
submission: null,
};
const module = {
title: 'Hello world',
slug,
solutionsEnabled: false,
chapters: [{
contentBlocks: [
{
title: 'A content block',
contents: [
{
type: 'text_block',
value: {
text: 'Ein Text',
},
},
{
type: 'assignment',
value: assignment,
},
],
},
],
}],
};
const operations = {
ModuleDetailsQuery: {
module,
},
MeQuery,
ModuleEditModeQuery: {
module: {
slug,
},
},
UpdateLastModule: {
module,
},
AssignmentQuery: {
assignment,
},
UpdateAssignmentWithSuccess: {
updateAssignment: {
successful: true,
updatedAssignment: assignment
},
},
};
beforeEach(() => {
cy.setup();
cy.mockGraphqlOps({operations});
cy.visit(`module/${slug}`);
});
it('types into the assignment input', () => {
cy.getByDataCy('submission-textarea').should('exist').type('My Solution');
});
it('does not see assignment input on mobile', () => {
cy.viewport('iphone-8');
cy.getByDataCy('submission-textarea').should('not.be.visible');
});
});

View File

@ -1,68 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
const MeQuery = getMinimalMe();
describe('Create Content Block', () => {
beforeEach(() => {
cy.setup();
cy.mockGraphqlOps({
operations: {
MeQuery,
ModuleDetailsQuery: {
module: {},
},
AddContentBlock: {
addContentBlock: {},
},
},
});
});
it('visits the page', () => {
// todo:
// add mocks
cy.visit('/module/some-module/add-after/bliblablub');
// add title
cy.getByDataCy('content-block-form-heading').should('exist');
cy.getByDataCy('content-list').should('not.exist');
cy.getByDataCy('save-button').should('exist').should('be.disabled');
cy.getByDataCy('content-block-title').within(() => {
cy.getByDataCy('input-with-label-input').type('Title of my book');
});
cy.getByDataCy('add-content-link').click();
cy.getByDataCy('chooser-heading').should('contain', 'Neuer Inhalt');
// add text element
cy.getByDataCy('choose-text-widget').click();
cy.get('.tip-tap__editor').last().type('Hallo Sam');
// add list item
cy.getByDataCy('add-content-link').last().click();
cy.getByDataCy('convert-to-list-checkbox').click();
// add text element to list item
cy.getByDataCy('choose-text-widget').click();
cy.getByDataCy('content-list').within(() => {
cy.get('.tip-tap__editor').last().type('Hallo Velo');
// add second list item
cy.getByDataCy('add-content-link').click();
// add text element to second list item
cy.getByDataCy('choose-text-widget').click();
cy.get('.tip-tap__editor').last().type('Hallo Velo');
// add another text element to second list item
cy.getByDataCy('add-content-link').last().click();
cy.getByDataCy('choose-text-widget').click();
cy.get('.tip-tap__editor').last().type('Hallo Outo');
});
// save
cy.getByDataCy('save-button').should('exist').should('not.be.disabled').click();
// another test
// go to page
// click cancel, go back
});
});
// todo: another test
// edit existing content block

View File

@ -1,210 +0,0 @@
const topics = [
{
id: 'VG9waWNOb2RlOjU=',
order: 1,
title: 'Geld und Kauf',
slug: 'geld-und-kauf',
},
{
id: 'VG9waWNOb2RlOjUz',
order: 2,
title: 'Berufliche Grundbildung',
slug: 'berufliche-grundbildung',
},
];
let recentModules = [];
const getId = (id) => btoa(`ModuleNode:${id}`);
const modules = {
[getId(1)]: {
title: 'Lohn und Budget',
metaTitle: 'Modul 1',
slug: 'lohn-und-budget',
id: getId(1),
},
[getId(2)]: {
title: 'Geld',
metaTitle: 'Modul 2',
slug: 'geld',
id: getId(2),
},
[getId(3)]: {
title: 'Lerntipps',
metaTitle: 'Modul 4',
slug: 'lerntipps',
id: getId(3),
},
[getId(4)]: {
title: 'Random',
metaTitle: 'Modul 5',
slug: 'random',
id: getId(4),
},
};
const slugs = {
'lohn-und-budget': getId(1),
'geld': getId(2),
'lerntipps': getId(3),
'random': getId(4),
};
const getModuleBySlug = (slug) => {
console.log('getModuleBySlug', slug);
const id = slugs[slug];
console.log(id);
return modules[id];
};
const moduleNodes = Object.values(modules).map(module => ({
node: module,
}));
console.log(moduleNodes);
const getTopic = () => {
console.info('calling getTopic');
return {
topic: {
title: 'Geld und Kauf',
id: 'VG9waWNOb2RlOjU=',
teaser: 'Topic 2',
modules: {
edges: moduleNodes,
},
}
};
};
const checkHome = (n, skipHome) => {
cy.log(`Checking if home has ${n} teasers`);
if (!skipHome) {
cy.get('[data-cy="home-link"]').click();
}
cy.get('[data-cy=start-modules-list]').should('exist');
cy.get('[data-cy=start-module-teaser]').should('have.length', n);
};
const goToModule = (topicTitle, moduleMetaTitle) => {
cy.log(`Going to module ${moduleMetaTitle} in topic ${topicTitle}`);
cy.get('[data-cy=open-sidebar-link]').click();
cy.contains(topicTitle).click();
cy.get('[data-cy=topic-title]').should('exist').should('contain', topicTitle);
cy.contains(moduleMetaTitle).click();
};
describe('Current Module', () => {
const me = {
lastModule: {
slug: 'lohn-und-budget',
id: 'last-module-id',
},
lastTopic: {
id: 'VG9waWNOb2RlOjU=',
slug: 'geld-und-kauf',
},
recentModules: {
edges: recentModules,
},
};
const operations = {
MeQuery: {
me,
},
AssignmentsQuery: {
assignments: [],
},
ModuleDetailsQuery: variables => {
console.log('calling ModuleDetailsQuery', getModuleBySlug(variables.slug));
return {
module: getModuleBySlug(variables.slug)
};
},
TopicsQuery: {
topics: {
edges: topics.map(topic => ({node: topic})),
},
},
Topic: getTopic(),
UpdateLastTopic: () => {
const Topic = getTopic();
const topic = Topic.topic;
return {
updateLastTopic: {
topic,
},
};
},
NewsTeasers: {
newsTeasers: {
edges: [],
},
},
UpdateLastModule: ({input: {id}}) => {
const lastModule = modules[id];
return {
updateLastModule: {
lastModule,
},
};
},
};
before(() => {
cy.setup();
});
it.skip('is set correctly', () => {
cy.mockGraphqlOps({
operations,
});
cy.visit('/');
// module list exists, but does not have anything in it
checkHome(0, true);
cy.get('[data-cy=no-modules-yet]').should('exist').should('contain', 'Sie haben sich noch kein Modul angeschaut. Legen Sie jetzt los!');
goToModule('Geld und Kauf', 'Modul 2');
cy.get('[data-cy=module-title]').should('contain', 'Geld');
checkHome(1);
cy.get('[data-cy=start-module-teaser]').first().should('contain', 'Geld');
goToModule('Geld und Kauf', 'Modul 1');
cy.get('[data-cy=module-title]').should('contain', 'Lohn und Budget');
checkHome(2);
cy.get('[data-cy=start-module-teaser]').first().should('contain', 'Lohn und Budget');
cy.get('[data-cy=start-module-teaser]').eq(1).should('contain', 'Geld');
goToModule('Geld und Kauf', 'Modul 4');
cy.get('[data-cy=module-title]').should('contain', 'Lerntipps');
checkHome(3);
cy.get('[data-cy=start-module-teaser]').first().should('contain', 'Lerntipps');
cy.get('[data-cy=start-module-teaser]').eq(1).should('contain', 'Lohn und Budget');
cy.get('[data-cy=start-module-teaser]').eq(2).should('contain', 'Geld');
// module list is full, should switch only the order around
goToModule('Geld und Kauf', 'Modul 2');
cy.get('[data-cy=module-title]').should('contain', 'Geld');
checkHome(3);
cy.get('[data-cy=start-module-teaser]').first().should('contain', 'Geld');
cy.get('[data-cy=start-module-teaser]').eq(1).should('contain', 'Lerntipps');
cy.get('[data-cy=start-module-teaser]').eq(2).should('contain', 'Lohn und Budget');
goToModule('Geld und Kauf', 'Modul 5');
cy.get('[data-cy=module-title]').should('contain', 'Random');
checkHome(3);
cy.get('[data-cy=start-module-teaser]').first().should('contain', 'Random');
cy.get('[data-cy=start-module-teaser]').eq(1).should('contain', 'Geld');
cy.get('[data-cy=start-module-teaser]').eq(2).should('contain', 'Lerntipps');
cy.get('[data-cy=start-module-teaser]').last().click();
cy.get('[data-cy=module-title]').should('contain', 'Lerntipps');
checkHome(3);
cy.get('[data-cy=start-module-teaser]').first().should('contain', 'Lerntipps');
cy.get('[data-cy=start-module-teaser]').eq(1).should('contain', 'Random');
cy.get('[data-cy=start-module-teaser]').eq(2).should('contain', 'Geld');
});
});

View File

@ -1,78 +0,0 @@
import module from '../../../fixtures/module.minimal';
import {getMinimalMe} from '../../../support/helpers';
const chapters = [{
title: 'ABC',
description: 'DEF',
contentBlocks: [
{
title: 'A ContentBlock',
userCreated: true,
mine: true,
contents: [
{
type: 'text_block',
value: {
text: 'Hello World'
}
}
],
},
],
}];
const operations = {
MeQuery: getMinimalMe({isTeacher: true}),
ModuleDetailsQuery: {
module: {
chapters,
},
},
ModuleEditModeQuery: {
module: {
slug: 'some-module',
}
},
DeleteContentBlock: {
success: true,
},
UpdateLastModule: {}
};
describe('Custom Content Block', () => {
beforeEach(() => {
cy.setup();
});
// todo: fix this test
it.skip('Deletes the custom content block and removes it from the view', () => {
cy.mockGraphqlOps({
operations,
});
cy.visit('module/some-module');
cy.log('Toggling Edit Mode');
cy.getByDataCy('toggle-editing').click();
cy.getByDataCy('module-title').should('exist');
cy.get('.content-block').should('have.length', 1);
cy.log('Opening More Menu');
cy.getByDataCy('more-options-link').click();
cy.log('Duplicating Content Block');
cy.getByDataCy('duplicate-content-block-link').click();
cy.get('.content-block').should('have.length', 2);
cy.log('Opening More Menu');
cy.getByDataCy('more-options-link').click();
// check if content block is still there
cy.log('Deleting Content Block');
cy.getByDataCy('delete-content-block-link').click();
cy.get('.content-block').should('have.length', 0);
});
});

View File

@ -1,192 +0,0 @@
import module from '../../../fixtures/module.minimal';
import {getMinimalMe} from '../../../support/helpers';
import {hasOperationName} from '../../../support/graphql';
const mockDeleteSnapshot = (success) => {
cy.intercept('POST', '/api/graphql', (req) => {
if (hasOperationName(req, 'DeleteSnapshot')) {
let result;
if (success) {
result = {
message: 'yay!',
__typename: 'Success'
};
} else {
result = {
reason: 'Not the owner',
__typename: 'NotOwner'
};
}
req.reply({
data: {
deleteSnapshot: {
result
}
},
});
}
});
};
const mockUpdateSnapshot = (title) => {
cy.intercept('POST', '/api/graphql', (req) => {
if (hasOperationName(req, 'UpdateSnapshot')) {
let snapshot;
if (title) {
snapshot = {
__typename: 'SnapshotNode',
id: 'U25hcHNob3ROb2RlOjQ=',
title,
};
} else {
snapshot = {
__typename: 'NotOwner',
reason: 'Not the owner'
};
}
req.reply({
data: {
updateSnapshot: {
snapshot,
},
},
});
}
});
};
describe('Snapshot', () => {
const operations = isTeacher => ({
operations: {
MeQuery: getMinimalMe({isTeacher}),
ModuleDetailsQuery: {
module,
},
CreateSnapshot: {
createSnapshot: {
snapshot: {
id: '',
title: '',
created: '',
creator: '',
},
success: true,
},
},
UpdateLastModule: {},
ModuleSnapshotsQuery: {
module: {
...module,
snapshots: [
{
id: 'U25hcHNob3ROb2RlOjQ=',
title: 'Old Title',
created: '2020-01-01',
mine: true,
shared: false,
creator: 'me',
},
{
id: 'U25hcHNob3ROb2RlOjU=',
title: 'Shared snapshot',
created: '2020-01-02',
mine: false,
shared: true,
creator: 'someone else',
},
],
},
},
SnapshotDetail: {
snapshot: {
chapters: [],
module: {}
}
},
ApplySnapshot: {
applySnapshot: {
success: true
}
}
},
});
beforeEach(() => {
cy.setup();
});
it('Menu is visible for teacher', () => {
cy.mockGraphqlOps(operations(true));
cy.visit('module/miteinander-reden/');
cy.getByDataCy('snapshot-menu').should('be.visible');
});
it('Menu is not visible for student', () => {
cy.mockGraphqlOps(operations(false));
cy.visit('module/miteinander-reden/');
cy.getByDataCy('module-title').should('be.visible');
cy.getByDataCy('snapshot-menu').should('not.exist');
});
it('Creates Snapshot', () => {
cy.mockGraphqlOps(operations(true));
cy.visit('module/miteinander-reden/');
cy.getByDataCy('module-snapshots-button').click();
cy.getByDataCy('create-snapshot-button').click();
cy.getByDataCy('show-all-snapshots-button').click();
cy.getByDataCy('snapshot-list').should('exist').within(() => {
cy.get('.snapshots__snapshot').should('have.length', 1);
});
});
it('Applies Snapshot', () => {
cy.mockGraphqlOps(operations(true));
cy.visit('module/miteinander-reden/snapshots');
cy.getByDataCy('snapshot-link').click();
cy.getByDataCy('apply-checkbox').click();
cy.getByDataCy('apply-button').click();
cy.getByDataCy('module-title').should('exist');
cy.getByDataCy('snapshot-header').should('not.exist');
});
it('Renames Snapshot', () => {
cy.mockGraphqlOps(operations(true));
const newTitle = 'New Title';
mockUpdateSnapshot(newTitle);
cy.visit('module/miteinander-reden/snapshots');
cy.getByDataCy('snapshot-link').should('have.text', 'Old Title');
cy.getByDataCy('rename-snapshot-button').click();
cy.getByDataCy('edit-name-input').clear().type(newTitle);
cy.getByDataCy('modal-save-button').click();
cy.getByDataCy('snapshot-link').should('have.text', 'New Title');
});
it('Deletes Snapshot', () => {
cy.mockGraphqlOps(operations(true));
mockDeleteSnapshot(true);
cy.visit('module/miteinander-reden/snapshots');
cy.getByDataCy('snapshot-entry').should('have.length', 1);
cy.getByDataCy('delete-snapshot-button').click();
cy.getByDataCy('modal-save-button').click();
cy.getByDataCy('snapshot-entry').should('have.length', 0);
});
it('Displays the Snapshot list correcly', () => {
cy.mockGraphqlOps(operations(true));
cy.visit('module/miteinander-reden/snapshots');
cy.getByDataCy('snapshot-entry').should('have.length', 1);
cy.getByDataCy('delete-snapshot-button').should('exist');
cy.getByDataCy('rename-snapshot-button').should('exist');
cy.getByDataCy('snapshot-link').should('have.text', 'Old Title');
cy.getByDataCy('team-snapshots-link').click();
cy.getByDataCy('snapshot-entry').should('have.length', 1);
cy.getByDataCy('snapshot-link').should('have.text', 'Shared snapshot');
cy.getByDataCy('delete-snapshot-button').should('not.exist');
cy.getByDataCy('rename-snapshot-button').should('not.exist');
});
});

View File

@ -1,88 +0,0 @@
import {getMe} from '../../../support/helpers';
import mocks from '../../../fixtures/mocks';
const modules = {
'lohn-und-budget': {
'objectiveGroups': {
'edges': [
{
'node': {
'title': 'LANGUAGE_COMMUNICATION',
'objectives': {
'edges': [
{
'node': {
'text': 'i-am-an-objective',
'hiddenFor': {
'edges': [],
},
},
},
],
},
},
},
],
},
},
};
const operations = {
MeQuery() {
return getMe({
schoolClasses: ['FLID2018a'],
teacher: false,
});
},
ModulesQuery: modules,
MySchoolClassQuery: {
me: {},
},
UpdateLastModule: {
updateLastModule: {
success: true,
},
},
SyncModuleVisibility: {
syncModuleVisibility: {
success: true,
},
},
};
// const mocks = {
// UUID: () => 'Whatever',
// GenericStreamFieldType: () => [],
// ObjectiveGroup: () => ({}),
// Module: () => ({
// title: 'title',
// slug: 'slug',
// metaTitle: 'metaTitle',
// teaser: 'teaser',
// intro: 'intro',
// assignments: {edges: []},
// objectiveGroups: {edges: []},
// id: 'ID',
// }),
// };
describe('Objective Visibility', () => {
beforeEach(() => {
cy.server();
cy.task('getSchema').then(schema => {
cy.mockGraphql({
schema,
// endpoint: '/api/graphql'
mocks,
operations,
});
});
});
//todo: finish writing this test, this does nothing
it.skip('should display the correct objectives', () => {
cy.fakeLogin('rachel.green', 'test');
cy.visit('/module/lohn-und-budget');
});
});

View File

@ -1,56 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
describe('New project', () => {
const MeQuery = getMinimalMe({isTeacher: false});
const schoolClass = MeQuery.me.selectedClass;
const operations = {
ProjectsQuery: {
projects: [
{
id: 'UHJvamVjdE5vZGU6NjY=',
title: 'Some random title',
appearance: 'blue',
description: 'This description rocks',
slug: 'some-random-title',
objectives: 'Git gud',
final: false,
schoolClass,
student: {
firstName: 'Rachel',
lastName: 'Green',
id: 'VXNlck5vZGU6NQ==',
avatarUrl: '',
},
entriesCount: 0,
},
],
},
MeQuery,
AddProject: variables => ({
addProject: {
project: Object.assign({}, variables.input.project, {schoolClass}),
errors: null,
__typename: 'AddProjectPayload',
},
}),
};
before(() => {
cy.setup();
});
it('creates a new project and displays it', () => {
cy.mockGraphqlOps({
operations,
});
cy.visit('/portfolio');
cy.get('[data-cy=create-project-button]').click();
cy.get('[data-cy=page-form-input-titel]').type('Some random title');
cy.get('[data-cy=page-form-input-beschreibung]').should('exist').should('be.empty');
cy.get('[data-cy=page-form-input-ziele]').should('not.exist');
cy.get('[data-cy=save-project-button]').click();
cy.getByDataCy('project').contains('random');
});
});

View File

@ -1,255 +0,0 @@
import {PROJECT_ENTRY_TEMPLATE} from '../../../../src/consts/strings.consts';
const created = '2021-06-01T11:49:00+00:00';
const createdLater = '2021-06-01T12:49:00+00:00';
const defaultEntries = [
{
id: 'UHJvamVjdEVudHJ5Tm9kZTo2NQ==',
description: 'Aktivität:\nKill Thanos\n\n\nReflexion:\nHe sucks\n\n\nNächste Schritte:\nGo for the head',
documentUrl: '',
created,
},
];
let entries = [...defaultEntries];
describe('Project Page', () => {
let final = false;
const project = {
id: 'UHJvamVjdE5vZGU6MzY=',
title: 'Groot',
appearance: 'yellow',
description: 'I am Groot',
slug: 'groot',
objectives: 'Be Groot\nBe awesome',
final: false,
student: {
firstName: 'Rachel',
lastName: 'Green',
id: 'VXNlck5vZGU6NQ==',
avatarUrl: '',
},
entries,
entriesCount: entries.length,
};
const operations = {
MeQuery: {
me: {
id: 'VXNlck5vZGU6NQ==',
permissions: [],
},
},
ProjectsQuery: {
projects: [
{
id: 'UHJvamVjdE5vZGU6MzM=',
title: 'Groot',
appearance: 'red',
description: 'I am Groot',
slug: 'groot',
objectives: 'Be Groot\nBe awesome',
final: false,
student: {
firstName: 'Rachel',
lastName: 'Green',
id: 'VXNlck5vZGU6NQ==',
avatarUrl: '',
},
entriesCount: 2,
},
],
},
ProjectQuery: () => ({
project,
}),
DeleteProject: {
deleteProject: {
success: true,
},
},
AddProjectEntry: variables => {
const projectEntry = Object.assign({}, variables.input.projectEntry, {
created: createdLater,
});
entries.push(projectEntry);
return {
addProjectEntry: {
projectEntry,
errors: null,
},
};
},
UpdateProjectEntry: variables => ({
updateProjectEntry: {
projectEntry: variables.input.projectEntry,
errors: null,
__typename: 'UpdateProjectEntryPayload',
},
}),
DeleteProjectEntry: {
deleteProjectEntry: {
success: true,
},
},
UpdateProjectShareState: () => {
final = !final;
return {
updateProjectSharedState: {
errors: null,
success: true,
shared: final,
},
};
},
};
beforeEach(() => {
cy.setup();
entries = [...defaultEntries];
cy.mockGraphqlOps({
operations,
});
});
it('has the correct layout', () => {
cy.visit('/portfolio/groot');
cy.getByDataCy('project-entry').eq(0).within(() => {
cy.getByDataCy('project-entry-date').should('contain', '1. Juni 2021');
});
});
it('uses the menu', () => {
cy.visit('/portfolio/groot');
cy.getByDataCy('project-actions').click();
cy.getByDataCy('delete-project').should('exist');
cy.getByDataCy('edit-project').should('exist');
});
it('deletes the project', () => {
cy.visit('/portfolio');
cy.getByDataCy('project-link').should('have.length', 1);
cy.getByDataCy('project-link').click();
cy.getByDataCy('project-actions').click();
cy.getByDataCy('delete-project').click();
cy.getByDataCy('page-title').should('contain', 'Portfolio');
cy.getByDataCy('project-link').should('have.length', 0);
});
it('shares and unshares the project', () => {
const getOperationsForSharing = () => {
let projectForSharing = {
...project,
final,
};
return {
...operations,
ProjectQuery: {
project: projectForSharing,
},
};
};
cy.mockGraphqlOps({
operations: getOperationsForSharing,
});
cy.visit('/portfolio/groot');
const unsharedText = 'Mit Lehrperson teilen';
const sharedText = 'Nicht mehr teilen';
cy.getByDataCy('project-share-link').should('contain', unsharedText);
cy.getByDataCy('project-share-link').click();
cy.getByDataCy('project-share-link').should('contain', sharedText);
cy.getByDataCy('project-share-link').click();
cy.getByDataCy('project-share-link').should('contain', unsharedText);
});
it('cannot edit or delete the project as a teacher', () => {
cy.mockGraphqlOps({
operations: {
...operations,
MeQuery: {
me: {
id: 'not-the-same',
isTeacher: true,
},
},
},
});
cy.visit('/portfolio/groot');
cy.getByDataCy('project-actions').should('not.exist');
cy.getByDataCy('project-entry').should('have.length', 1);
cy.getByDataCy('project-entry-more').should('not.exist');
});
it('does not show button on mobile', () => {
cy.viewport('iphone-8');
cy.getByDataCy('project-title').should('exist');
cy.getByDataCy('add-project-entry').should('not.exist');
});
describe('Project Entry', () => {
it('should create a new project entry', () => {
cy.visit('/portfolio');
cy.get('[data-cy=project-link]:first-of-type').click();
cy.get('[data-cy=add-project-entry]:first-of-type').click();
cy.getByDataCy('activity-input').should('not.exist');
cy.getByDataCy('reflection-input').should('not.exist');
cy.getByDataCy('next-steps-input').should('not.exist');
cy.getByDataCy('modal-title').should('contain', 'Beitrag erfassen');
cy.getByDataCy('project-entry-textarea').should('exist');
cy.getByDataCy('use-template-button').should('exist').click();
cy.getByDataCy('upload-document-button').should('exist');
cy.getByDataCy('modal-save-button').click();
cy.get('.project-entry:last-of-type').within(() => {
cy.get('.project-entry__paragraph:first-of-type').contains('Schwierigkeiten');
});
});
it('should edit first entry', () => {
cy.visit('/portfolio/groot');
cy.get('.project-entry__paragraph:first-of-type').contains('Kill Thanos');
cy.get('.project-entry:first-of-type').within(() => {
cy.get('[data-cy=project-entry-more]').click();
cy.get('[data-cy=edit-project-entry]').click();
});
cy.getByDataCy('activity-input').should('not.exist');
cy.getByDataCy('project-entry-textarea').clear().type('Defeat Thanos');
cy.get('[data-cy=modal-save-button]').click();
cy.get('.project-entry__paragraph:first-of-type').contains('Defeat Thanos');
});
it('should delete the last entry', () => {
cy.visit('/portfolio/groot');
cy.get('.project-entry').should('have.length', 1);
cy.get('.project-entry:last-of-type').within(() => {
cy.get('[data-cy=project-entry-more]').click();
cy.get('[data-cy=delete-project-entry]').click();
});
cy.get('.project-entry').should('have.length', 0);
});
it('should use the template', () => {
cy.visit('/portfolio/groot');
cy.get('[data-cy=add-project-entry]:first-of-type').click();
cy.getByDataCy('use-template-button').click();
cy.getByDataCy('project-entry-textarea').should('have.value', PROJECT_ENTRY_TEMPLATE);
});
it('should not display the entry actions on mobile', () => {
cy.viewport('iphone-8') ;
cy.visit('/portfolio/groot');
cy.getByDataCy('project-entry').should('exist');
cy.getByDataCy('project-entry-more').should('not.be.visible');
cy.getByDataCy('project-actions').should('not.be.visible');
});
});
})
;

View File

@ -1,128 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
describe('Projects page', () => {
const MeQuery = getMinimalMe({});
beforeEach(() => {
cy.setup();
cy.intercept('GET', '/avatars/**', {fixture: 'maxim.png'});
});
it('displays portfolio onboarding', () => {
const operations = {
MeQuery,
ProjectsQuery: {
projects: [],
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit('/portfolio');
cy.getByDataCy('page-title').should('contain', 'Portfolio');
cy.getByDataCy('portfolio-onboarding-illustration').should('exist');
cy.getByDataCy('portfolio-onboarding-subtitle').should('contain', 'Woran denken Sie gerade');
cy.getByDataCy('portfolio-onboarding-text').should('contain', 'Hier können Sie Projekte erstellen');
cy.getByDataCy('page-footer').should('not.exist');
cy.getByDataCy('create-project-button-onboarding').should('exist');
});
it('displays the project list', () => {
const projectTitle = 'What is love?';
const operations = {
MeQuery,
ProjectsQuery: {
projects: [
{
title: projectTitle,
student: {
firstName: 'Bilbo',
lastName: 'Baggins',
avatarUrl: '/avatars/bilbo.png',
},
entriesCount: 0,
entries: {
nodes: [],
},
},
],
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit('/portfolio');
cy.getByDataCy('page-title').should('contain', 'Portfolio');
cy.getByDataCy('create-project-button').should('exist');
cy.getByDataCy('project-list').should('exist');
cy.getByDataCy('project').should('have.length', 1);
cy.getByDataCy('owner-name').should('contain', 'Bilbo Baggins');
cy.getByDataCy('project-title').should('contain', projectTitle);
cy.getByDataCy('entry-count').should('contain', 0);
});
it('creates a new project', () => {
const operations = {
MeQuery,
ProjectsQuery: {
projects: [
{
title: 'first project',
student: {
firstName: 'Bilbo',
lastName: 'Baggins',
avatarUrl: '/avatars/bilbo.png',
},
entriesCount: 0,
entries: {
nodes: [],
},
},
],
},
AddProject: variables => {
const {input: {project}} = variables;
return {
addProject: {
errors: null,
project,
},
};
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit('/portfolio');
cy.getByDataCy('project').should('have.length', 1);
cy.getByDataCy('create-project-button').click();
cy.getByDataCy('page-form-input-titel').type('Titel');
cy.getByDataCy('page-form-input-beschreibung').type('Beschreibung');
cy.getByDataCy('save-project-button').click();
cy.getByDataCy('project').should('have.length', 2);
});
it('does not display button on mobile', () => {
const operations = {
MeQuery,
ProjectsQuery: {
projects: [],
},
};
cy.mockGraphqlOps({
operations,
});
cy.viewport('iphone-8');
cy.getByDataCy('page-title').should('exist');
cy.getByDataCy('create-project-button').should('not.be.visible');
});
});

View File

@ -1,71 +0,0 @@
const myText = 'Mein Feedback';
const getOperations = ({readOnly, classReadOnly = false}) => ({
MeQuery: {
me: {
readOnly,
selectedClass: {
id: 'selectedClassId',
readOnly: classReadOnly
}
},
},
StudentSubmissions: {
studentSubmission: {
id: 'id',
text: 'Submission Text',
document: '',
student: {
firstName: 'Peter',
lastName: 'Student',
},
assignment: {
title: 'Assignment Title',
assignment: 'Assignment Text',
},
submissionFeedback: {
id: 'feedback-id',
text: myText,
final: true,
},
},
},
});
describe('Assignment feedback read-only - Teacher', () => {
beforeEach(() => {
cy.setup();
});
it('can not edit', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: true}),
});
cy.visit('submission/submission-id');
cy.isSubmissionReadOnly(myText);
cy.getByDataCy('final-submission-reopen').should('not.exist');
});
it('can edit', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: false}),
});
cy.visit('submission/submission-id');
cy.getByDataCy('final-submission-reopen').should('exist');
});
it('can not edit for inactive class', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: false, classReadOnly: true}),
});
cy.visit('submission/submission-id');
cy.isSubmissionReadOnly(myText);
cy.getByDataCy('final-submission-reopen').should('not.exist');
});
});

View File

@ -1,122 +0,0 @@
import minimalModule from '../../../fixtures/module.minimal';
const module = {
...minimalModule,
chapters: [
{
contentBlocks: [
{
type: 'task',
contents: [
{
type: 'text_block',
value: {
text: 'hallo velo',
},
id: 'bla-123',
},
{
type: 'assignment',
value: {
title: 'assignment-title',
assignment: 'assignment-assignment',
id: 'some-assignment',
},
id: '123-456',
},
],
},
],
},
],
};
const myText = 'submission text';
const getOperations = ({final, readOnly, classReadOnly = false}) => ({
MeQuery: {
me: {
readOnly,
selectedClass: {
id: 'selectedClassId',
readOnly: classReadOnly
}
},
},
ModuleDetailsQuery: {
module,
},
UpdateLastModule: {},
AssignmentQuery: {
assignment: {
submission: {
text: myText,
final,
document: '',
submissionFeedback: null
},
},
},
});
describe('Assignments read-only - Student', () => {
beforeEach(() => {
cy.setup();
});
it('can edit and turn in', () => {
cy.mockGraphqlOps({
operations: getOperations({final: false, readOnly: false})
});
cy.visit('module/module-with-assignment');
cy.get('.submission-form__textarea').as('textarea');
cy.get('@textarea').invoke('val').should('contain', myText);
cy.get('@textarea').clear().type('Hello');
cy.get('@textarea').should('not.have.attr', 'readonly');
cy.getByDataCy('submission-form-submit').should('exist');
});
// todo: very flaky test, fix and re-enable
it.skip('can not edit or turn in', () => {
cy.mockGraphqlOps({
operations: getOperations({final: false, readOnly: true})
});
cy.visit('module/module-with-assignment');
cy.isSubmissionReadOnly(myText);
cy.getByDataCy('final-submission-reopen').should('not.exist');
});
it('can revoke turn in', () => {
cy.mockGraphqlOps({
operations: getOperations({final: true, readOnly: false})
});
cy.visit('module/module-with-assignment');
cy.getByDataCy('final-submission').should('exist');
cy.getByDataCy('final-submission-reopen').should('exist');
});
it('can not revoke turn in', () => {
cy.mockGraphqlOps({
operations: getOperations({final: true, readOnly: true})
});
cy.visit('module/module-with-assignment');
cy.getByDataCy('final-submission').should('exist');
cy.getByDataCy('final-submission-reopen').should('not.exist');
});
it('can not edit or turn in in inactive class', () => {
cy.mockGraphqlOps({
operations: getOperations({final: false, readOnly: false, classReadOnly: true})
});
cy.visit('module/module-with-assignment');
cy.isSubmissionReadOnly(myText);
cy.getByDataCy('final-submission-reopen').should('not.exist');
});
});

View File

@ -1,57 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
const getOperations = ({readOnly, classReadOnly = false}) => ({
MeQuery: getMinimalMe({readOnly, classReadOnly}),
NewsTeasers: {
newsTeasers: {
edges: [],
},
},
});
describe('Read Only Banner', () => {
beforeEach(() => {
cy.setup();
});
it('is not shown', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: false}),
});
cy.visit('/');
cy.getByDataCy('start-page-heading').should('exist');
cy.getByDataCy('read-only-banner').should('not.exist');
});
it('is shown for expired license', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: true}),
});
cy.visit('/');
cy.getByDataCy('start-page-heading').should('exist');
cy.getByDataCy('read-only-banner').should('exist').should('contain', 'Lizenz');
cy.getByDataCy('license-activation-link')
.should('exist')
.should('contain', 'Neuen Lizenzcode eingeben')
.click();
cy.url().should('contain', 'license-activation');
});
it('is shown for inactive school class', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: false, classReadOnly: true}),
});
cy.visit('/');
cy.getByDataCy('start-page-heading').should('exist');
cy.getByDataCy('read-only-banner').should('exist').should('contain', 'Klasse');
cy.getByDataCy('license-activation-link').should('not.exist');
});
});

View File

@ -1,94 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
const getOperations = (readOnly = false, classReadOnly = false) => {
const MeQuery = getMinimalMe({readOnly, classReadOnly});
const me = MeQuery.me;
return {
MeQuery,
MySchoolClassQuery: {
me: {
...me,
id: 'meId',
selectedClass: {
...me.selectedClass,
members: [
{
id: 'meId',
firstName: 'Helge',
lastName: 'Schneider',
isTeacher: true,
isMe: true,
active: true
},
{
id: 'notMeId',
firstName: 'Otto',
lastName: 'Waalkes',
isTeacher: false,
isMe: false,
active: true
},
{
id: 'alsoNotMeId',
firstName: 'Kaya',
lastName: 'Yanar',
isTeacher: false,
isMe: false,
active: false
}
]
}
},
},
AddRemoveMember: {
addRemoveMember: {
success: true
}
}
};
};
describe('Leave School Class', () => {
beforeEach(() => {
cy.setup();
});
it('can leave class', () => {
cy.mockGraphqlOps({
operations: getOperations(),
});
cy.visit('/me/class');
cy.getByDataCy('remove-from-class').should('exist');
cy.getByDataCy('add-to-class').should('exist');
cy.getByDataCy('leave-group').click();
cy.getByDataCy('modal-save-button').click();
cy.getByDataCy('read-only-banner').should('exist');
});
it('can not leave class when license invalid', () => {
cy.mockGraphqlOps({
operations: getOperations(true),
});
cy.visit('/me/class');
cy.getByDataCy('remove-from-class').should('not.exist');
cy.getByDataCy('add-to-class').should('not.exist');
cy.getByDataCy('leave-group').should('not.exist');
});
it('can not leave class when class inactive', () => {
cy.mockGraphqlOps({
operations: getOperations(false, true),
});
cy.visit('/me/class');
cy.getByDataCy('remove-from-class').should('not.exist');
cy.getByDataCy('add-to-class').should('not.exist');
cy.getByDataCy('leave-group').should('not.exist');
});
});

View File

@ -1,43 +0,0 @@
import minimalModule from '../../../fixtures/module.minimal';
import {getMinimalMe} from '../../../support/helpers';
const getOperations = ({readOnly, classReadOnly = false}) => ({
MeQuery: getMinimalMe({readOnly, classReadOnly}),
ModuleDetailsQuery: {
module: {
...minimalModule,
},
},
UpdateLastModule: {}
});
const moduleNavigationTest = ({readOnly, classReadOnly = false, displayMenu}) => {
cy.mockGraphqlOps({
operations: getOperations({readOnly, classReadOnly}),
});
const shouldMenuExist = displayMenu ? 'exist' : 'not.exist';
cy.visit('module/module-slug');
cy.getByDataCy('module-navigation').should('exist');
cy.getByDataCy('module-teacher-menu').should(shouldMenuExist);
};
describe('Module Navigation - read only', () => {
beforeEach(() => {
cy.setup();
});
it('is shown', () => {
moduleNavigationTest({readOnly: false, displayMenu: true});
});
it('is not shown when no valid license', () => {
moduleNavigationTest({readOnly: true, displayMenu: false});
});
it('is not shown when inactive school class', () => {
moduleNavigationTest({readOnly: false, classReadOnly: true, displayMenu: false});
});
});

View File

@ -1,41 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
const getOperations = ({readOnly}) => ({
MeQuery: getMinimalMe({readOnly}),
NewsTeasers: {
newsTeasers: [
{},
{},
{},
]
}
});
describe('Read Only News', () => {
beforeEach(() => {
cy.setup();
});
it('displays the news', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: false}),
});
cy.visit('/');
cy.getByDataCy('news-navigation-link').should('exist');
cy.getByDataCy('news-teasers').should('exist');
cy.getByDataCy('news-teaser').should('have.length', 2);
});
it('does not display the news', () => {
cy.mockGraphqlOps({
operations: getOperations({readOnly: true}),
});
cy.visit('/');
cy.getByDataCy('news-navigation-link').should('not.exist');
cy.getByDataCy('news-teasers').should('not.exist');
});
});

View File

@ -1,53 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
const getOperations = ({readOnly = false, classReadOnly = false}) => ({
MeQuery: getMinimalMe({readOnly, classReadOnly}),
ProjectsQuery: {
projects: [
{
id: 'projectId',
final: false,
student: {
id: btoa('PrivateUserNode:1'),
},
entriesCount: 3,
},
],
},
});
describe('Read Only Portfolio', () => {
beforeEach(() => {
cy.setup();
});
it('Can create and edit project', () => {
cy.mockGraphqlOps({operations: getOperations({readOnly: false})});
cy.visit('/portfolio');
cy.getByDataCy('project-list').should('exist');
cy.getByDataCy('create-project-button').should('exist');
cy.getByDataCy('project').should('have.length', 1);
cy.getByDataCy('project-actions').should('exist');
});
it('Can not create and edit project when license invalid', () => {
cy.mockGraphqlOps({operations: getOperations({readOnly: true})});
cy.visit('/portfolio');
cy.getByDataCy('project-list').should('exist');
cy.getByDataCy('add-project-button').should('not.exist');
cy.getByDataCy('project').should('have.length', 1);
cy.getByDataCy('project-actions').should('not.exist');
});
it('Can not create and edit project when class inactive', () => {
cy.mockGraphqlOps({operations: getOperations({readOnly: false, classReadOnly: true})});
cy.visit('/portfolio');
cy.getByDataCy('project-list').should('exist');
cy.getByDataCy('add-project-button').should('not.exist');
cy.getByDataCy('project').should('have.length', 1);
cy.getByDataCy('project-actions').should('not.exist');
});
});

View File

@ -1,48 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
const getOperations = ({readOnly = false, classReadOnly = false}) => ({
MeQuery: getMinimalMe({readOnly, classReadOnly}),
ProjectQuery: {
project: {
id: 'projectId',
slug: 'project-name',
final: false,
student: {
id: btoa('PrivateUserNode:1'),
},
entriesCount: 1,
entries: [
{}
]
},
},
});
const testProject = (readOnly, shouldActionsExist, classReadOnly = false) => {
cy.mockGraphqlOps({operations: getOperations({readOnly, classReadOnly})});
const exist = shouldActionsExist ? 'exist' : 'not.exist';
cy.visit('/portfolio/project-name');
cy.getByDataCy('project-title').should('exist');
cy.getByDataCy('project-entry').should('have.length', 1);
cy.getByDataCy('add-project-entry').should(exist);
cy.getByDataCy('project-actions').should(exist);
cy.getByDataCy('project-entry-more').should(exist);
};
describe('Read Only Project', () => {
beforeEach(() => {
cy.setup();
});
it('Can create and edit project entry', () => {
testProject(false, true);
});
it('Can not create and edit project entry when license expired', () => {
testProject(true, false);
});
it('Can not create and edit project entry when class inactive', () => {
testProject(false, false, true);
});
});

View File

@ -1,83 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
const SELECTED_CLASS_ID = 'selectedClassId';
const getOperations = ({readOnly, classReadOnly}) => {
const {me} = getMinimalMe({readOnly, classReadOnly, isTeacher: true});
return {
MeQuery: {
me: {
...me,
readOnly,
selectedClass: {
id: SELECTED_CLASS_ID,
readOnly: classReadOnly,
},
},
},
RoomEntriesQuery: {
room: {
id: 'roomId',
slug: '',
title: 'room title',
entryCount: 3,
appearance: 'blue',
description: 'room description',
schoolClass: {
id: SELECTED_CLASS_ID,
name: 'selected class',
},
roomEntries: {
edges: [
{
node: {
id: 'entryId',
slug: '',
title: 'entry title',
contents: [],
author: {
id: btoa('PublicUserNode:authorId'),
firstName: 'first',
lastName: 'last',
avatarUrl: '',
},
},
},
],
},
},
},
};
};
const checkRoomReadOnly = ({editable, readOnly, classReadOnly = false}) => {
const operations = getOperations({readOnly, classReadOnly});
cy.mockGraphqlOps({
operations,
});
const exist = editable ? 'exist' : 'not.exist';
cy.visit('room/some-room');
cy.get('.room-entry').should('exist');
cy.getByDataCy('add-room-entry-button').should(exist);
cy.getByDataCy('room-actions').should(exist);
};
describe('Room Team Management - Read only', () => {
beforeEach(() => {
cy.setup();
});
it('can edit room', () => {
checkRoomReadOnly({editable: true, readOnly: false});
});
it('can not edit room', () => {
checkRoomReadOnly({editable: false, readOnly: true});
});
it('can not edit room of inactive class', () => {
checkRoomReadOnly({editable: false, readOnly: false, classReadOnly: true});
});
});

View File

@ -1,61 +0,0 @@
describe('Room Team Management - Read only', () => {
const SELECTED_CLASS_ID = 'selectedClassId';
const getOperations = ({readOnly, classReadOnly}) => ({
MeQuery: {
me: {
readOnly,
isTeacher: true,
selectedClass: {
id: SELECTED_CLASS_ID,
readOnly: classReadOnly,
},
},
},
RoomsQuery: {
rooms: [{
id: '',
slug: '',
title: 'some room',
entryCount: 3,
appearance: 'red',
description: 'some description',
schoolClass: {
id: SELECTED_CLASS_ID,
name: 'bla',
},
}],
},
});
const checkRoomsReadOnly = ({editable, readOnly, classReadOnly = false}) => {
const operations = getOperations({readOnly, classReadOnly});
cy.mockGraphqlOps({
operations,
});
const exist = editable ? 'exist' : 'not.exist';
cy.visit('rooms');
cy.log('visit');
cy.get('.room-widget').should('exist');
cy.getByDataCy('add-room').should(exist);
cy.getByDataCy('widget-footer').should(exist);
};
beforeEach(() => {
cy.setup();
});
it('can edit room', () => {
checkRoomsReadOnly({editable: true, readOnly: false});
});
it('can not edit room', () => {
checkRoomsReadOnly({editable: false, readOnly: true});
});
it('can not edit room of inactive class', () => {
checkRoomsReadOnly({editable: false, readOnly: false, classReadOnly: true});
});
});

View File

@ -1,70 +0,0 @@
import mocks from '../../../fixtures/mocks';
const selectedClassName = 'My Class';
const getOperations = ({readOnly}) => ({
MeQuery: {
me: {
readOnly,
isTeacher: true,
},
},
MySchoolClassQuery: {
me: {
readOnly,
isTeacher: true,
selectedClass: {
name: selectedClassName,
code: 'XXXX',
members: [
{
id: 'id',
firstName: 'Me',
lastName: 'Myson',
isTeacher: true,
active: true,
isMe: true,
},
],
},
},
},
});
const checkSchoolClassTeamReadOnly = (readOnly) => {
cy.mockGraphqlOps({
operations: getOperations({readOnly}),
});
const exist = readOnly ? 'not.exist' : 'exist';
cy.visit('me/class');
cy.getByDataCy('group-list-name').should('exist').should('contain', selectedClassName);
cy.getByDataCy('show-code-button').should(exist);
cy.getByDataCy('edit-group-name-link').should(exist);
cy.openSidebar();
cy.getByDataCy('class-selection').click();
cy.getByDataCy('current-class-name').should('exist');
cy.getByDataCy('create-class-link').should(exist);
cy.getByDataCy('my-team-link').should(exist);
};
describe('School Class and Team Management - Read only', () => {
beforeEach(() => {
cy.fakeLogin('rachel.green', 'test');
cy.server();
cy.task('getSchema').then(schema => {
cy.mockGraphql({
schema,
mocks,
});
});
});
it('can see menu items', () => {
checkSchoolClassTeamReadOnly(false);
});
it('can not see menu items', () => {
checkSchoolClassTeamReadOnly(true);
});
});

View File

@ -1,82 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
describe('Article page', () => {
const slug = 'this-article-has-a-slug';
const roomEntry = {
slug,
id: 'room-entry-id',
title: 'Some Room Entry, yay!',
comments: [],
contents: [{
type: 'text_block',
value: {
text: 'Ein Text',
},
}, {
type: 'subtitle',
value: {
text: 'Ein Untertitel'
}
}],
};
const operations = {
MeQuery: getMinimalMe({}),
RoomEntryQuery: {
roomEntry,
},
AddComment({input}) {
return {
addComment: {
success: true,
comment: {
text: input.comment,
roomEntry: roomEntry,
owner: {
firstName: 'Matt',
lastName: 'Damon',
},
},
},
};
},
};
beforeEach(() => {
cy.setup();
});
it('shows the article with contents', () => {
cy.mockGraphqlOps({
operations,
});
cy.visit(`/article/${slug}`);
cy.getByDataCy('text-block').should('contain.text', 'Ein Text');
cy.getByDataCy('subtitle-block').should('contain.text', 'Ein Untertitel');
});
it('goes to article and leaves a comment', () => {
cy.mockGraphqlOps({
operations,
});
const commentText = 'First! ';
const emoji = '🖐';
cy.visit(`/article/${slug}`);
cy.getByDataCy('comment-textarea').type(commentText);
cy.getByDataCy('emoji-button').should('have.length', 9).first().click();
cy.getByDataCy('submit-comment').should('contain', 'Kommentar teilen').click();
cy.getByDataCy('comment').first().should('contain', commentText + emoji);
});
it('does not show input field on mobile', () => {
cy.mockGraphqlOps({
operations,
});
cy.viewport('iphone-8');
cy.visit(`/article/${slug}`);
cy.getByDataCy('article-title').should('exist');
cy.getByDataCy('comment-textarea').should('not.be.visible');
});
});

View File

@ -1,403 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
describe('The Room Page (Teacher)', () => {
const MeQuery = getMinimalMe();
const selectedClass = MeQuery.me.selectedClass;
const entryText = 'something should be here';
const entryTitle = 'some title';
const slug = 'ein-historisches-festival';
const id = btoa('RoomNode:1');
const room = {
id,
slug,
schoolClass: selectedClass,
restricted: false,
roomEntries: {
edges: [],
},
};
const RoomEntriesQuery = {
room,
};
const operations = {
MeQuery,
RoomEntriesQuery,
AddRoomEntry: {
addRoomEntry: {
roomEntry: {
title: entryTitle,
contents: [
{
type: 'text_block',
value: {
text: entryText,
},
},
],
author: {
firstName: 'Rachel',
lastName: 'Green',
id: btoa('PublicUserNode:rachels-id'),
},
},
errors: [],
},
},
};
const checkRadioButton = () => {
cy.get('.base-input-container__input:checked + .base-input-container__radiobutton svg').should('have.length', 1);
};
beforeEach(() => {
cy.setup();
});
it('displays new room entry with author name', () => {
cy.mockGraphqlOps({
operations,
});
cy.visit(`/room/${slug}`);
cy.getByDataCy('add-room-entry-button').click();
cy.getByDataCy('add-content-link').first().click();
cy.getByDataCy('choose-text-widget').click();
cy.getByDataCy('input-with-label-input').type(entryTitle);
cy.get('.tip-tap__editor').type(entryText);
cy.getByDataCy('save-button').click();
cy.get('.room-entry__content:first').should('contain', entryText).should('contain', 'Rachel Green');
});
// todo: re-enable once cypress can do it correctly
it.skip('changes visibility of a room', () => {
const MeQuery = getMinimalMe({
isTeacher: true,
});
const operations = {
MeQuery,
RoomEntriesQuery,
UpdateRoomVisibility: {
updateRoomVisibility: {
success: true,
room: {
...room,
restricted: true,
},
},
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit(`/room/${slug}`);
cy.getByDataCy('room-visibility-status').should('contain', 'alle Lernenden');
cy.getByDataCy('toggle-more-actions-menu').click();
cy.getByDataCy('change-visibility').click();
cy.getByDataCy('modal-title').should('contain', 'Sichtbarkeit anpassen');
cy.get('.change-visibility__radio').should('have.length', 2);
cy.get('.change-visibility__radio--selected').should('have.length', 1);
checkRadioButton();
cy.get('.change-visibility__radio--selected').should('have.length', 1).should('contain', 'alle Lernenden');
checkRadioButton();
cy.getByDataCy('select-option').eq(0).click();
cy.get('.change-visibility__radio--selected').should('have.length', 1);
checkRadioButton();
cy.getByDataCy('select-option').eq(1).click();
cy.getByDataCy('select-option').eq(1).click();
cy.get('.change-visibility__radio--selected').should('have.length', 1).should('contain', 'eigenen Beiträge');
checkRadioButton();
cy.getByDataCy('modal-save-button').click();
cy.getByDataCy('room-visibility-status').should('contain', 'eigenen Beiträge');
cy.getByDataCy('toggle-more-actions-menu').click();
cy.getByDataCy('change-visibility').click();
cy.getByDataCy('modal-title').should('contain', 'Sichtbarkeit anpassen');
cy.get('.change-visibility__radio--selected').should('have.length', 1).should('contain', 'eigenen Beiträge');
checkRadioButton();
});
it('deletes the room and goes back to the overview', () => {
const MeQuery = getMinimalMe();
const schoolClass = MeQuery.me.selectedClass;
const roomToDelete = {
id: btoa('RoomNode:room-to-delete'),
schoolClass,
slug: 'delete-me',
roomEntries: {
edges: [],
},
};
const otherRoom = {
id: btoa('RoomNode:otherRoom'),
slug: 'other-slug',
schoolClass,
};
let rooms = [roomToDelete, otherRoom];
const operations = {
MeQuery,
RoomsQuery() {
return {
rooms,
};
},
RoomEntriesQuery: {
room: roomToDelete,
},
DeleteRoom: {
deleteRoom: {
success: true,
},
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit(`/rooms`);
cy.getByDataCy('room-widget').should('have.length', 2);
cy.getByDataCy('room-widget').first().click();
cy.getByDataCy('toggle-more-actions-menu').click();
cy.getByDataCy('delete-room').within(() => {
cy.get('a').click();
});
cy.getByDataCy('modal-save-button').click();
cy.url().should('include', 'rooms');
cy.getByDataCy('room-widget').should('have.length', 1);
});
it('changes class while on room page', () => {
const {me} = MeQuery;
const otherClass = {
id: btoa('SchoolClassNode:34'),
name: 'Other Class',
readOnly: false,
};
let selectedClass = me.selectedClass;
const operations = {
MeQuery: () => {
return {
me: {
...me,
schoolClasses: [...me.schoolClasses, otherClass],
selectedClass,
},
};
},
RoomEntriesQuery,
UpdateSettings() {
selectedClass = otherClass;
return {
updateSettings: {
success: true,
},
};
},
ModuleDetailsQuery: {},
MySchoolClassQuery: () => {
return {
me: {
selectedClass,
},
};
},
RoomsQuery: {
rooms: [],
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit(`/room/${slug}`);
cy.getByDataCy('room-title').should('contain', 'A Room');
cy.selectClass('Other Class');
cy.url().should('include', 'rooms');
cy.getByDataCy('current-class-name').should('contain', 'Other Class');
});
});
describe('The Room Page (student)', () => {
const slug = 'ein-historisches-festival';
const MeQuery = getMinimalMe({isTeacher: false});
const {me} = MeQuery;
const id = atob(me.id).split(':')[1];
const authorId = btoa(`PublicUserNode:${id}`);
const entrySlug = 'entry-slug';
const {selectedClass} = me;
const roomEntry = {
id: 'entry-id',
slug: entrySlug,
title: 'My Entry',
contents: [
{
type: 'text_block',
value: {
text: 'some text',
},
},
],
comments: [{}, {}],
author: {
...me,
id: authorId,
firstName: 'Hans',
lastName: 'Was Heiri',
avatarUrl: '',
},
};
const room = {
id,
slug,
schoolClass: selectedClass,
restricted: false,
roomEntries: {
edges: [{
node: roomEntry,
}],
},
};
const RoomEntriesQuery = {
room,
};
beforeEach(() => {
cy.setup();
});
it('room actions should not exist for student', () => {
const operations = {
MeQuery: getMinimalMe({isTeacher: false}),
RoomEntriesQuery,
};
cy.mockGraphqlOps({
operations,
});
cy.visit(`/room/${slug}`);
cy.getByDataCy('room-title').should('exist');
cy.getByDataCy('room-actions').should('not.exist');
});
it('creates a room entry', () => {
const MeQuery = getMinimalMe({isTeacher: false});
const room = {
id: 'some-room',
roomEntries: {
edges: [],
},
};
const operations = {
MeQuery,
RoomEntriesQuery: {
room,
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit(`/room/${slug}`);
cy.getByDataCy('add-room-entry-button').click();
cy.getByDataCy('content-form-section-title').should('have.text', 'Titel (Pflichtfeld)');
});
it('edits own room entry', () => {
const room = {
id: 'some-room',
slug,
// schoolClass: me.selectedClass,
roomEntries: {
edges: [
{
node: roomEntry,
},
],
},
};
const operations = {
MeQuery: MeQuery,
RoomEntriesQuery: {
room,
},
RoomEntryQuery: {
roomEntry,
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit(`/room/${slug}`);
cy.getByDataCy('room-entry-actions').click();
cy.getByDataCy('edit-room-entry').click();
cy.location('pathname').should('include', entrySlug);
});
it('deletes room entry', () => {
const DeleteRoomEntry = {
deleteRoomEntry: {
success: true,
errors: null,
roomSlug: slug,
},
};
const operations = {
MeQuery,
RoomEntriesQuery,
DeleteRoomEntry,
};
cy.mockGraphqlOps({
operations,
});
cy.visit(`/room/${slug}`);
cy.getByDataCy('room-entry').should('have.length', 1);
cy.getByDataCy('room-entry-actions').click();
cy.getByDataCy('delete-room-entry').click();
cy.getByDataCy('delete-room-entry').should('not.exist');
cy.getByDataCy('modal-save-button').click();
cy.getByDataCy('room-entry').should('have.length', 0);
});
it('shows room entries with comment count', () => {
const operations = {
MeQuery,
RoomEntriesQuery,
};
cy.mockGraphqlOps({
operations,
});
cy.visit(`/room/${slug}`);
cy.getByDataCy('room-entry').should('have.length', 1).within(() => {
cy.getByDataCy('entry-count').should('contain.text', '2');
});
});
it('does not show actions on mobile', () => {
const operations = {
MeQuery,
RoomEntriesQuery,
};
cy.mockGraphqlOps({
operations,
});
cy.viewport('iphone-8');
cy.visit(`/room/${slug}`);
cy.getByDataCy('room-actions').should('not.exist');
cy.getByDataCy('room-entry').should('have.length', 1);
cy.getByDataCy('room-entry-actions').should('not.be.visible');
});
});

View File

@ -1,127 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
import {SELECTED_CLASS_ID_ENCODED} from '../../../fixtures/mocks';
describe('The Rooms Page', () => {
const getOperations = (isTeacher) => ({
MeQuery: getMinimalMe({isTeacher}),
RoomsQuery: {
rooms: [{
schoolClass: {
id: SELECTED_CLASS_ID_ENCODED,
},
}],
},
});
const getOnboardingOperations = (isTeacher) => {
const operations = getOperations(isTeacher);
return {
...operations,
RoomsQuery: {
rooms: [],
},
};
};
beforeEach(() => {
cy.setup();
});
it('shows the onboarding page', () => {
cy.mockGraphqlOps({
operations: getOnboardingOperations(true),
});
cy.visit('/rooms');
cy.getByDataCy('page-title').should('contain', 'Räume');
cy.getByDataCy('rooms-onboarding-text').should('contain', 'Hier können Sie Räume erstellen');
cy.getByDataCy('page-footer').should('not.exist');
cy.getByDataCy('create-room-button').should('contain', 'Raum erstellen').click();
cy.url().should('include', 'new-room');
});
it('shows the onboarding page without button for student', () => {
cy.mockGraphqlOps({
operations: getOnboardingOperations(false),
});
cy.visit('/rooms');
cy.getByDataCy('page-title').should('contain', 'Räume');
cy.getByDataCy('rooms-onboarding-text').should('contain', 'Hier können Sie Räume erstellen');
cy.getByDataCy('page-footer').should('not.exist');
cy.getByDataCy('create-room-button').should('not.exist');
});
it('goes to the rooms page', () => {
const operations = getOperations(true);
cy.mockGraphqlOps({
operations,
});
cy.visit('/rooms');
cy.getByDataCy('room-widget').should('have.length', 1);
cy.get('[data-cy=add-room]').should('exist');
});
it('actions should not exist for student', () => {
const operations = getOperations(false);
cy.mockGraphqlOps({
operations,
});
cy.visit('/rooms');
cy.getByDataCy('room-widget').should('have.length', 1);
cy.getByDataCy('toggle-more-actions-menu').should('not.exist');
});
it('adds a room as teacher', () => {
const MeQuery = getMinimalMe({isTeacher: true});
const getRoom = (title, appearance, description) => {
let id = title.toLowerCase().replace(' ', '-');
return {
id,
slug: id,
title: title,
entryCount: 3,
appearance: appearance,
description: description,
schoolClass: MeQuery.me.selectedClass
};
};
let rooms = [
getRoom('First Room', 'blue', 'Some description')
];
const operations = {
MeQuery,
RoomsQuery() {
return {
rooms
};
},
AddRoom({input: {room: {title, appearance, description}}}) {
const room = getRoom(title, appearance, description);
rooms.push(room);
return {
addRoom: {
room,
},
};
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit('/rooms');
cy.getByDataCy('room-widget').should('have.length', 1);
cy.getByDataCy('add-room').click();
cy.getByDataCy('form-title').should('contain', 'Neuer Raum');
cy.getByDataCy('page-form-input-titel').type('Strg F');
cy.getByDataCy('school-class-select').should('not.exist');
cy.getByDataCy('color-select').eq(2).click();
cy.getByDataCy('room-form-save').click();
cy.getByDataCy('room-widget').should('have.length', 2);
});
});

View File

@ -1,151 +0,0 @@
import module from '../../fixtures/module.minimal';
const spellCheck = require('../../fixtures/spell-check.json');
const operations = {
MeQuery: {
me: {
permissions: [],
readOnly: false,
},
},
AssignmentQuery: {
assignment: {
id: '',
title: 'Ein Auftragstitel',
assignment: 'Ein Auftrag',
submission: {
id: 'U3R1ZGVudFN1Ym1pc3Npb25Ob2RlOjE=',
text: 'Hir ist ein Feler gewesen',
final: false,
document: '',
submissionFeedback: {
'id': 'U3VibWlzc2lvbkZlZWRiYWNrTm9kZTox',
'text': '\ud83d\ude42\ud83d\ude10\ud83e\udd2c\ud83d\udc4d\ud83e\udd22\ud83e\udd22\ud83e\udd22\ud83e\udd22\ud83d\ude2e\ud83e\udd17',
'teacher': {
'firstName': 'Nico',
'lastName': 'Zickgraf',
'__typename': 'UserNode',
},
},
},
},
},
ModuleDetailsQuery: {
module: {
...module,
assignments: [
{
'id': 'QXNzaWdubWVudE5vZGU6MQ==',
'title': 'Ein Auftragstitel',
'assignment': 'Ein Auftrag',
'solution': null,
'submission': {
'id': 'U3R1ZGVudFN1Ym1pc3Npb25Ob2RlOjE=',
'text': 'Hir ist ein Feler gewesen',
'final': false,
'document': '',
'submissionFeedback': {
'id': 'U3VibWlzc2lvbkZlZWRiYWNrTm9kZTox',
'text': '🙂😐🤬👍🤢🤢🤢🤢😮🤗',
'teacher': {
'firstName': 'Nico',
'lastName': 'Zickgraf',
'__typename': 'UserNode',
},
'__typename': 'SubmissionFeedbackNode',
},
'__typename': 'StudentSubmissionNode',
},
'__typename': 'AssignmentNode',
},
],
chapters: [
{
'id': 'Q2hhcHRlck5vZGU6MTg=',
'title': '1.1 Lehrbeginn',
'description': 'Wie sieht Ihr Konsumverhalten aus?',
'bookmark': {
'note': {
'id': 'Tm90ZU5vZGU6Mg==',
'text': 'Chapter Chapter',
'__typename': 'NoteNode',
},
'__typename': 'ChapterBookmarkNode',
},
contentBlocks: [
{
'id': 'Q29udGVudEJsb2NrTm9kZToxOQ==',
'slug': 'assignment',
'title': 'Assignment',
'type': 'NORMAL',
'contents': [
{
'type': 'assignment',
'value': {
'title': 'Ein Auftragstitel',
'assignment': 'Ein Auftrag',
'id': 'QXNzaWdubWVudE5vZGU6MQ==',
},
'id': 'df8212ee-3e82-49fa-977e-c4b60789163e',
},
],
'userCreated': false,
'mine': false,
'bookmarks': [
{
'uuid': 'df8212ee-3e82-49fa-977e-c4b60789163e',
'note': {
'id': 'Tm90ZU5vZGU6Mw==',
'text': 'Noch eine Notiz',
'__typename': 'NoteNode',
},
'__typename': 'ContentBlockBookmarkNode',
},
],
'hiddenFor': [],
'visibleFor': [],
'__typename': 'ContentBlockNode',
},
],
},
],
},
},
SpellCheck: {
spellCheck,
},
UpdateAssignment: {
updateAssignment: {
assignment: {
id: '',
title: 'title',
assignment: '',
solution: '',
},
},
},
UpdateLastModule: {
updateLastModule: {
lastModule: {},
},
},
};
describe('Spellcheck', () => {
beforeEach(() => {
cy.setup();
cy.mockGraphqlOps({
operations,
});
});
// todo: unskip me
it('should highlight three errors', () => {
cy.visit('/module/lohn-und-budget/');
cy.getByDataCy('spellcheck-correction').should('have.length', 0);
cy.getByDataCy('spellcheck-button').click();
cy.getByDataCy('spellcheck-correction').should('have.length', 3);
});
});

View File

@ -1,68 +0,0 @@
const module = require('../../fixtures/module.json');
describe('Survey', () => {
beforeEach(() => {
cy.setup();
});
it('should display and fill out the survey', () => {
let answer = null;
cy.mockGraphqlOps({
operations: {
MeQuery: {
me: {
permissions: [],
}
},
ModuleQuery: variables => ({module}),
SurveyQuery: () => ({
survey: {
id: 'U3VydmV5Tm9kZTox',
title: 'Test',
data: '{"pages": [{"name": "Seite 1", "elements": [{"name": "Fall 1", "type": "panel", "title": "Fall 1", "elements": [{"name": "A: Max gibt ihr das Geld und muss das Billardspiel absagen.", "type": "text", "placeHolder": "Passende Tugenden erfassen...", "correctAnswer": "Triss"}, {"name": "question2", "type": "text", "title": "B: Max gibt ihr das Geld nicht und geht Billard spielen.", "placeHolder": "Passende Tugenden erfassen...", "correctAnswer": "Jaskier"}], "description": "Max hat Ende Monat noch Fr. 20.\\u2013 \\u00fcbrig, die er gespart hat, um mit seinem besten Kumpel, der ein halbes Jahr im Ausland verweilte, Billard spielen zu gehen. Doch dann bittet ihn seine j\\u00fcngere Schwester um Geld. Sie hat ein unverhofftes Date mit einem jungen Mann, in den sie sich bereits vor Monaten unsterblich verliebt hat. Leider ist ihr Kontostand aber bereits auf Null."}]}, {"name": "Seite 2", "elements": [{"name": "panel1", "type": "panel", "title": "Fall 2", "elements": [{"name": "question1", "type": "text", "title": "A: Silvio bringt seinen Mitfahrer in Sicherheit.", "placeHolder": "Passende Tugenden erfassen...", "correctAnswer": "Yennefer", "useDisplayValuesInTitle": false}, {"name": "question3", "type": "text", "title": "B: Silvio sperrt die Strasse ab.", "placeHolder": "Passende Tugenden erfassen...", "correctAnswer": "Geralt"}], "description": "Auf der Autobahn brennt ein Lastwagen, der jederzeit explodieren kann. Silvio, dem Fahrer, bleiben nur noch wenige Minuten: Entweder bringt er seinen ohnm\\u00e4chtig gewordenen Mitfahrer in Sicherheit oder er sperrt die Strasse ab, die nach wie vor dicht befahren wird."}]}], "completeText": "Abschliessen", "showQuestionNumbers": "off"}',
module: {
id: 'TW9kdWxlTm9kZToxNw==',
__typename: 'ModuleNode'
},
answer,
__typename: 'SurveyNode'
},
}),
UpdateAnswer: variables => {
answer = variables.input.answer;
return {
updateAnswer: {
answer,
__typename: 'UpdateAnswerPayload'
}
};
},
ModuleSolutions: {
module: {
solutionsEnabled: false
}
}
}
});
cy.visit('/survey/U3VydmV5Tm9kZTox');
cy.get('.survey__panel-title').should('contain', 'Fall 1');
cy.get('#sq_100i').type('Wohlwollen');
cy.get('#sq_101i').type('Demut');
cy.get('[value="Speichern & Weiter"]').click();
cy.get('#sq_102i').type('Keuschheit');
cy.get('#sq_103i').type('Geduld');
cy.get('[value=Abschliessen]').click();
cy.visit('/survey/U3VydmV5Tm9kZTox');
cy.get('#sq_100i').should('have.value', 'Wohlwollen');
});
});

View File

@ -1,5 +0,0 @@
describe('The Home Page', () => {
it('successfully loads', () => {
cy.visit('/')
})
})

View File

@ -1,76 +0,0 @@
import {assertStartPage} from '../../../support/helpers';
describe('Onboarding', () => {
beforeEach(() => {
cy.setup();
});
it('shows the onboarding steps and finishes them', () => {
let onboardingVisited = false;
cy.mockGraphqlOps({
operations: {
MeQuery: () => ({
me: {
onboardingVisited,
},
}),
UpdateOnboardingProgress: () => {
onboardingVisited = true;
return {
updateOnboardingProgress: {
success: true,
},
};
},
NewsTeasers: {}
},
});
cy.visit('/');
assertStartPage(true);
cy.get('[data-cy=onboarding-next-link]').click();
cy.get('[data-cy=onboarding-next-link]').click();
cy.get('[data-cy=onboarding-next-link]').click();
cy.get('[data-cy=onboarding-next-link]').click();
assertStartPage(false);
});
it('shows the onboarding steps and skips them', () => {
let onboardingVisited = false;
cy.mockGraphqlOps({
operations: {
MeQuery: {
me: {
onboardingVisited,
},
},
UpdateOnboardingProgress: () => {
onboardingVisited = true;
return {
updateOnboardingProgress: {
success: true,
},
};
},
},
});
cy.visit('/');
assertStartPage(true);
cy.getByDataCy('onboarding-skip-link').click();
assertStartPage(false);
});
it('does not show the onboarding', () => {
cy.mockGraphqlOps({
operations: {
MeQuery: {
me: {}
}
},
});
cy.visit('/');
assertStartPage(false);
});
});

View File

@ -1,35 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
describe('Sidebar', () => {
beforeEach(() => {
cy.setup();
});
it('should open sidebar and stay open', () => {
const {me} = getMinimalMe({});
const operations = {
MeQuery: {
me: {
...me,
schoolClasses: [...me.schoolClasses, {}],
},
},
ProjectsQuery: {
projects: [],
},
};
cy.mockGraphqlOps({
operations,
});
cy.visit('/portfolio');
cy.getByDataCy('sidebar').should('not.exist');
cy.getByDataCy('user-widget-avatar').click();
cy.getByDataCy('sidebar').should('exist');
cy.getByDataCy('class-selection').click();
cy.getByDataCy('class-selection-entry').should('have.length', 2);
cy.getByDataCy('close-profile-sidebar-link').click();
cy.getByDataCy('sidebar').should('not.exist');
});
});

View File

@ -1,82 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
// const me = require('../../fixtures/me.new-student.json');
describe('New student', () => {
before(() => {
cy.setup();
});
// todo: unskip me
it.skip('shows "Enter Code" page and adds the user to a class', () => {
const {me} = getMinimalMe({isTeacher: false});
let onboardingVisited = false;
let selectedClass;
let schoolClasses = [];
const name = 'KF1A';
const id = 'selectedClassId';
console.log('me', me);
const getSelectedClass = () => {
return selectedClass;
};
const getMe = () => {
return {
...me,
onboardingVisited,
schoolClasses,
selectedClass: getSelectedClass(),
};
};
console.log('getMe()', getMe());
cy.mockGraphqlOps({
operations: {
MeQuery() {
return {
me: getMe(),
};
},
JoinClass() {
console.log('joining class');
selectedClass = {
id,
name,
};
schoolClasses.push(selectedClass);
return {
joinClass: {
success: true,
schoolClass: selectedClass,
},
};
},
MySchoolClassQuery: {
me: getMe(),
},
UpdateOnboardingProgress: () => {
onboardingVisited = true;
return {
updateOnboardingProgress: {
success: true,
},
};
},
},
});
cy.visit('/');
cy.get('[data-cy=join-form-title]').should('contain', 'Einer Klasse beitreten');
cy.get('[data-cy=join-form-input]').type('XXXX');
cy.get('[data-cy=join-form-confirm]').click();
cy.getByDataCy('onboarding-skip-link').click();
cy.get('[data-cy=user-widget-avatar]').click();
cy.get('[data-cy=class-list-link]').click();
cy.get('[data-cy=group-list-title]').should('contain', 'Klassenliste');
});
});

View File

@ -1,396 +0,0 @@
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';
let selectedClass = teacher.selectedClass;
selectedClass.name = 'Some stupid class';
const schoolClasses = [
teacher.selectedClass,
];
const me = () => ({
...teacher,
selectedClass,
schoolClasses,
});
cy.mockGraphqlOps({
operations: {
MeQuery: () => ({
me: me(),
}),
WhateverNode() {
console.log('Through here');
return {};
},
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.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.');
});
});

View File

@ -1,77 +0,0 @@
import {getMinimalMe} from '../../../support/helpers';
import {hasOperationName} from '../../../support/graphql';
const teacher = getMinimalMe();
const mockCreateTeamCall = (name) => {
cy.intercept('POST', '/api/graphql', (req) => {
if (hasOperationName(req, 'CreateTeamMutation')) {
let result;
if (name) {
result = {
__typename: 'TeamNode',
id: 'newTeamId',
name,
code: 'ABC',
members: [],
};
} else {
result = {
__typename: 'DuplicateName',
reason: 'Dieser Name wird bereits verwendet.'
};
}
req.reply({
data: {
createTeam: {
result,
},
},
});
}
});
};
describe('Team', () => {
beforeEach(() => {
cy.setup();
cy.mockGraphqlOps({
operations: {
MeQuery: {
me: {
...teacher,
team: null,
},
},
},
});
});
it('creates a new team', () => {
const name = 'Team Böhmi';
mockCreateTeamCall(name);
cy.visit('/me/team');
cy.getByDataCy('create-team-button').click();
cy.getByDataCy('join-form-input').type(name);
cy.getByDataCy('join-form-confirm').click();
cy.getByDataCy('group-list-name').should('contain', name);
});
it('tries to create team but fails due to duplicate name', () => {
const name = 'Gibt\'s schon';
mockCreateTeamCall(false);
cy.visit('/me/team');
cy.getByDataCy('create-team-button').click();
cy.getByDataCy('join-form-input').type(name);
cy.getByDataCy('join-form-confirm').click();
cy.getByDataCy('join-form-input-error').should('contain', 'Dieser Name wird bereits verwendet.');
});
});

View File

@ -138,10 +138,28 @@ Cypress.Commands.add('setup', () => {
cy.mockGraphql();
});
const typenameResolver = {
__resolveType(obj, context, info) {
return obj.__typename;
}
};
Cypress.Commands.add('mockGraphql', (options?: any) => {
cy.task('getSchema').then(schemaString => {
const schema = makeExecutableSchema({typeDefs: schemaString});
const schemaWithMocks = addMocksToSchema({schema, mocks});
cy.task('getSchema').then(( schemaString: string ) => {
const resolverMap = {
DeleteSnapshotResult: typenameResolver,
UpdateSnapshotResult: typenameResolver
};
const schema = makeExecutableSchema({
typeDefs: schemaString,
resolvers: resolverMap
});
const schemaWithMocks = addMocksToSchema({
schema,
mocks,
preserveResolvers: true
});
let currentOperations = options && options.operations ? options.operations : {};

View File

@ -1,14 +1,18 @@
<template>
<div class="snapshot">
<header class="snapshot__header">
<header
class="snapshot__header"
>
<snapshot-header
:snapshot="snapshot"
v-if="snapshot"
/>
</header>
<module
:module="snapshot"
class="snapshot__module"
v-if="module"
/>
</div>
</template>