From bfb6a6e7a08b21ce48091030fee6f40a9de29f75 Mon Sep 17 00:00:00 2001 From: Ramon Wenger Date: Thu, 29 Sep 2022 16:39:33 +0200 Subject: [PATCH] Update cypress typescript support --- client/cypress.frontend.ts | 4 +- client/cypress/support/commands.ts | 142 ++++++++++++++++++++++ client/cypress/support/{e2e.js => e2e.ts} | 0 client/cypress/support/index.d.ts | 24 ---- client/cypress/tsconfig.json | 2 +- 5 files changed, 145 insertions(+), 27 deletions(-) create mode 100644 client/cypress/support/commands.ts rename client/cypress/support/{e2e.js => e2e.ts} (100%) diff --git a/client/cypress.frontend.ts b/client/cypress.frontend.ts index 42bbeedc..29927148 100644 --- a/client/cypress.frontend.ts +++ b/client/cypress.frontend.ts @@ -6,8 +6,8 @@ export default defineConfig({ chromeWebSecurity: false, e2e: { baseUrl: "http://localhost:8080", - specPattern: 'cypress/e2e/frontend/**/*.spec.{js,ts}', - supportFile: 'cypress/support/e2e.js', + specPattern: 'cypress/e2e/frontend/**/*.{cy,spec}.{js,ts}', + supportFile: 'cypress/support/e2e.ts', setupNodeEvents(on, config) { on('task', { getSchema() { diff --git a/client/cypress/support/commands.ts b/client/cypress/support/commands.ts new file mode 100644 index 00000000..c38e2449 --- /dev/null +++ b/client/cypress/support/commands.ts @@ -0,0 +1,142 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +declare global { + namespace Cypress { + interface Chainable { + /** + * Login via API call to the GraphQL endpoint, without calling the frontend. Faster than the other login. + * @param username + * @param password + * @example + * cy.apolloLogin('ross.geller', 'test') + */ + apolloLogin(username: string, password: string): Chainable + + /** + * Selects an element based on the `data-cy=xxx` attribute + * @param selector - The value of the data-cy attribute to select + * @example + * cy.getByDataCy('my-new-button') + */ + getByDataCy(selector: string): Chainable + + selectClass(schoolClass: string): void + + login(username: string, password: string, visitLogin?: boolean): void + + fakeLogin(username: string, password: string): void + + isSubmissionReadOnly(myText: string): void + + openSidebar(): void + + setup(): void + } + } +} +// installed a fork of the original package, because of this issue: +// https://github.com/tgriesser/cypress-graphql-mock/issues/23 +// todo: once above issue is fixed, go back to the original repo -> npm install cypress-graphql-mock +// import 'cypress-graphql-mock'; +import '@iam4x/cypress-graphql-mock'; +import mocks from '../fixtures/mocks'; + +Cypress.Commands.add('apolloLogin', (username, password) => { + const payload = { + 'operationName': 'BetaLogin', + 'variables': { + 'input': { + 'usernameInput': username, + 'passwordInput': password, + }, + }, + 'query': 'mutation BetaLogin($input: BetaLoginInput!) {\n betaLogin(input: $input) {\n success\n __typename\n }\n}\n', + }; + + cy.request({ + method: 'POST', + url: '/api/graphql-public/', + body: payload, + }); +}); + +// todo: replace with apollo call +Cypress.Commands.add('login', (username, password, visitLogin = false) => { + if (visitLogin) { + cy.visit('/beta-login'); + } + + if (username !== '') { + cy.get('[data-cy=email-input]').type(username); + } + + if (password !== '') { + cy.get('[data-cy=password-input]').type(password); + } + cy.get('[data-cy=login-button]').click(); +}); + + +Cypress.Commands.add('getByDataCy', (selector: string) => { + return cy.get(`[data-cy=${selector}]`); +}); + +Cypress.Commands.add('selectClass', (schoolClass) => { + cy.getByDataCy('user-widget-avatar').click(); + cy.getByDataCy('class-selection').click(); + cy.getByDataCy('class-selection-entry').contains(schoolClass).click(); +}); + +Cypress.Commands.add('fakeLogin', () => { + cy.log('Logging in (fake)'); + cy.setCookie('loginStatus', 'true'); +}); + +Cypress.Commands.add('isSubmissionReadOnly', (myText) => { + cy.get('.submission-form__textarea--readonly').as('textarea'); + + cy.get('@textarea').invoke('val').should('contain', myText); + cy.get('@textarea').should('have.attr', 'readonly'); + cy.getByDataCy('submission-form-submit').should('not.exist'); +}); + +Cypress.Commands.add('openSidebar', () => { + cy.getByDataCy('user-widget-avatar').click(); +}); + +Cypress.Commands.add('setup', () => { + cy.fakeLogin('nino.teacher', 'test'); + cy.server(); + cy.viewport('macbook-15'); + cy.task('getSchema').then((schema: string) => { + cy.mockGraphql({ + schema, + mocks, + }); + }); +}); diff --git a/client/cypress/support/e2e.js b/client/cypress/support/e2e.ts similarity index 100% rename from client/cypress/support/e2e.js rename to client/cypress/support/e2e.ts diff --git a/client/cypress/support/index.d.ts b/client/cypress/support/index.d.ts index 254a699d..5e41a64a 100644 --- a/client/cypress/support/index.d.ts +++ b/client/cypress/support/index.d.ts @@ -1,33 +1,9 @@ // Intellisense for custom Commands: https://github.com/cypress-io/cypress-example-todomvc#cypress-intellisense declare namespace Cypress { interface Chainable { - /** - * Login via API call to the GraphQL endpoint, without calling the frontend. Faster than the other login. - * @param username - * @param password - * @example - * cy.apolloLogin('ross.geller', 'test') - */ - apolloLogin(username: string, password: string): Chainable - /** - * Selects an element based on the `data-cy=xxx` attribute - * @param selector - The value of the data-cy attribute to select - * @example - * cy.getByDataCy('my-new-button') - */ - getByDataCy(selector: string): Chainable - selectClass(schoolClass: string): void - login(username: string, password: string, visitLogin?: boolean): void - fakeLogin(username: string, password: string): void - - isSubmissionReadOnly(myText: string): void - - openSidebar(): void - - setup(): void } } diff --git a/client/cypress/tsconfig.json b/client/cypress/tsconfig.json index f87a578b..18edb199 100644 --- a/client/cypress/tsconfig.json +++ b/client/cypress/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "es5", "lib": ["es5", "dom"], - "types": ["cypress"] + "types": ["cypress", "node"] }, "include": ["**/*.ts"] }