@@ -100,6 +100,19 @@ public function i_launch_the_app() {
100100 $ this ->prepare_browser ();
101101 }
102102
103+ /**
104+ * @Then /^I wait the app to restart$/
105+ */
106+ public function i_wait_the_app_to_restart () {
107+ // Wait window to reload.
108+ $ this ->spin (function () {
109+ return $ this ->evaluate_script ("return !window.behat; " );
110+ });
111+
112+ // Prepare testing runtime again.
113+ $ this ->prepare_browser (false );
114+ }
115+
103116 /**
104117 * Finds elements in the app.
105118 *
@@ -347,24 +360,28 @@ public static function close_ionic() {
347360 * @param string $url App URL
348361 * @throws DriverException If the app fails to load properly
349362 */
350- protected function prepare_browser () {
351- // Restart the browser and set its size.
352- $ this ->getSession ()->restart ();
353- $ this ->resize_window ('360x720 ' , true );
363+ protected function prepare_browser (bool $ restart = true ) {
364+ if ($ restart ) {
365+ // Restart the browser and set its size.
366+ $ this ->getSession ()->restart ();
367+ $ this ->resize_window ('360x720 ' , true );
368+
369+ if (empty ($ this ->ionicurl )) {
370+ $ this ->ionicurl = $ this ->start_or_reuse_ionic ();
371+ }
354372
355- if (empty ($ this ->ionicurl )) {
356- $ this ->ionicurl = $ this ->start_or_reuse_ionic ();
357- }
373+ // Check whether the app is running a legacy version.
374+ $ json = @file_get_contents ("{$ this ->ionicurl }/assets/env.json " ) ?: @file_get_contents ("{$ this ->ionicurl }/config.json " );
375+ $ data = json_decode ($ json );
376+ $ appversion = $ data ->build ->version ?? str_replace ('-dev ' , '' , $ data ->versionname );
358377
359- // Check whether the app is running a legacy version.
360- $ json = @file_get_contents ("{$ this ->ionicurl }/assets/env.json " ) ?: @file_get_contents ("{$ this ->ionicurl }/config.json " );
361- $ data = json_decode ($ json );
362- $ appversion = $ data ->build ->version ?? str_replace ('-dev ' , '' , $ data ->versionname );
378+ $ this ->islegacy = version_compare ($ appversion , '3.9.5 ' , '< ' );
363379
364- $ this ->islegacy = version_compare ($ appversion , '3.9.5 ' , '< ' );
380+ // Visit the Ionic URL.
381+ $ this ->getSession ()->visit ($ this ->ionicurl );
382+ }
365383
366- // Visit the Ionic URL and wait for it to load.
367- $ this ->getSession ()->visit ($ this ->ionicurl );
384+ // Wait the application to load.
368385 $ this ->spin (function ($ context ) {
369386 $ title = $ context ->getSession ()->getPage ()->find ('xpath ' , '//title ' );
370387
@@ -387,34 +404,36 @@ protected function prepare_browser() {
387404 $ this ->execute_script ("window.BehatMoodleAppLegacy = $ islegacyboolean; " );
388405 $ this ->execute_script (file_get_contents (__DIR__ . '/app_behat_runtime.js ' ));
389406
390- // Assert initial page.
391- $ this ->spin (function ($ context ) {
392- $ page = $ context ->getSession ()->getPage ();
393- $ element = $ page ->find ('xpath ' , '//page-core-login-site//input[@name="url"] ' );
407+ if ($ restart ) {
408+ // Assert initial page.
409+ $ this ->spin (function ($ context ) {
410+ $ page = $ context ->getSession ()->getPage ();
411+ $ element = $ page ->find ('xpath ' , '//page-core-login-site//input[@name="url"] ' );
394412
395- if ($ element ) {
396- // Wait for the onboarding modal to open, if any.
397- $ this ->wait_for_pending_js ();
413+ if ($ element ) {
414+ // Wait for the onboarding modal to open, if any.
415+ $ this ->wait_for_pending_js ();
398416
399- $ element = $ this ->islegacy
400- ? $ page ->find ('xpath ' , '//page-core-login-site-onboarding ' )
401- : $ page ->find ('xpath ' , '//core-login-site-onboarding ' );
417+ $ element = $ this ->islegacy
418+ ? $ page ->find ('xpath ' , '//page-core-login-site-onboarding ' )
419+ : $ page ->find ('xpath ' , '//core-login-site-onboarding ' );
402420
403- if ($ element ) {
404- $ this ->i_press_in_the_app ($ this ->parse_element_locator ('"Skip" ' ));
405- }
421+ if ($ element ) {
422+ $ this ->i_press_in_the_app ($ this ->parse_element_locator ('"Skip" ' ));
423+ }
406424
407- // Login screen found.
408- return true ;
409- }
425+ // Login screen found.
426+ return true ;
427+ }
410428
411- if ($ page ->find ('xpath ' , '//page-core-mainmenu ' )) {
412- // Main menu found.
413- return true ;
414- }
429+ if ($ page ->find ('xpath ' , '//page-core-mainmenu ' )) {
430+ // Main menu found.
431+ return true ;
432+ }
415433
416- throw new DriverException ('Moodle app not launched properly ' );
417- }, false , 60 );
434+ throw new DriverException ('Moodle app not launched properly ' );
435+ }, false , 60 );
436+ }
418437
419438 // Continue only after JS finishes.
420439 $ this ->wait_for_pending_js ();
@@ -484,12 +503,12 @@ public function i_press_the_standard_button_in_the_app(string $button) {
484503 }
485504
486505 /**
487- * Receives push notifications for forum events .
506+ * Receives push notifications.
488507 *
489- * @Given /^I receive a forum push notification for:$/
508+ * @Given /^I receive a push notification in the app for:$/
490509 * @param TableNode $data
491510 */
492- public function i_receive_a_forum_push_notification (TableNode $ data ) {
511+ public function i_receive_a_push_notification (TableNode $ data ) {
493512 global $ DB , $ CFG ;
494513
495514 $ data = (object ) $ data ->getColumnsHash ()[0 ];
@@ -513,6 +532,41 @@ public function i_receive_a_forum_push_notification(TableNode $data) {
513532 $ this ->wait_for_pending_js ();
514533 }
515534
535+ /**
536+ * Replace arguments from the content in the given activity field.
537+ *
538+ * @Given /^I replace the arguments in "([^"]+)" "([^"]+)"$/
539+ */
540+ public function i_replace_arguments_in_the_activity (string $ idnumber , string $ field ) {
541+ global $ DB ;
542+
543+ $ coursemodule = $ DB ->get_record ('course_modules ' , compact ('idnumber ' ));
544+ $ module = $ DB ->get_record ('modules ' , ['id ' => $ coursemodule ->module ]);
545+ $ activity = $ DB ->get_record ($ module ->name , ['id ' => $ coursemodule ->instance ]);
546+
547+ $ DB ->update_record ($ module ->name , [
548+ 'id ' => $ coursemodule ->instance ,
549+ $ field => $ this ->replace_arguments ($ activity ->{$ field }),
550+ ]);
551+ }
552+
553+ /**
554+ * Opens a custom link.
555+ *
556+ * @Given /^I open a custom link in the app for:$/
557+ */
558+ public function i_open_a_custom_link (TableNode $ data ) {
559+ global $ DB , $ CFG ;
560+
561+ $ data = (object ) $ data ->getColumnsHash ()[0 ];
562+ $ discussion = $ DB ->get_record ('forum_discussions ' , ['name ' => $ data ->discussion ]);
563+ $ pageurl = "{$ CFG ->behat_wwwroot }/mod/forum/discuss.php?d= {$ discussion ->id }" ;
564+ $ url = "moodlemobile://link= " . urlencode ($ pageurl );
565+
566+ $ this ->evaluate_script ("return window.urlSchemes.handleCustomURL(' $ url') " );
567+ $ this ->wait_for_pending_js ();
568+ }
569+
516570 /**
517571 * Closes a popup by clicking on the 'backdrop' behind it.
518572 *
@@ -853,4 +907,31 @@ public function replace_wwwroot($text) {
853907 return str_replace ('$WWWROOT ' , $ CFG ->behat_wwwroot , $ text );
854908 }
855909
910+ /**
911+ * Replace arguments with the format "${activity:field}" from a string, where "activity" is
912+ * the idnumber of an activity and "field" is the activity's field to get replacement from.
913+ *
914+ * At the moment, the only field supported is "cmid", the id of the course module for this activity.
915+ *
916+ * @param string $text Original text.
917+ * @return string Text with arguments replaced.
918+ */
919+ protected function replace_arguments (string $ text ): string {
920+ global $ DB ;
921+
922+ preg_match_all ("/ \\$ \\{([^:}]+):([^}]+) \\}/ " , $ text , $ matches );
923+
924+ foreach ($ matches [0 ] as $ index => $ match ) {
925+ switch ($ matches [2 ][$ index ]) {
926+ case 'cmid ' :
927+ $ coursemodule = $ DB ->get_record ('course_modules ' , ['idnumber ' => $ matches [1 ][$ index ]]);
928+ $ text = str_replace ($ match , $ coursemodule ->id , $ text );
929+
930+ break ;
931+ }
932+ }
933+
934+ return $ text ;
935+ }
936+
856937}
0 commit comments