MOBILE-4110 behat: Fix namespace

main
Noel De Martin 2022-06-29 12:16:33 +02:00
parent 93cfcd4ae0
commit e974912880
4 changed files with 49 additions and 49 deletions

View File

@ -14,12 +14,12 @@
import { APP_INITIALIZER, NgModule } from '@angular/core'; import { APP_INITIALIZER, NgModule } from '@angular/core';
import { CoreAppProvider } from '@services/app'; import { CoreAppProvider } from '@services/app';
import { TestsBehatBlockingService } from './services/behat-blocking'; import { TestingBehatBlockingService } from './services/behat-blocking';
import { BehatTestsWindow, TestsBehatRuntime } from './services/behat-runtime'; import { BehatTestsWindow, TestingBehatRuntime } from './services/behat-runtime';
function initializeBehatTestsWindow(window: BehatTestsWindow) { function initializeBehatTestsWindow(window: BehatTestsWindow) {
// Make functions publicly available for Behat to call. // Make functions publicly available for Behat to call.
window.behatInit = TestsBehatRuntime.init; window.behatInit = TestingBehatRuntime.init;
} }
@NgModule({ @NgModule({
@ -27,7 +27,7 @@ function initializeBehatTestsWindow(window: BehatTestsWindow) {
CoreAppProvider.isAutomated() CoreAppProvider.isAutomated()
? [ ? [
{ provide: APP_INITIALIZER, multi: true, useValue: () => initializeBehatTestsWindow(window) }, { provide: APP_INITIALIZER, multi: true, useValue: () => initializeBehatTestsWindow(window) },
TestsBehatBlockingService, TestingBehatBlockingService,
] ]
: [], : [],
}) })

View File

@ -15,13 +15,13 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { makeSingleton, NgZone } from '@singletons'; import { makeSingleton, NgZone } from '@singletons';
import { BehatTestsWindow, TestsBehatRuntime } from './behat-runtime'; import { BehatTestsWindow, TestingBehatRuntime } from './behat-runtime';
/** /**
* Behat block JS manager. * Behat block JS manager.
*/ */
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class TestsBehatBlockingService { export class TestingBehatBlockingService {
protected waitingBlocked = false; protected waitingBlocked = false;
protected recentMutation = false; protected recentMutation = false;
@ -48,7 +48,7 @@ export class TestsBehatBlockingService {
win.M.util = win.M.util ?? {}; win.M.util = win.M.util ?? {};
win.M.util.pending_js = win.M.util.pending_js ?? []; win.M.util.pending_js = win.M.util.pending_js ?? [];
TestsBehatRuntime.log('Initialized!'); TestingBehatRuntime.log('Initialized!');
} }
/** /**
@ -90,7 +90,7 @@ export class TestsBehatBlockingService {
} }
this.pendingList.push(key); this.pendingList.push(key);
TestsBehatRuntime.log('PENDING+: ' + this.pendingList); TestingBehatRuntime.log('PENDING+: ' + this.pendingList);
return key; return key;
} }
@ -105,7 +105,7 @@ export class TestsBehatBlockingService {
// Remove the key immediately. // Remove the key immediately.
this.pendingList = this.pendingList.filter((x) => x !== key); this.pendingList = this.pendingList.filter((x) => x !== key);
TestsBehatRuntime.log('PENDING-: ' + this.pendingList); TestingBehatRuntime.log('PENDING-: ' + this.pendingList);
// If the only thing left is DELAY, then remove that as well, later... // If the only thing left is DELAY, then remove that as well, later...
if (this.pendingList.length === 1) { if (this.pendingList.length === 1) {
@ -124,7 +124,7 @@ export class TestsBehatBlockingService {
// Only remove it if the pending array is STILL empty after all that. // Only remove it if the pending array is STILL empty after all that.
if (this.pendingList.length === 1) { if (this.pendingList.length === 1) {
this.pendingList = []; this.pendingList = [];
TestsBehatRuntime.log('PENDING-: ' + this.pendingList); TestingBehatRuntime.log('PENDING-: ' + this.pendingList);
} }
} }
} }
@ -221,16 +221,16 @@ export class TestsBehatBlockingService {
try { try {
// Add to the list of pending requests. // Add to the list of pending requests.
TestsBehatBlocking.block(key); TestingBehatBlocking.block(key);
// Detect when it finishes and remove it from the list. // Detect when it finishes and remove it from the list.
this.addEventListener('loadend', () => { this.addEventListener('loadend', () => {
TestsBehatBlocking.unblock(key); TestingBehatBlocking.unblock(key);
}); });
return realOpen.apply(this, args); return realOpen.apply(this, args);
} catch (error) { } catch (error) {
TestsBehatBlocking.unblock(key); TestingBehatBlocking.unblock(key);
throw error; throw error;
} }
}); });
@ -239,4 +239,4 @@ export class TestsBehatBlockingService {
} }
export const TestsBehatBlocking = makeSingleton(TestsBehatBlockingService); export const TestingBehatBlocking = makeSingleton(TestingBehatBlockingService);

View File

@ -15,7 +15,7 @@
import { CorePromisedValue } from '@classes/promised-value'; import { CorePromisedValue } from '@classes/promised-value';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { NgZone } from '@singletons'; import { NgZone } from '@singletons';
import { TestBehatElementLocator } from './behat-runtime'; import { TestingBehatElementLocator, TestingBehatFindOptions } from './behat-runtime';
// Containers that block containers behind them. // Containers that block containers behind them.
const blockingContainers = ['ION-ALERT', 'ION-POPOVER', 'ION-ACTION-SHEET', 'CORE-USER-TOURS-USER-TOUR', 'ION-PAGE']; const blockingContainers = ['ION-ALERT', 'ION-POPOVER', 'ION-ACTION-SHEET', 'CORE-USER-TOURS-USER-TOUR', 'ION-PAGE'];
@ -23,7 +23,7 @@ const blockingContainers = ['ION-ALERT', 'ION-POPOVER', 'ION-ACTION-SHEET', 'COR
/** /**
* Behat Dom Utils helper functions. * Behat Dom Utils helper functions.
*/ */
export class TestsBehatDomUtils { export class TestingBehatDomUtils {
/** /**
* Check if an element is visible. * Check if an element is visible.
@ -328,7 +328,7 @@ export class TestsBehatDomUtils {
* @param containerName Whether to search only inside a specific container. * @param containerName Whether to search only inside a specific container.
* @return First found element. * @return First found element.
*/ */
static findElementBasedOnText(locator: TestBehatElementLocator, containerName = ''): HTMLElement { static findElementBasedOnText(locator: TestingBehatElementLocator, containerName = ''): HTMLElement {
return this.findElementsBasedOnText(locator, containerName, true)[0]; return this.findElementsBasedOnText(locator, containerName, true)[0];
} }
@ -341,7 +341,7 @@ export class TestsBehatDomUtils {
* @return Found elements * @return Found elements
*/ */
protected static findElementsBasedOnText( protected static findElementsBasedOnText(
locator: TestBehatElementLocator, locator: TestingBehatElementLocator,
containerName = '', containerName = '',
stopWhenFound = false, stopWhenFound = false,
): HTMLElement[] { ): HTMLElement[] {
@ -366,7 +366,7 @@ export class TestsBehatDomUtils {
* @return Found elements * @return Found elements
*/ */
protected static findElementsBasedOnTextInContainer( protected static findElementsBasedOnTextInContainer(
locator: TestBehatElementLocator, locator: TestingBehatElementLocator,
topContainer: HTMLElement, topContainer: HTMLElement,
): HTMLElement[] { ): HTMLElement[] {
let container: HTMLElement | null = topContainer; let container: HTMLElement | null = topContainer;

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { TestsBehatDomUtils } from './behat-dom'; import { TestingBehatDomUtils } from './behat-dom';
import { TestsBehatBlocking } from './behat-blocking'; import { TestingBehatBlocking } from './behat-blocking';
import { CoreCustomURLSchemes } from '@services/urlschemes'; import { CoreCustomURLSchemes } from '@services/urlschemes';
import { CoreLoginHelperProvider } from '@features/login/services/login-helper'; import { CoreLoginHelperProvider } from '@features/login/services/login-helper';
import { CoreConfig } from '@services/config'; import { CoreConfig } from '@services/config';
@ -34,15 +34,15 @@ import { CoreCoursesDashboardPage } from '@features/courses/pages/dashboard/dash
/** /**
* Behat runtime servive with public API. * Behat runtime servive with public API.
*/ */
export class TestsBehatRuntime { export class TestingBehatRuntime {
/** /**
* Init behat functions and set options like skipping onboarding. * Init behat functions and set options like skipping onboarding.
* *
* @param options Options to set on the app. * @param options Options to set on the app.
*/ */
static init(options?: TestsBehatInitOptions): void { static init(options?: TestingBehatInitOptions): void {
TestsBehatBlocking.init(); TestingBehatBlocking.init();
(window as BehatTestsWindow).behat = { (window as BehatTestsWindow).behat = {
closePopup: TestsBehatRuntime.closePopup, closePopup: TestsBehatRuntime.closePopup,
@ -104,14 +104,14 @@ export class TestsBehatRuntime {
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
static async notificationClicked(data: CorePushNotificationsNotificationBasicData): Promise<void> { static async notificationClicked(data: CorePushNotificationsNotificationBasicData): Promise<void> {
const blockKey = TestsBehatBlocking.block(); const blockKey = TestingBehatBlocking.block();
try { try {
await NgZone.run(async () => { await NgZone.run(async () => {
await CorePushNotifications.notificationClicked(data); await CorePushNotifications.notificationClicked(data);
}); });
} finally { } finally {
TestsBehatBlocking.unblock(blockKey); TestingBehatBlocking.unblock(blockKey);
} }
} }
@ -156,20 +156,20 @@ export class TestsBehatRuntime {
switch (button) { switch (button) {
case 'back': case 'back':
foundButton = TestsBehatDomUtils.findElementBasedOnText({ text: 'Back' }); foundButton = TestingBehatDomUtils.findElementBasedOnText({ text: 'Back' });
break; break;
case 'main menu': // Deprecated name. case 'main menu': // Deprecated name.
case 'more menu': case 'more menu':
foundButton = TestsBehatDomUtils.findElementBasedOnText({ foundButton = TestingBehatDomUtils.findElementBasedOnText({
text: 'More', text: 'More',
selector: 'ion-tab-button', selector: 'ion-tab-button',
}); });
break; break;
case 'user menu' : case 'user menu' :
foundButton = TestsBehatDomUtils.findElementBasedOnText({ text: 'User account' }); foundButton = TestingBehatDomUtils.findElementBasedOnText({ text: 'User account' });
break; break;
case 'page menu': case 'page menu':
foundButton = TestsBehatDomUtils.findElementBasedOnText({ text: 'Display options' }); foundButton = TestingBehatDomUtils.findElementBasedOnText({ text: 'Display options' });
break; break;
default: default:
return 'ERROR: Unsupported standard button type'; return 'ERROR: Unsupported standard button type';
@ -180,7 +180,7 @@ export class TestsBehatRuntime {
} }
// Click button // Click button
await TestsBehatDomUtils.pressElement(foundButton); await TestingBehatDomUtils.pressElement(foundButton);
return 'OK'; return 'OK';
} }
@ -206,7 +206,7 @@ export class TestsBehatRuntime {
backdrop.click(); backdrop.click();
// Mark busy until the click finishes processing. // Mark busy until the click finishes processing.
TestsBehatBlocking.delay(); TestingBehatBlocking.delay();
return 'OK'; return 'OK';
} }
@ -218,11 +218,11 @@ export class TestsBehatRuntime {
* @param containerName Whether to search only inside a specific container content. * @param containerName Whether to search only inside a specific container content.
* @return OK if successful, or ERROR: followed by message * @return OK if successful, or ERROR: followed by message
*/ */
static find(locator: TestBehatElementLocator, containerName: string): string { static find(locator: TestingBehatElementLocator, containerName: string): string {
this.log('Action - Find', { locator, containerName }); this.log('Action - Find', { locator, containerName });
try { try {
const element = TestsBehatDomUtils.findElementBasedOnText(locator, containerName); const element = TestingBehatDomUtils.findElementBasedOnText(locator, containerName);
if (!element) { if (!element) {
return 'ERROR: No element matches locator to find.'; return 'ERROR: No element matches locator to find.';
@ -242,11 +242,11 @@ export class TestsBehatRuntime {
* @param locator Element locator. * @param locator Element locator.
* @return OK if successful, or ERROR: followed by message * @return OK if successful, or ERROR: followed by message
*/ */
static scrollTo(locator: TestBehatElementLocator): string { static scrollTo(locator: TestingBehatElementLocator): string {
this.log('Action - scrollTo', { locator }); this.log('Action - scrollTo', { locator });
try { try {
let element = TestsBehatDomUtils.findElementBasedOnText(locator); let element = TestingBehatDomUtils.findElementBasedOnText(locator);
if (!element) { if (!element) {
return 'ERROR: No element matches element to scroll to.'; return 'ERROR: No element matches element to scroll to.';
@ -316,13 +316,13 @@ export class TestsBehatRuntime {
* @param locator Element locator. * @param locator Element locator.
* @return YES or NO if successful, or ERROR: followed by message * @return YES or NO if successful, or ERROR: followed by message
*/ */
static isSelected(locator: TestBehatElementLocator): string { static isSelected(locator: TestingBehatElementLocator): string {
this.log('Action - Is Selected', locator); this.log('Action - Is Selected', locator);
try { try {
const element = TestsBehatDomUtils.findElementBasedOnText(locator); const element = TestingBehatDomUtils.findElementBasedOnText(locator);
return TestsBehatDomUtils.isElementSelected(element, document.body) ? 'YES' : 'NO'; return TestingBehatDomUtils.isElementSelected(element, document.body) ? 'YES' : 'NO';
} catch (error) { } catch (error) {
return 'ERROR: ' + error.message; return 'ERROR: ' + error.message;
} }
@ -334,17 +334,17 @@ export class TestsBehatRuntime {
* @param locator Element locator. * @param locator Element locator.
* @return OK if successful, or ERROR: followed by message * @return OK if successful, or ERROR: followed by message
*/ */
static async press(locator: TestBehatElementLocator): Promise<string> { static async press(locator: TestingBehatElementLocator): Promise<string> {
this.log('Action - Press', locator); this.log('Action - Press', locator);
try { try {
const found = TestsBehatDomUtils.findElementBasedOnText(locator); const found = TestingBehatDomUtils.findElementBasedOnText(locator);
if (!found) { if (!found) {
return 'ERROR: No element matches locator to press.'; return 'ERROR: No element matches locator to press.';
} }
await TestsBehatDomUtils.pressElement(found); await TestingBehatDomUtils.pressElement(found);
return 'OK'; return 'OK';
} catch (error) { } catch (error) {
@ -394,7 +394,7 @@ export class TestsBehatRuntime {
this.log('Action - Get header'); this.log('Action - Get header');
let titles = Array.from(document.querySelectorAll<HTMLElement>('.ion-page:not(.ion-page-hidden) > ion-header h1')); let titles = Array.from(document.querySelectorAll<HTMLElement>('.ion-page:not(.ion-page-hidden) > ion-header h1'));
titles = titles.filter((title) => TestsBehatDomUtils.isElementVisible(title, document.body)); titles = titles.filter((title) => TestingBehatDomUtils.isElementVisible(title, document.body));
if (titles.length > 1) { if (titles.length > 1) {
return 'ERROR: Too many possible titles ('+titles.length+').'; return 'ERROR: Too many possible titles ('+titles.length+').';
@ -419,7 +419,7 @@ export class TestsBehatRuntime {
static async setField(field: string, value: string): Promise<string> { static async setField(field: string, value: string): Promise<string> {
this.log('Action - Set field ' + field + ' to: ' + value); this.log('Action - Set field ' + field + ' to: ' + value);
const found: HTMLElement | HTMLInputElement = TestsBehatDomUtils.findElementBasedOnText( const found: HTMLElement | HTMLInputElement = TestingBehatDomUtils.findElementBasedOnText(
{ text: field, selector: 'input, textarea, [contenteditable="true"], ion-select' }, { text: field, selector: 'input, textarea, [contenteditable="true"], ion-select' },
); );
@ -427,7 +427,7 @@ export class TestsBehatRuntime {
return 'ERROR: No element matches field to set.'; return 'ERROR: No element matches field to set.';
} }
await TestsBehatDomUtils.setElementValue(found, value); await TestingBehatDomUtils.setElementValue(found, value);
return 'OK'; return 'OK';
} }
@ -478,14 +478,14 @@ export type BehatTestsWindow = Window & {
behat?: unknown; behat?: unknown;
}; };
export type TestBehatElementLocator = { export type TestingBehatElementLocator = {
text: string; text: string;
within?: TestBehatElementLocator; within?: TestingBehatElementLocator;
near?: TestBehatElementLocator; near?: TestingBehatElementLocator;
selector?: string; selector?: string;
}; };
export type TestsBehatInitOptions = { export type TestingBehatInitOptions = {
skipOnBoarding?: boolean; skipOnBoarding?: boolean;
configOverrides?: Partial<EnvironmentConfig>; configOverrides?: Partial<EnvironmentConfig>;
}; };