diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 30ef05f6..a30d1e78 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -69,75 +69,73 @@ unit: coverage_format: cobertura path: coverage/cobertura-coverage.xml -# Disabled until redesign is settled -# -# .e2e-chrome: -# image: cypress/browsers:node14.19.0-chrome100-ff99-edge -# stage: test -# script: -# - npm run e2e -- --watch=false --headless=true --browser=chrome -# artifacts: -# when: on_failure -# paths: -# - cypress/videos -# - cypress/screenshots -# -# .e2e-firefox: -# image: cypress/browsers:node14.19.0-chrome100-ff99-edge -# stage: test -# script: -# - npm run e2e -- --watch=false --headless=true --browser=firefox -# artifacts: -# when: on_failure -# paths: -# - cypress/videos -# - cypress/screenshots -# -# ui-chrome: -# extends: .e2e-chrome -# rules: -# - if: $CI_PIPELINE_SOURCE == "merge_request_event" -# when: never -# - if: ($CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME == "master") -# when: always -# allow_failure: false -# - if: ($CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master") -# when: never -# -# ui-firefox: -# extends: .e2e-firefox -# rules: -# - if: $CI_PIPELINE_SOURCE == "merge_request_event" -# when: never -# - if: ($CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME == "master") -# when: always -# allow_failure: false -# - if: ($CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master") -# when: never -# -# e2e-chrome: -# extends: .e2e-chrome -# stage: ui test -# rules: -# - if: $CI_PIPELINE_SOURCE == "merge_request_event" -# when: never -# - if: ($CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME == "master") -# when: never -# - if: ($CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master") -# when: manual -# allow_failure: false -# -# e2e-firefox: -# extends: .e2e-firefox -# stage: ui test -# rules: -# - if: $CI_PIPELINE_SOURCE == "merge_request_event" -# when: never -# - if: ($CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME == "master") -# when: never -# - if: ($CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master") -# when: manual -# allow_failure: false +.e2e-chrome: + image: cypress/browsers:node14.19.0-chrome100-ff99-edge + stage: test + script: + - npm run e2e -- --watch=false --headless=true --browser=chrome + artifacts: + when: on_failure + paths: + - cypress/videos + - cypress/screenshots + +.e2e-firefox: + image: cypress/browsers:node14.19.0-chrome100-ff99-edge + stage: test + script: + - npm run e2e -- --watch=false --headless=true --browser=firefox + artifacts: + when: on_failure + paths: + - cypress/videos + - cypress/screenshots + +ui-chrome: + extends: .e2e-chrome + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: never + - if: ($CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME == "master") + when: always + allow_failure: false + - if: ($CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master") + when: never + +ui-firefox: + extends: .e2e-firefox + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: never + - if: ($CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME == "master") + when: always + allow_failure: false + - if: ($CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master") + when: never + +e2e-chrome: + extends: .e2e-chrome + stage: ui test + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: never + - if: ($CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME == "master") + when: never + - if: ($CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master") + when: manual + allow_failure: false + +e2e-firefox: + extends: .e2e-firefox + stage: ui test + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: never + - if: ($CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME == "master") + when: never + - if: ($CI_COMMIT_REF_NAME != "develop" && $CI_COMMIT_REF_NAME != "master") + when: manual + allow_failure: false audit: stage: test diff --git a/cypress/integration/catalog.spec.ts b/cypress/integration/catalog.spec.ts index 5163294a..0eeabd29 100644 --- a/cypress/integration/catalog.spec.ts +++ b/cypress/integration/catalog.spec.ts @@ -28,21 +28,4 @@ describe('catalog', function () { .should('contain', 'Studium der Pflichtfächer (1. bis 5. Semester)'); }); }); - - it('should have default back nav', function () { - cy.visit('/data-detail/ae3cf884-4dc4-526b-9213-6850135591ab'); - cy.intercept('POST', 'https://mobile.server.uni-frankfurt.de/search', { - fixture: 'search/types/catalog/catalog-1.json', - }); - cy.get('h1').should( - 'contain', - 'Studium der Pflichtfächer (1. bis 5. Semester)', - ); - - cy.intercept('POST', 'https://mobile.server.uni-frankfurt.de/search', { - fixture: 'search/types/catalog/catalog-2.json', - }); - cy.get('.show-back-button').click(); - cy.get('h1').should('contain', 'FB 1 - Rechtswissenschaft'); - }); }); diff --git a/cypress/integration/context-menu.spec.ts b/cypress/integration/context-menu.spec.ts index d73b20c0..56325b8d 100644 --- a/cypress/integration/context-menu.spec.ts +++ b/cypress/integration/context-menu.spec.ts @@ -26,9 +26,9 @@ describe('context menu', function () { fixture: 'search/multi-result.json', }, ); - cy.get('ion-searchbar').type('test{enter}'); + cy.get('ion-searchbar').type('test'); cy.wait('@search'); - cy.get('ion-buttons').last().find('ion-menu-button').click(); + cy.get('ion-searchbar > ion-menu-button').click(); }); it('should sort', function () { diff --git a/cypress/integration/favorites.spec.ts b/cypress/integration/favorites.spec.ts index 511c3744..addb9521 100644 --- a/cypress/integration/favorites.spec.ts +++ b/cypress/integration/favorites.spec.ts @@ -15,13 +15,17 @@ describe('favorites', function () { it('should add a favorite', function () { + cy.intercept('POST', 'https://mobile.server.uni-frankfurt.de/search', { + fixture: 'search/test.json', + }).as('search'); + cy.visit('/search'); cy.get('ion-searchbar').type('test'); let text!: string; cy.get('stapps-data-list-item') .first() .within(() => { - cy.get('h2') + cy.get('.title') .invoke('text') .then(it => { text = it; @@ -30,7 +34,7 @@ describe('favorites', function () { }); cy.visit('/favorites'); cy.get('stapps-data-list-item').within(() => { - cy.get('h2').should('contain', text); + cy.get('.title').should('contain', text); cy.get('stapps-favorite-button').click(); }); cy.get('stapps-data-list').contains('Keine Ergebnisse'); diff --git a/cypress/integration/ical.spec.ts b/cypress/integration/ical.spec.ts index 2834b3d0..9dbe7470 100644 --- a/cypress/integration/ical.spec.ts +++ b/cypress/integration/ical.spec.ts @@ -29,7 +29,7 @@ describe('ical', function () { it('should export a single event', function () { cy.visit('/search'); - cy.get('ion-searchbar').click().type('test{enter}'); + cy.get('ion-searchbar').click().type('test'); cy.contains('ion-item', 'UNIcert (Test)') .contains('ion-chip', 'Termine Auswählen') .click(); diff --git a/cypress/integration/news.spec.ts b/cypress/integration/news.spec.ts index 71db7b96..c0506be2 100644 --- a/cypress/integration/news.spec.ts +++ b/cypress/integration/news.spec.ts @@ -1,16 +1,16 @@ /* * Copyright (C) 2022 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ describe('news', function () { @@ -28,6 +28,7 @@ describe('news', function () { it('should have infinite scroll', function () { cy.visit('/news'); cy.get('stapps-news-item').should('have.length', 6); + cy.wait(500); cy.get('stapps-news-page > ion-content') .shadow() .find('main') @@ -49,7 +50,7 @@ describe('news', function () { }).as('search'); cy.visit('/data-detail/c90c7d30-410f-5aea-a67b-ea1f98929b93'); cy.contains('ion-card', 'Ursprünglicher Link') - .find('ion-icon[name="open-outline"]') + .find('ion-icon[name="open_in_browser"]') .should('exist'); }); }); diff --git a/cypress/integration/schedule.spec.ts b/cypress/integration/schedule.spec.ts index 918cd6c9..32e5b4a2 100644 --- a/cypress/integration/schedule.spec.ts +++ b/cypress/integration/schedule.spec.ts @@ -27,25 +27,31 @@ describe('schedule', function () { ); }); + it('should respect the url', function () { + cy.visit('/schedule/calendar/2022-01-19'); + cy.get('#date-select-button0').should('contain', '19.01.22'); + }); + it('should navigate a full page', function () { cy.visit('/schedule/calendar/2022-01-19'); - cy.get('.swiper-slide-active').should('contain', '19. Jan. 2022'); + + cy.get('.swiper-slide-active').should('contain', 'Mi'); cy.get('.left-button').click(); cy.wait(2000); - cy.get('.swiper-slide-active').should('not.contain', '19. Jan. 2022'); + cy.get('.swiper-slide-active').should('contain', 'So'); cy.get('.right-button').click(); cy.wait(2000); - cy.get('.swiper-slide-active').should('contain', '19. Jan. 2022'); + cy.get('.swiper-slide-active').should('contain', 'Mi'); cy.get('.right-button').click(); cy.wait(2000); - cy.get('.swiper-slide-active').should('not.contain', '19. Jan. 2022'); + cy.get('.swiper-slide-active').should('contain', 'Sa'); }); for (const [width, count] of [ - [760, 1], + [760, 3], [770, 3], [1700, 7], ]) { @@ -53,24 +59,24 @@ describe('schedule', function () { it(`should have ${count} slides for ${width}px`, function () { cy.visit('/schedule/calendar/2022-01-19'); cy.viewport(width, 550); - cy.get('ion-content') + cy.get('.schedule-wrapper > .infinite-swiper-wrapper') .find('.swiper-slide') .should('have.length', slideMultiplier * count) .first() .invoke('outerWidth') - .should('be.gt', 170); + .should('be.gt', 140); }); } it('should navigate to a specific date', function () { cy.visit('/schedule/calendar/2022-01-19'); - cy.contains('.swiper-slide-active', '19. Jan. 2022').click(); + cy.contains('#date-select-button0', '19.01.22').click(); cy.wait(2000); cy.get('button[data-day=1][data-month=1][data-year=2022]', { includeShadowDom: true, }).click(); cy.wait(2000); - cy.get('.swiper-slide-active').should('contain', '1. Jan. 2022'); + cy.contains('#date-select-button0', '01.01.22').click(); }); it('should add events', function () { diff --git a/cypress/integration/settings.spec.ts b/cypress/integration/settings.spec.ts index 69db06ff..5aa343b2 100644 --- a/cypress/integration/settings.spec.ts +++ b/cypress/integration/settings.spec.ts @@ -14,7 +14,7 @@ */ describe('Settings Page', () => { it('should have a proper title', () => { - cy.visit('/app/settings'); + cy.visit('/settings'); cy.get('ion-title').contains('Einstellungen'); }); diff --git a/cypress/integration/translations.spec.ts b/cypress/integration/translations.spec.ts index 673495a5..e8a4f89c 100644 --- a/cypress/integration/translations.spec.ts +++ b/cypress/integration/translations.spec.ts @@ -14,9 +14,10 @@ */ /** - * Something akin to a.b.c but never a... + * Something akin to a.b.c a.b.C but never a... or a.AbC */ -const probablyBadTranslationPattern = /^\s*\w+\.(\w+\.?)+\s*(?!\.\.\.)\s*$/; +const probablyBadTranslationPattern = + /^\s*([a-z_]+|[A-Z_]+)\.(([a-z_]+|[A-Z_]+)\.)([a-z_]+|[A-Z_]+)$/; describe('translations', function () { for (const path of [ @@ -46,6 +47,7 @@ describe('translations', function () { 'canteen', 'catalog', 'schedule', + 'dashboard', [ 'schedule add modal', () => { @@ -68,6 +70,8 @@ describe('translations', function () { cy.visit(`/${path}`); } + cy.wait(500); + cy.get('ion-app *').each($element => { const text = $element.text(); if (text) { diff --git a/src/app/modules/schedule/page/components/calendar.component.ts b/src/app/modules/schedule/page/components/calendar.component.ts index da242f5f..b5e2ad78 100644 --- a/src/app/modules/schedule/page/components/calendar.component.ts +++ b/src/app/modules/schedule/page/components/calendar.component.ts @@ -1,16 +1,16 @@ /* - * Copyright (C) 2021 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ import {Component, Input, OnDestroy, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; @@ -126,13 +126,6 @@ export class CalendarComponent implements OnInit, OnDestroy { } onInit() { - this.dateRange.startDate = this.calculateDateFromIndex(0, 0, 'DD.MM.YY'); - this.dateRange.endDate = this.calculateDateFromIndex( - 0, - this.layout.days - 1, - 'DD.MM.YY', - ); - let dayString: string | number | null = this.activatedRoute.snapshot.paramMap.get('date'); if (dayString == undefined || dayString === 'now') { @@ -154,6 +147,13 @@ export class CalendarComponent implements OnInit, OnDestroy { }, ); }); + + this.dateRange.startDate = this.calculateDateFromIndex(0, 0, 'DD.MM.YY'); + this.dateRange.endDate = this.calculateDateFromIndex( + 0, + this.layout.days - 1, + 'DD.MM.YY', + ); } onDestroy() { diff --git a/src/theme/variables.scss b/src/theme/variables.scss index 44f33acc..29974259 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -1,3 +1,18 @@ +/*! + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + // Ionic Variables and Theming. For more info, please see: // http://ionicframework.com/docs/theming/ @@ -100,8 +115,8 @@ --shadow-cards: 0 0 8px 1px #ddd; --shadow-cards-hover: 5px 5px 8px 4px #ccc; --shadow-profile-card: 0 2px 6px 6px rgba(0,0,0,0.06), - 0 4px 5px 12px rgba(0,0,0,0.04), - 0 5px 6px 20px rgba(0,0,0,0.02); + 0 4px 5px 12px rgba(0,0,0,0.04), + 0 5px 6px 20px rgba(0,0,0,0.02); // Fonts --ion-font-family: "Barlow",Helvetica,Arial,sans-serif;