feat: improved e2e tests

This commit is contained in:
2023-12-05 15:21:01 +01:00
committed by Thea Schöbl
parent bff2d985aa
commit d7a85b7fae
66 changed files with 6353 additions and 4471 deletions

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
/* eslint-disable @typescript-eslint/no-explicit-any */
import type {Component, NgZone} from '@angular/core';
/**
*
*/
export function ng(): Cypress.Chainable<any> {
return cy.window().its('ng');
}
/**
* Get the Angular zone (Change Detection!)
*/
export function zone(): Cypress.Chainable<NgZone> {
return cy.get('app-root').component().its('zone');
}
/**
* Runs a callback inside Angular so change detection can happen
*/
export function runInsideAngular<T, U>(subject: T, zoneAwareTask: (subject: T) => U): Cypress.Chainable<U> {
return cy.zone().then(zone => cy.wrap(zone.run(zoneAwareTask, undefined, [subject])));
}
/**
*
*/
export function component<T = Component>($element: Cypress.JQueryWithSelector): Cypress.Chainable<T> {
return cy.ng().then(ng => ng.getComponent($element[0]));
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
/* eslint-disable @typescript-eslint/no-explicit-any */
import equal from 'fast-deep-equal';
import {extendsDeepEqual} from '@openstapps/collection-utils';
import {SCSearchRequest, SCSearchResponse} from '@openstapps/core';
type InterceptArguments = {
fixture?: string | SCSearchResponse | ((request: SCSearchRequest) => SCSearchResponse);
alias?: string;
} & (
| {
exact: string | SCSearchRequest | ((searchRequest: SCSearchRequest) => boolean);
}
| {
extends: string | SCSearchRequest;
}
);
/**
*
*/
export function interceptConfig(config?: string) {
cy.intercept({url: '/', method: 'POST'}, {fixture: config || 'config/default-config.json'}).as('config');
}
/**
*
*/
export function interceptBackend(route: string, fixtureKey: string, parameters: InterceptArguments) {
const condition = 'exact' in parameters ? parameters.exact : parameters.extends;
parameters.fixture ||= 'no-results';
Cypress.Promise.all([
typeof condition === 'string' ? cy.fixture(`${condition}.${fixtureKey}.req.json`) : condition,
typeof parameters.fixture === 'string'
? cy.fixture(`${parameters.fixture}.${fixtureKey}.res.json`)
: parameters.fixture,
'exact' in parameters ? equal : extendsDeepEqual,
] as const).spread((requestCondition, response, comparisonFunction) => {
cy.intercept({url: route, method: 'POST'}, request => {
const body = request.body;
if (
typeof requestCondition === 'object'
? (comparisonFunction as any)(requestCondition, body)
: (requestCondition as any)(body)
) {
request.alias = parameters.alias;
request.reply(typeof response === 'object' ? response : (response as any)(body));
}
});
});
}
/**
*
*/
export function interceptSearch(parameters: InterceptArguments) {
parameters.alias ||= 'search';
cy.interceptBackend('/search', 'search', parameters);
}
/**
*
*/
export function interceptMultiSearch(parameters: InterceptArguments) {
parameters.alias ||= 'multi-search';
cy.interceptBackend('/search/multi', 'multi', parameters);
}
/**
*
*/
export function interceptGet(parameters: Omit<InterceptArguments, 'exact' | 'extends'> & {uid: string}) {
cy.interceptBackend('/search', 'get', {
exact: request => {
return (
request.size === 1 &&
request.filter?.type === 'value' &&
request.filter.arguments.field === 'uid' &&
request.filter.arguments.value === parameters.uid
);
},
fixture: parameters.fixture || `get/${parameters.uid}`,
alias: parameters.alias || parameters.uid,
});
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
import type {SearchPageComponent} from '../../../src/app/modules/data/list/search-page.component';
/**
* Sets the due time to zero, higher values can lead to issues in cypress
*/
export function patchSearchPage(dueTime = 0) {
return cy
.get('stapps-search-page')
.component<SearchPageComponent>()
.then(component => {
component.searchQueryDueTime = dueTime;
// component.ngOnDestroy();
component.ngOnInit();
});
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
import {STORAGE_KEY_SETTING_VALUES} from '../../../src/app/modules/settings/settings.provider';
import {Storage} from '@ionic/storage-angular';
import deepmerge from 'deepmerge';
import {STORAGE_KEY_CONFIG} from '../../../src/app/modules/config/config.provider';
import {SCIndexResponse} from '@openstapps/core';
export function storage(): Cypress.Chainable<Storage> {
const storage = new Storage({});
return cy.wrap(storage.create());
}
/**
* Writes settings
*/
export function setSettings(settings: Record<string, Record<string, string>>) {
return cy.storage().then(async storage => {
const currentSettings = (await storage.get(STORAGE_KEY_SETTING_VALUES)) || {};
console.log(deepmerge(currentSettings, settings));
await storage.set(STORAGE_KEY_SETTING_VALUES, deepmerge(currentSettings, settings));
});
}
export function getAllSettings(): Cypress.Chainable<Record<string, Record<string, string>> | undefined> {
return cy.storage().invoke('get', STORAGE_KEY_SETTING_VALUES);
}
/**
* Reads settings
*/
export function getSetting(group: string, key: string): Cypress.Chainable<string | undefined> {
return cy.storage().then(async storage => {
const currentSettings = await storage.get(STORAGE_KEY_SETTING_VALUES);
return currentSettings?.[group]?.[key];
});
}
/**
*
*/
export function clearAllSettings() {
return cy.storage().invoke('clear');
}
/**
*
*/
export function setLocalConfig(config: SCIndexResponse | any) {
cy.storage().invoke('set', STORAGE_KEY_CONFIG, config);
}