MOBILE-4061 behat: Always use the runtime to communicate with the app

main
Pau Ferrer Ocaña 2022-06-14 12:29:59 +02:00
parent f69e7971be
commit ef574e7e63
6 changed files with 83 additions and 77 deletions

View File

@ -408,7 +408,7 @@ class behat_app extends behat_app_helper {
],
]);
$this->evaluate_script("return window.pushNotifications.notificationClicked($notification)");
$this->evaluate_script("window.behat.notificationClicked($notification)");
$this->wait_for_pending_js();
}
@ -717,25 +717,8 @@ class behat_app extends behat_app_helper {
* @When I run cron tasks in the app
*/
public function i_run_cron_tasks_in_the_app() {
$session = $this->getSession();
// Force cron tasks execution and wait until they are completed.
$operationid = random_string();
$session->executeScript(
"cronProvider.forceSyncExecution().then(() => { window['behat_{$operationid}_completed'] = true; });"
);
$this->spin(
function() use ($session, $operationid) {
return $session->evaluateScript("window['behat_{$operationid}_completed'] || false");
},
false,
60,
new ExpectationException('Forced cron tasks in the app took too long to complete', $session)
);
// Trigger Angular change detection.
$this->trigger_angular_change_detection();
$this->evaluate_script('window.behat.forceSyncExecution()');
$this->wait_for_pending_js();
}
/**
@ -744,28 +727,8 @@ class behat_app extends behat_app_helper {
* @When I wait loading to finish in the app
*/
public function i_wait_loading_to_finish_in_the_app() {
$session = $this->getSession();
$this->spin(
function() use ($session) {
$this->trigger_angular_change_detection();
$nodes = $this->find_all('css', 'core-loading ion-spinner');
foreach ($nodes as $node) {
if (!$node->isVisible()) {
continue;
}
return false;
}
return true;
},
false,
60,
new ExpectationException('"Loading took too long to complete', $session)
);
$this->evaluate_script('window.behat.waitLoadingToFinish()');
$this->wait_for_pending_js();
}
/**
@ -786,7 +749,7 @@ class behat_app extends behat_app_helper {
$this->getSession()->switchToWindow($names[1]);
}
$this->execute_script('window.close();');
$this->evaluate_script('window.close();');
$this->getSession()->switchToWindow($names[0]);
}
@ -798,7 +761,7 @@ class behat_app extends behat_app_helper {
* @throws DriverException If the navigator.online mode is not available
*/
public function i_switch_offline_mode(string $offline) {
$this->execute_script("appProvider.setForceOffline($offline);");
$this->evaluate_script("window.behat.network.setForceOffline($offline);");
}
}

View File

@ -318,7 +318,7 @@ class behat_app_helper extends behat_base {
$initOptions->skipOnBoarding = $options['skiponboarding'] ?? true;
$initOptions->configOverrides = $this->appconfig;
$this->execute_script('window.behatInit(' . json_encode($initOptions) . ');');
$this->evaluate_script('window.behatInit(' . json_encode($initOptions) . ');');
} catch (Exception $error) {
throw new DriverException('Moodle App not running or not running on Automated mode.');
}
@ -433,14 +433,6 @@ class behat_app_helper extends behat_base {
}
}
/**
* Trigger Angular change detection.
*/
protected function trigger_angular_change_detection() {
$this->getSession()->executeScript('ngZone.run(() => {});');
}
/**
* Evaluate a script that returns a Promise.
*

View File

@ -431,7 +431,7 @@ export class CorePushNotificationsProvider {
/**
* Function called when a push notification is clicked. Redirect the user to the right state.
*
* @param notification Notification.
* @param data Notification data.
* @return Promise resolved when done.
*/
async notificationClicked(data: CorePushNotificationsNotificationBasicData): Promise<void> {

View File

@ -12,35 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { ApplicationRef, NgZone as NgZoneService } from '@angular/core';
import { CorePushNotifications, CorePushNotificationsProvider } from '@features/pushnotifications/services/pushnotifications';
import { CoreApp, CoreAppProvider } from '@services/app';
import { CoreConfig, CoreConfigProvider } from '@services/config';
import { CoreCronDelegate, CoreCronDelegateService } from '@services/cron';
import { CoreAppProvider } from '@services/app';
import { CoreDB, CoreDbProvider } from '@services/db';
import { CoreCustomURLSchemes, CoreCustomURLSchemesProvider } from '@services/urlschemes';
import { Application, NgZone } from '@singletons';
type AutomatedTestsWindow = Window & {
appRef?: ApplicationRef;
appProvider?: CoreAppProvider;
dbProvider?: CoreDbProvider;
configProvider?: CoreConfigProvider;
cronProvider?: CoreCronDelegateService;
ngZone?: NgZoneService;
pushNotifications?: CorePushNotificationsProvider;
urlSchemes?: CoreCustomURLSchemesProvider;
};
function initializeAutomatedTestsWindow(window: AutomatedTestsWindow) {
window.appRef = Application.instance;
window.appProvider = CoreApp.instance;
window.dbProvider = CoreDB.instance;
window.configProvider = CoreConfig.instance;
window.cronProvider = CoreCronDelegate.instance;
window.ngZone = NgZone.instance;
window.pushNotifications = CorePushNotifications.instance;
window.urlSchemes = CoreCustomURLSchemes.instance;
}
export default function(): void {

View File

@ -468,7 +468,7 @@ export class TestsBehatDomUtils {
* @param element Element to press.
*/
static async pressElement(element: HTMLElement): Promise<void> {
NgZone.run(async () => {
await NgZone.run(async () => {
const blockKey = TestsBehatBlocking.block();
// Events don't bubble up across Shadow DOM boundaries, and some buttons
@ -511,7 +511,7 @@ export class TestsBehatDomUtils {
* @param value Value to be set.
*/
static async setElementValue(element: HTMLElement, value: string): Promise<void> {
NgZone.run(async () => {
await NgZone.run(async () => {
const blockKey = TestsBehatBlocking.block();
// Functions to get/set value depending on field type.

View File

@ -19,6 +19,15 @@ import { CoreLoginHelperProvider } from '@features/login/services/login-helper';
import { CoreConfig } from '@services/config';
import { EnvironmentConfig } from '@/types/config';
import { NgZone } from '@singletons';
import { CoreNetwork } from '@services/network';
import {
CorePushNotifications,
CorePushNotificationsNotificationBasicData,
} from '@features/pushnotifications/services/pushnotifications';
import { CoreCronDelegate } from '@services/cron';
import { CoreLoadingComponent } from '@components/loading/loading';
import { CoreComponentsRegistry } from '@singletons/components-registry';
import { CoreDom } from '@singletons/dom';
/**
* Behat runtime servive with public API.
@ -46,6 +55,10 @@ export class TestsBehatRuntime {
scrollTo: TestsBehatRuntime.scrollTo,
setField: TestsBehatRuntime.setField,
handleCustomURL: TestsBehatRuntime.handleCustomURL,
notificationClicked: TestsBehatRuntime.notificationClicked,
forceSyncExecution: TestsBehatRuntime.forceSyncExecution,
waitLoadingToFinish: TestsBehatRuntime.waitLoadingToFinish,
network: CoreNetwork.instance,
};
if (!options) {
@ -85,6 +98,64 @@ export class TestsBehatRuntime {
}
}
/**
* Function called when a push notification is clicked. Redirect the user to the right state.
*
* @param data Notification data.
* @return Promise resolved when done.
*/
static async notificationClicked(data: CorePushNotificationsNotificationBasicData): Promise<void> {
const blockKey = TestsBehatBlocking.block();
try {
await NgZone.run(async () => {
await CorePushNotifications.notificationClicked(data);
});
} finally {
TestsBehatBlocking.unblock(blockKey);
}
}
/**
* Force execution of synchronization cron tasks without waiting for the scheduled time.
* Please notice that some tasks may not be executed depending on the network connection and sync settings.
*
* @return Promise resolved if all handlers are executed successfully, rejected otherwise.
*/
static async forceSyncExecution(): Promise<void> {
const blockKey = TestsBehatBlocking.block();
try {
await NgZone.run(async () => {
await CoreCronDelegate.forceSyncExecution();
});
} finally {
TestsBehatBlocking.unblock(blockKey);
}
}
/**
* Wait all controlled components to be rendered.
*
* @return Promise resolved when all components have been rendered.
*/
static async waitLoadingToFinish(): Promise<void> {
const blockKey = TestsBehatBlocking.block();
await NgZone.run(async () => {
try {
const elements = Array.from(document.body.querySelectorAll<HTMLElement>('core-loading'))
.filter((element) => CoreDom.isElementVisible(element));
await Promise.all(elements.map(element =>
CoreComponentsRegistry.waitComponentReady(element, CoreLoadingComponent)));
} finally {
TestsBehatBlocking.unblock(blockKey);
}
});
}
/**
* Function to find and click an app standard button.
*