diff --git a/.github/workflows/behat.yml b/.github/workflows/behat.yml index 59fa3bc7a41..807e098de61 100644 --- a/.github/workflows/behat.yml +++ b/.github/workflows/behat.yml @@ -95,9 +95,6 @@ jobs: # https://github.com/marketplace/actions/setup-chromedriver - name: Start chromedriver uses: nanasess/setup-chromedriver@master - with: - # Optional: do not specify to match Chrome's version - chromedriver-version: '100.0.4896.60' - run: | export DISPLAY=:99 @@ -147,6 +144,7 @@ jobs: sed -i "s/APP_DEBUG='1'/APP_DEBUG='0'/g" .env printf '\nwhen@prod:\n framework:\n http_cache: true\n' >> config/packages/framework.yaml sudo php bin/console cache:clear + sudo php bin/console cache:warmup sudo chmod -R 777 var - name: Behat tests diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index fbea9642cff..c9dcc5c9145 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -9,7 +9,8 @@ framework: # Enables session support. Note that the session will ONLY be started if you read or write from it. # Remove or comment this section to explicitly disable session support. session: - handler_id: null + handler_id: 'session.handler.native_file' + save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%' cookie_secure: auto cookie_samesite: lax name: chamilo2 diff --git a/tests/behat/behat.yml b/tests/behat/behat.yml index a04298f2ddf..13fa1119cb0 100644 --- a/tests/behat/behat.yml +++ b/tests/behat/behat.yml @@ -1,11 +1,11 @@ default: extensions: Behat\MinkExtension: - base_url: http://localhost + base_url: http://my.chamilo.net default_session: selenium2 javascript_session: selenium2 selenium2: - wd_host: "http://127.0.0.1:4444" + wd_host: "http://127.0.0.1:4444/wd/hub" browser: chrome capabilities: browserName: chrome @@ -17,6 +17,8 @@ default: - "--disable-dev-shm-usage" - "--disable-gpu" - "--window-size=1920,1080" + "goog:loggingPrefs": + browser: "ALL" files_path: "%paths.base%/../../" suites: default: diff --git a/tests/behat/features/SpecialCase1.feature b/tests/behat/features/SpecialCase1.feature index d56eab7fc0c..b66a0f41245 100644 --- a/tests/behat/features/SpecialCase1.feature +++ b/tests/behat/features/SpecialCase1.feature @@ -5,11 +5,9 @@ Feature: Special admin settings flows Background: Given I am a platform administrator - And I wait very long for the page to be loaded Scenario: Initial platform searches and basic settings Given I am on "/admin" - And I wait very long for the page to be loaded # Diagnostic search When I fill in the following: @@ -41,10 +39,8 @@ Feature: Special admin settings flows # Additional check: the homepage must display "Diagnosis management" And I am on "/home" - And I wait very long for the page to be loaded Then I should see "Diagnosis management" And I am on "/admin" - And I wait very long for the page to be loaded # Multiple anonymous users When I fill in the following: @@ -67,11 +63,8 @@ Feature: Special admin settings flows # Additional check: on /home we must not see "Explore more courses" And I am on "/home" - And I wait very long for the page to be loaded Then I should not see "Explore more courses" - And I wait very long for the page to be loaded And I am on "/admin" - And I wait very long for the page to be loaded # Certificate links When I fill in the following: @@ -86,11 +79,9 @@ Feature: Special admin settings flows And I am not logged And I am logged as "acostea" And I am on "/home" - And I wait very long for the page to be loaded Then I should not see "My certificates" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | allow_general_certificate | @@ -249,9 +240,7 @@ Feature: Special admin settings flows # Login as first student and open messaging Given I am not logged Then I am logged as "studentone" - And I wait very long for the page to be loaded And I am on "resources/messages" - And I wait very long for the page to be loaded When I press "mdi-email-plus-outline" And I wait very long for the page to be loaded And I should not see an error @@ -266,7 +255,6 @@ Feature: Special admin settings flows Then I should not see an error And I am not logged Then I am logged as "admin" - And wait very long for the page to be loaded # Cookie, registration, terms and extra fields When I fill in the following: @@ -288,7 +276,6 @@ Feature: Special admin settings flows # Verify that, when logged out, the homepage offers a "Sign up" button to main/auth/registration.php Given I am not logged And I am on "/home" - And I wait very long for the page to be loaded Then I should see "Sign up" When I follow "Sign up" And I wait very long for the page to be loaded @@ -296,7 +283,6 @@ Feature: Special admin settings flows And I should not see an error And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | allow_registration_as_teacher | @@ -308,12 +294,10 @@ Feature: Special admin settings flows And I am not logged And I am on "/main/auth/registration.php" - And wait very long for the page to be loaded And I should see "Follow courses" And I should not see "Teach courses" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | allow_terms_conditions | @@ -332,7 +316,6 @@ Feature: Special admin settings flows # 1) Gender (Radio) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Genre | @@ -349,7 +332,6 @@ Feature: Special admin settings flows # 2) Date of birth (Date) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Date de naissance | @@ -364,7 +346,6 @@ Feature: Special admin settings flows # 3) Nationality (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Nationalité | @@ -379,7 +360,6 @@ Feature: Special admin settings flows # 4) Address (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Adresse | @@ -394,7 +374,6 @@ Feature: Special admin settings flows # 5) Postal code (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Code postal | @@ -409,7 +388,6 @@ Feature: Special admin settings flows # 6) City (Geolocalization) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Ville | @@ -424,7 +402,6 @@ Feature: Special admin settings flows # 7) Country of residence (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Pays de Résidence | @@ -439,7 +416,6 @@ Feature: Special admin settings flows # 8) Target learning language (Select) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Langue cible d'apprentissage | @@ -456,7 +432,6 @@ Feature: Special admin settings flows # 9) Currently, I am (Radio) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Actuellement, je suis | @@ -473,7 +448,6 @@ Feature: Special admin settings flows # 10) Field of study (Radio) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Je suis actuellement dans une filière ou je suis diplômé(e) d’une filière | @@ -493,7 +467,6 @@ Feature: Special admin settings flows # 11) Last diploma obtained (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Dernier diplôme obtenu | @@ -508,7 +481,6 @@ Feature: Special admin settings flows # 12) Internship city (Geolocalization) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Ville du stage | @@ -523,7 +495,6 @@ Feature: Special admin settings flows # 13) If your field is not indicated... (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Si ta filière n’est pas indiquée ci-dessus, veux-tu la préciser ici ? | @@ -538,7 +509,6 @@ Feature: Special admin settings flows # 14) During this period... hours per week (Integer) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Pendant cette durée, je peux / je veux consacrer en moyenne en heures par semaine à mon apprentissage sur la plateforme. | @@ -553,7 +523,6 @@ Feature: Special admin settings flows # 15) My internship starts on (Date) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Mon stage commence le | @@ -568,7 +537,6 @@ Feature: Special admin settings flows # 16) and ends on (Date) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | et dure jusqu’au | @@ -583,7 +551,6 @@ Feature: Special admin settings flows # 17) During my internship... hours per week (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Pendant mon stage, je peux / je veux consacrer en moyenne en heures par semaine à mon apprentissage sur la plateforme. | @@ -598,7 +565,6 @@ Feature: Special admin settings flows # 18) I wish to continue... during my internship (Radio) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Je souhaite poursuivre mon apprentissage sur la plateforme pendant mon stage. | @@ -615,7 +581,6 @@ Feature: Special admin settings flows # 19) Learning objective (Tag) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Objectif d'apprentissage | @@ -630,7 +595,6 @@ Feature: Special admin settings flows # 20) I like to work (Radio) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | J’aime travailler | @@ -647,7 +611,6 @@ Feature: Special admin settings flows # 21) I wish to be supported (Radio) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Je souhaite etre accompagne(e) | @@ -664,7 +627,6 @@ Feature: Special admin settings flows # 22) termactivated (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | termactivated | @@ -679,7 +641,6 @@ Feature: Special admin settings flows # 23) I want to do the internship in this field (Radio) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Je veux faire le stage dans cette filiere | @@ -696,7 +657,6 @@ Feature: Special admin settings flows # 24) PlatformUseConditions (Checkbox) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | PlatformUseConditions | @@ -713,7 +673,6 @@ Feature: Special admin settings flows # 25) DiagnosisCompleted (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | DiagnosisCompleted | @@ -728,7 +687,6 @@ Feature: Special admin settings flows # 26) Je ne connais pas encore mes dates de stage (Checkbox) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Je ne connais pas encore mes dates de stage | @@ -743,7 +701,6 @@ Feature: Special admin settings flows # 27) En general, je suis plutot disponible (Select multiple) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | En general, je suis plutot disponible | @@ -758,7 +715,6 @@ Feature: Special admin settings flows # 28) Je suis deja sur place /mon stage/mon emploi a deja commence (Checkbox) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Je suis deja sur place /mon stage/mon emploi a deja commence | @@ -773,7 +729,6 @@ Feature: Special admin settings flows # 29) Un ordinateur fixe ou portable (Checkbox) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Un ordinateur fixe ou portable | @@ -790,7 +745,6 @@ Feature: Special admin settings flows # 30) Une tablette (Checkbox) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Une tablette | @@ -805,7 +759,6 @@ Feature: Special admin settings flows # 31) Un smartphone (Checkbox) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Un smartphone | @@ -820,7 +773,6 @@ Feature: Special admin settings flows # 32) Quel est le systeme d'exploitation ? (computer) (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Quel est le systeme d'exploitation ? | @@ -835,7 +787,6 @@ Feature: Special admin settings flows # 33) Quel est le systeme d'exploitation ? (tablet) (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Quel est le systeme d'exploitation ? | @@ -850,7 +801,6 @@ Feature: Special admin settings flows # 34) Quel est le systeme d'exploitation ? (smartphone) (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Quel est le systeme d'exploitation ? | @@ -865,7 +815,6 @@ Feature: Special admin settings flows # 35) Pour travailler sur la plateforme, j'utilise le browser suivant : (Select multiple) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Pour travailler sur la plateforme, j'utilise le browser suivant : | @@ -880,7 +829,6 @@ Feature: Special admin settings flows # 36) Autre (preciser) : (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Autre (preciser) : | @@ -895,7 +843,6 @@ Feature: Special admin settings flows # 37) Quelle est la version ? (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Quelle est la version ? | @@ -910,7 +857,6 @@ Feature: Special admin settings flows # 38) Hobbies (Tag) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Hobbies | @@ -925,7 +871,6 @@ Feature: Special admin settings flows # 39) State (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | State | @@ -940,7 +885,6 @@ Feature: Special admin settings flows # 40) Level (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Level | @@ -955,7 +899,6 @@ Feature: Special admin settings flows # 41) Quality (Text) And I am on "/main/admin/extra_fields.php?type=user" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #user_field_display_text | Quality | @@ -972,11 +915,9 @@ Feature: Special admin settings flows Scenario: Add minimal session extra fields Given I am a platform administrator - And I wait very long for the page to be loaded # 1) Je commence mon apprentissage sur la plateforme le (Date) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Je commence mon apprentissage sur la plateforme le | @@ -991,7 +932,6 @@ Feature: Special admin settings flows # 2) Je suis disponible jusqu'au (Date) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Je suis disponible jusqu'au | @@ -1008,7 +948,6 @@ Feature: Special admin settings flows # 3) Je souhaite m'inscrire dans une filière (Radio) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Je souhaite m'inscrire dans une filière | @@ -1025,7 +964,6 @@ Feature: Special admin settings flows # 4) Les îlots d'apprentissage (Select multiple) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Les îlots d'apprentissage sont conçus autour des trois grands domaines suivants. Numérote-les de 1 à 3 selon tes priorités et tes intérêts. | @@ -1042,7 +980,6 @@ Feature: Special admin settings flows # 5) Temps de travail (Integer) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Temps de travail | @@ -1057,7 +994,6 @@ Feature: Special admin settings flows # 6) Choisis 5 thèmes et objectifs (Tag) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Choisis 5 thèmes et objectifs et numérote-les de 1 à 5. | @@ -1072,7 +1008,6 @@ Feature: Special admin settings flows # 7) Ecouter (Select multiple) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Ecouter | @@ -1087,12 +1022,10 @@ Feature: Special admin settings flows And I press "user_field_submit" Then I should not see an error - And I wait very long for the page to be loaded # 8) Lire (Select multiple) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Lire | @@ -1109,7 +1042,6 @@ Feature: Special admin settings flows # 9) Participer a une conversation (Select multiple) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Participer à une conversation | @@ -1126,7 +1058,6 @@ Feature: Special admin settings flows # 10) S'exprimer oralement en continu (Select multiple) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | S'exprimer oralement en continu | @@ -1143,7 +1074,6 @@ Feature: Special admin settings flows # 11) Ecrire (Select multiple) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Ecrire | @@ -1160,7 +1090,6 @@ Feature: Special admin settings flows # 12) Thema (Tag) And I am on "/main/admin/extra_fields.php?type=session" - And I wait very long for the page to be loaded When I click the "i.mdi-plus-box" element And I fill in the following: | #session_field_display_text | Thema | @@ -1175,7 +1104,6 @@ Feature: Special admin settings flows Then I should not see an error - And I wait very long for the page to be loaded When I fill in the following: | search_keyword | required_extra_fields_in_inscription | And I press "search_search" @@ -1201,7 +1129,6 @@ Feature: Special admin settings flows And I should see "langue_cible" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded # Registration fields and messages When I fill in the following: @@ -1215,7 +1142,6 @@ Feature: Special admin settings flows And I am not logged And I am on "/main/auth/registration.php" - And I wait very long for the page to be loaded Then I should see "lastname" And I should see "firstname" And I should see "email" @@ -1239,7 +1165,6 @@ Feature: Special admin settings flows And I should see "langue_cible" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | send_inscription_msg_to_inbox | @@ -1261,11 +1186,9 @@ Feature: Special admin settings flows And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded Then I should see "My sessions" And I should not see "Platform administration" And I am on "/admin" - And I wait very long for the page to be loaded # Legal accept, captcha limits and session toggles When I fill in the following: @@ -1311,7 +1234,6 @@ Feature: Special admin settings flows And I wait very long for the page to be loaded And I am on "/main/session/session_list.php" - And I wait very long for the page to be loaded Then I should see "Past session" And I should see "Present session" And I should see "Session in the future" @@ -1357,12 +1279,10 @@ Feature: Special admin settings flows And I wait very long for the page to be loaded And I am on "/main/admin/session_list.php" - And I wait very long for the page to be loaded Then I should see "Students" And I should see "#sessions" And I should see "ID" And I am on "/admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | session_admins_access_all_content | @@ -1393,10 +1313,8 @@ Feature: Special admin settings flows And I wait very long for the page to be loaded And I am on "/main/admin/session_list.php" - And I wait very long for the page to be loaded Then I should see "Custom" And I am on "/admin" - And I wait very long for the page to be loaded # Badges, skills and social When I fill in the following: @@ -1434,7 +1352,6 @@ Feature: Special admin settings flows And I wait very long for the page to be loaded And I am on "main/skills/skill_create.php" - And I wait very long for the page to be loaded When I fill in the following: | title | NewSkill | | short_code | NS | @@ -1445,7 +1362,6 @@ Feature: Special admin settings flows Then I should see "NewSkill" And I am on "main/skills/skill_create.php" - And I wait very long for the page to be loaded When I fill in the following: | title | SubSkill | | short_code | SS | @@ -1458,12 +1374,10 @@ Feature: Special admin settings flows # Assign parent skill and check subskill list appears for user And I am on "main/skills/assign.php?user=1" - And I wait very long for the page to be loaded When I select "NewSkill" from "skill" And I wait very long for the page to be loaded Then I should see "SubSkill" And I am on "/admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | social_enable_messages_feedback | @@ -1475,7 +1389,6 @@ Feature: Special admin settings flows And I am on "/main/social/home.php" - And I wait very long for the page to be loaded When I fill in the following: | post_text | This is a test post created by behat | And I press "submit" @@ -1484,7 +1397,6 @@ Feature: Special admin settings flows And I should see "Like" And I should see "Dislike" And I am on "/admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | disable_dislike_option | @@ -1495,12 +1407,10 @@ Feature: Special admin settings flows And I wait very long for the page to be loaded And I am on "/main/social/home.php" - And I wait very long for the page to be loaded # (environment must have dislike disabled for this check) Then I should see "Like" And I should not see "Dislike" And I am on "/admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | social_show_language_flag_in_profile | @@ -1511,10 +1421,8 @@ Feature: Special admin settings flows And I wait very long for the page to be loaded And I am on "/main/social/home.php" - And I wait very long for the page to be loaded Then I should not see "My communities" And I am on "/admin" - And I wait very long for the page to be loaded # Ticket settings When I fill in the following: @@ -1526,13 +1434,11 @@ Feature: Special admin settings flows And I wait very long for the page to be loaded And I am on "/main/ticket/projects.php?project_id=1" - And I wait very long for the page to be loaded When I follow "Categories" And I wait very long for the page to be loaded Then I should see "Enrollment" And I should see "i.mdi-pencil" And I am on "/admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | ticket_allow_student_add | @@ -1543,14 +1449,11 @@ Feature: Special admin settings flows And I wait very long for the page to be loaded Given I am logged as "studentone" - And I wait very long for the page to be loaded And I am on "/main/ticket/new_ticket.php?project_id=1" - And I wait very long for the page to be loaded Then I should see "Send message" And I should not see an error And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | ticket_send_warning_to_all_admins | @@ -1646,14 +1549,12 @@ Feature: Special admin settings flows Given I am logged as "studentone" And I am on "/main/auth/profile.php" - And I wait very long for the page to be loaded Then I should see "language" And I should see "picture" And I should not see "firstname" And I should not see "lastname" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | visible_options | @@ -1669,14 +1570,12 @@ Feature: Special admin settings flows Then I am logged as "studentone" And I am on "/main/auth/profile.php" - And I wait very long for the page to be loaded Then I should see "official_code" And I should see "email" And I should see "picture" And I should see "language" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | use_users_timezone | @@ -1707,7 +1606,6 @@ Feature: Special admin settings flows And I am not logged And I am logged as "studentone" And I am on "/main/auth/profile.php" - And I wait very long for the page to be loaded Then I should see "firstname" And I should see "lastname" And I should see "picture" @@ -1715,7 +1613,6 @@ Feature: Special admin settings flows And I should see "terms_ville" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | allow_social_map_fields | @@ -1738,13 +1635,11 @@ Feature: Special admin settings flows And I am not logged Then I am logged as "studenttwo" And I am on "/main/auth/terms.php" - And I wait very long for the page to be loaded Then I should see "complete your profile before accepting the terms" And I should see "Accept" # Note: step to check the Accept button is disabled may require an extra step definition; we assert the message appears above. And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | load_term_conditions_section | @@ -1756,14 +1651,11 @@ Feature: Special admin settings flows And I am logged as "studenttwo" And I am on "/home" - And I wait very long for the page to be loaded Then I should not see "Terms and conditions" When I am on "/course/TEMPPRIVATE/home" - And I wait very long for the page to be loaded Then I should see "Terms and conditions" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: @@ -1777,13 +1669,11 @@ Feature: Special admin settings flows Given I am logged as "studentone" And I am on "/" - And I wait very long for the page to be loaded When I follow "Home" And I wait very long for the page to be loaded Then I should see "My sessions" And I am not logged And I am logged as "admin" - And I wait very long for the page to be loaded When I fill in the following: | platform_management_search | default_menu_entry_for_course_or_session | @@ -1797,16 +1687,13 @@ Feature: Special admin settings flows Then I should not see an error And I am logged as "studentthree" - And I wait very long for the page to be loaded Then I should see "My sessions" Scenario: Create courses, multilingual documents, exercises, forum, learning path and assessment activity Given I am a platform administrator - And I wait very long for the page to be loaded # Create courses When I am on "/main/admin/course_add.php" - And I wait very long for the page to be loaded When I fill in the following: | title | Testing course en | And I select "English" from "language" @@ -1815,7 +1702,6 @@ Feature: Special admin settings flows Then I should see "Testing course en" When I am on "/main/admin/course_add.php" - And I wait very long for the page to be loaded When I fill in the following: | title | Special | And I click the "#special_course" element @@ -1824,7 +1710,6 @@ Feature: Special admin settings flows Then I should see "Special" When I am on "/main/admin/course_add.php" - And I wait very long for the page to be loaded When I fill in the following: | title | Testing course fr | And I select "French" from "language" @@ -2010,11 +1895,9 @@ Feature: Special admin settings flows Scenario: Create teacher and configure "Present session" with settings and include course Given I am a platform administrator - And I wait very long for the page to be loaded # Create a teacher account When I am on "/main/admin/user_add.php" - And I wait very long for the page to be loaded And I fill in the following: | firstname | Teacher | | lastname | Teacher | @@ -2029,7 +1912,6 @@ Feature: Special admin settings flows # Create session Present session with start = 2026-01-20 and end = 2026-02-03 When I am on "/main/session/session_add.php" - And I wait very long for the page to be loaded And I fill in the following: | name | Present session | | start_date | 2026-01-20 | @@ -2043,18 +1925,15 @@ Feature: Special admin settings flows When I press "Advanced settings" And I wait very long for the page to be loaded And I select "In progress" from "status" - And I wait very long for the page to be loaded # Set extra fields for the session When I fill in the following: | domaine | vie-quotidienne | And I select "vie-quotidienne" from "domaine" - And I wait very long for the page to be loaded When I fill in the following: | filiere | art-et-culture | And I select "art-et-culture" from "filiere" - And I wait very long for the page to be loaded # theme_fr and theme_de: type and select the suggested option When I fill in "theme_fr" with "theme1" @@ -2073,7 +1952,6 @@ Feature: Special admin settings flows And I select "1" from "participer_a_une_conversation" And I select "1" from "s_exprimer_oralement_en_continu" And I select "1" from "ecrire" - And I wait very long for the page to be loaded # Go to next step and include Testing course fr When I press "Next step" @@ -2091,11 +1969,9 @@ Feature: Special admin settings flows Scenario: Create future session "Session in the futur" and include course Given I am a platform administrator - And I wait very long for the page to be loaded # Create session Session in the futur with start = 2026-02-03 and end = 2026-02-17 When I am on "/main/session/session_add.php" - And I wait very long for the page to be loaded And I fill in the following: | name | Session in the futur | | start_date | 2026-02-03 | @@ -2109,13 +1985,10 @@ Feature: Special admin settings flows When I press "Advanced settings" And I wait very long for the page to be loaded And I select "Planned" from "status" - And I wait very long for the page to be loaded # Set extra fields for the session And I select "arrivee-sur-mon-poste-de-travail" from "domaine" - And I wait very long for the page to be loaded And I select "art-et-culture" from "filiere" - And I wait very long for the page to be loaded # theme_fr and theme_de: type and select the suggested option When I fill in "theme_fr" with "theme1" @@ -2134,7 +2007,6 @@ Feature: Special admin settings flows And I select "1" from "participer_a_une_conversation" And I select "1" from "s_exprimer_oralement_en_continu" And I select "1" from "ecrire" - And I wait very long for the page to be loaded # Go to next step and include Testing course fr When I press "Next step" @@ -2152,11 +2024,9 @@ Feature: Special admin settings flows Scenario: Create past session "Past session" and include course Given I am a platform administrator - And I wait very long for the page to be loaded # Create session Past session with start = 2026-01-06 and end = 2026-01-20 When I am on "/main/session/session_add.php" - And I wait very long for the page to be loaded And I fill in the following: | name | Past session | | start_date | 2026-01-06 | @@ -2170,13 +2040,10 @@ Feature: Special admin settings flows When I press "Advanced settings" And I wait very long for the page to be loaded And I select "Finished" from "status" - And I wait very long for the page to be loaded # Set extra fields for the session And I select "competente-dans-mon-domaine-de-specialite" from "domaine" - And I wait very long for the page to be loaded And I select "art-et-culture" from "filiere" - And I wait very long for the page to be loaded # theme_fr and theme_de: type and select the suggested option (theme2) When I fill in "theme_fr" with "theme2" @@ -2195,7 +2062,6 @@ Feature: Special admin settings flows And I select "1" from "participer_a_une_conversation" And I select "1" from "s_exprimer_oralement_en_continu" And I select "1" from "ecrire" - And I wait very long for the page to be loaded # Go to next step and include Testing course fr When I press "Next step" @@ -2213,11 +2079,9 @@ Feature: Special admin settings flows Scenario: Create future English session "Session in the futur en" and include course Given I am a platform administrator - And I wait very long for the page to be loaded # Create session Session in the futur en with start = 2026-02-03 and end = 2026-02-17 When I am on "/main/session/session_add.php" - And I wait very long for the page to be loaded And I fill in the following: | name | Session in the futur en | | start_date | 2026-02-03 | @@ -2231,13 +2095,10 @@ Feature: Special admin settings flows When I press "Advanced settings" And I wait very long for the page to be loaded And I select "Planned" from "status" - And I wait very long for the page to be loaded # Set extra fields for the session And I select "arrivee-sur-mon-poste-de-travail" from "domaine" - And I wait very long for the page to be loaded And I select "art-et-culture" from "filiere" - And I wait very long for the page to be loaded # theme_fr and theme_de: type and select the suggested option When I fill in "theme_fr" with "theme1" @@ -2256,7 +2117,6 @@ Feature: Special admin settings flows And I select "1" from "participer_a_une_conversation" And I select "1" from "s_exprimer_oralement_en_continu" And I select "1" from "ecrire" - And I wait very long for the page to be loaded # Go to next step and include Testing course en When I press "Next step" @@ -2275,9 +2135,7 @@ Feature: Special admin settings flows Scenario: Tare Down Given I am a platform administrator - And I wait very long for the page to be loaded And I am on "/admin" - And I wait very long for the page to be loaded When I fill in the following: diff --git a/tests/behat/features/actionInstall.feature b/tests/behat/features/actionInstall.feature index 14394e3979e..100c71194b4 100644 --- a/tests/behat/features/actionInstall.feature +++ b/tests/behat/features/actionInstall.feature @@ -3,7 +3,6 @@ Feature: Install portal Scenario: Installation process Given I am on "/main/install/index.php" - And I wait for the page to be loaded when ready Then I should see "Step 1 - Installation Language" Then I press "Next" Then I should see "Step 2 - Requirements" @@ -13,7 +12,6 @@ Feature: Install portal Then I check "accept_licence" Then I press "license-next" Then I should see "Step 4 - Database settings" - Then wait for the page to be loaded Then I fill in the following: | dbUsernameForm | root | | dbPassForm | root | @@ -32,7 +30,6 @@ Feature: Install portal Then I press "step5" And I wait for the page to be loaded Then I should see "Step 6 - Last check before install" - When I wait for the page to be loaded And I press "button_step6" And I wait one minute for the page to be loaded Then I should see "Step 7" diff --git a/tests/behat/features/actionUserCheck.feature b/tests/behat/features/actionUserCheck.feature index 4c9a12ec772..8cd942ad65b 100644 --- a/tests/behat/features/actionUserCheck.feature +++ b/tests/behat/features/actionUserCheck.feature @@ -3,7 +3,6 @@ Feature: User check after installation Scenario: Check admin information Given I am a platform administrator And I am on "/main/admin/user_list.php?keyword=admin" - And wait for the page to be loaded Then I should see "admin" Then I follow "John" And wait for the page to be loaded @@ -12,7 +11,6 @@ Feature: User check after installation Scenario: Check anon information Given I am a platform administrator And I am on "/main/admin/user_list.php?keyword=anon" - Then wait very long for the page to be loaded Then I should see "anon" Then I should see "anon" diff --git a/tests/behat/features/actionUserLogin.feature b/tests/behat/features/actionUserLogin.feature index 70915e4731a..2ebedc5319f 100644 --- a/tests/behat/features/actionUserLogin.feature +++ b/tests/behat/features/actionUserLogin.feature @@ -2,7 +2,6 @@ Feature: Login user Scenario: Login as admin user successfully Given I am on "/login" - And wait very long for the page to be loaded Then I should see "Sign in" When I fill in "admin" for "login" And I fill in "admin" for "password" diff --git a/tests/behat/features/adminChamiloOrgBlock.feature b/tests/behat/features/adminChamiloOrgBlock.feature index 1cb502a532e..c6bae84a31c 100644 --- a/tests/behat/features/adminChamiloOrgBlock.feature +++ b/tests/behat/features/adminChamiloOrgBlock.feature @@ -5,11 +5,9 @@ Feature: Admin Chamilo.org block navigation Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open Chamilo homepage Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Chamilo homepage" And I wait for the page to be loaded @@ -17,7 +15,6 @@ Feature: Admin Chamilo.org block navigation Scenario: Open User guides Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "User guides" And I wait for the page to be loaded @@ -25,7 +22,6 @@ Feature: Admin Chamilo.org block navigation Scenario: Open Chamilo forum Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Chamilo forum" And I wait for the page to be loaded @@ -33,7 +29,6 @@ Feature: Admin Chamilo.org block navigation Scenario: Open Installation guide Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Installation guide" And I wait for the page to be loaded @@ -41,7 +36,6 @@ Feature: Admin Chamilo.org block navigation Scenario: Open Changes in last version Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Changes in last version" And I wait for the page to be loaded @@ -49,7 +43,6 @@ Feature: Admin Chamilo.org block navigation Scenario: Open Contributors list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Contributors list" And I wait for the page to be loaded @@ -57,7 +50,6 @@ Feature: Admin Chamilo.org block navigation Scenario: Open Security guide Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Security guide" And I wait for the page to be loaded @@ -65,7 +57,6 @@ Feature: Admin Chamilo.org block navigation Scenario: Open Optimization guide Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Optimization guide" And I wait for the page to be loaded @@ -81,7 +72,6 @@ Feature: Admin Chamilo.org block navigation Scenario: Open Chamilo official services providers Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Chamilo official services providers" And I wait for the page to be loaded diff --git a/tests/behat/features/adminCourseBlock.feature b/tests/behat/features/adminCourseBlock.feature index 7136486bfe6..e01d4621033 100644 --- a/tests/behat/features/adminCourseBlock.feature +++ b/tests/behat/features/adminCourseBlock.feature @@ -5,11 +5,9 @@ Feature: Admin Course management block Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open Course list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Course list" And I wait for the page to be loaded @@ -17,7 +15,6 @@ Feature: Admin Course management block Scenario: Open Add course Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Add course" And I wait for the page to be loaded @@ -25,7 +22,6 @@ Feature: Admin Course management block Scenario: Open Export courses Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Export courses" And I wait for the page to be loaded @@ -33,7 +29,6 @@ Feature: Admin Course management block Scenario: Open Import courses list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Import courses list" And I wait for the page to be loaded @@ -41,7 +36,6 @@ Feature: Admin Course management block Scenario: Open Course categories Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Course categories" And I wait for the page to be loaded @@ -49,7 +43,6 @@ Feature: Admin Course management block Scenario: Open Add a user to a course Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Add a user to a course" And I wait for the page to be loaded @@ -57,7 +50,6 @@ Feature: Admin Course management block Scenario: Open Import users list (course block) Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Import users list" And I wait for the page to be loaded @@ -65,7 +57,6 @@ Feature: Admin Course management block Scenario: Open Manage extra fields for courses Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Manage extra fields for courses" And I wait for the page to be loaded @@ -73,7 +64,6 @@ Feature: Admin Course management block Scenario: Open Questions Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Questions" And I wait for the page to be loaded @@ -81,7 +71,6 @@ Feature: Admin Course management block Scenario: Open Resources sequencing Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Resources sequencing" And I wait for the page to be loaded diff --git a/tests/behat/features/adminFillCourses.feature b/tests/behat/features/adminFillCourses.feature index 509e6238758..64ced0c769c 100644 --- a/tests/behat/features/adminFillCourses.feature +++ b/tests/behat/features/adminFillCourses.feature @@ -5,9 +5,7 @@ Feature: Admin fill courses and subscribe users Scenario: Admin fills courses then subscribes a user to a course with long waits Given I am on "/main/admin/filler.php?fill=courses" - When wait very long for the page to be loaded When I am on "/main/admin/subscribe_user2course.php" - And wait very long for the page to be loaded And I select "ywarnier" from "UserList[]" And I select "(SOLARSYSTEM) Our solar system" from "CourseList[]" When I click the "button.btn--primary" element diff --git a/tests/behat/features/adminFillUsers.feature b/tests/behat/features/adminFillUsers.feature index 0dbd1dbd93a..259b7a1fd65 100644 --- a/tests/behat/features/adminFillUsers.feature +++ b/tests/behat/features/adminFillUsers.feature @@ -3,7 +3,6 @@ Feature: Fill users Scenario: Create tests users successfully Given I am a platform administrator Then I am on "/main/admin/filler.php?fill=users" - And I wait one minute for the page to be loaded Then I should see "Inserted" And I should not see an error diff --git a/tests/behat/features/adminHealthBlock.feature b/tests/behat/features/adminHealthBlock.feature index d42549dc6b4..107941a5f81 100644 --- a/tests/behat/features/adminHealthBlock.feature +++ b/tests/behat/features/adminHealthBlock.feature @@ -5,11 +5,9 @@ Feature: Admin Health check block Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open Health check Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Health check" And I wait for the page to be loaded @@ -17,7 +15,6 @@ Feature: Admin Health check block Scenario: See health warnings Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Health check" And I wait for the page to be loaded diff --git a/tests/behat/features/adminPlatformBlock.feature b/tests/behat/features/adminPlatformBlock.feature index 527debe6516..55a1325284e 100644 --- a/tests/behat/features/adminPlatformBlock.feature +++ b/tests/behat/features/adminPlatformBlock.feature @@ -5,11 +5,9 @@ Feature: Admin Platform management block Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open Configuration settings Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Configuration settings" And I wait for the page to be loaded @@ -17,7 +15,6 @@ Feature: Admin Platform management block Scenario: Open Languages Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Languages" And I wait for the page to be loaded @@ -25,7 +22,6 @@ Feature: Admin Platform management block Scenario: Open Plugins Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Plugins" And I wait for the page to be loaded @@ -33,7 +29,6 @@ Feature: Admin Platform management block Scenario: Open Regions Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Regions" And I wait for the page to be loaded @@ -41,7 +36,6 @@ Feature: Admin Platform management block Scenario: Open Portal news Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Portal news" And I wait for the page to be loaded @@ -49,7 +43,6 @@ Feature: Admin Platform management block Scenario: Open Global agenda Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Global agenda" And I wait for the page to be loaded @@ -57,7 +50,6 @@ Feature: Admin Platform management block Scenario: Open Import course events Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Import course events" And I wait for the page to be loaded @@ -65,7 +57,6 @@ Feature: Admin Platform management block Scenario: Open Pages Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Pages" And I wait for the page to be loaded @@ -73,7 +64,6 @@ Feature: Admin Platform management block Scenario: Open Setting the registration page Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Setting the registration page" And I wait for the page to be loaded @@ -81,7 +71,6 @@ Feature: Admin Platform management block Scenario: Open Statistics Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Statistics" And I wait for the page to be loaded @@ -89,7 +78,6 @@ Feature: Admin Platform management block Scenario: Open Reports Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Reports" And I wait for the page to be loaded @@ -97,7 +85,6 @@ Feature: Admin Platform management block Scenario: Open Teachers time report Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Teachers time report" And I wait for the page to be loaded @@ -105,7 +92,6 @@ Feature: Admin Platform management block Scenario: Open Extra fields Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Extra fields" And I wait for the page to be loaded @@ -113,7 +99,6 @@ Feature: Admin Platform management block Scenario: Open Configure multiple access URL Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Configure multiple access URL" And I wait for the page to be loaded @@ -121,7 +106,6 @@ Feature: Admin Platform management block Scenario: Open Mail templates Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Mail templates" And I wait for the page to be loaded @@ -129,7 +113,6 @@ Feature: Admin Platform management block Scenario: Open External tools (LTI) Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "External tools (LTI)" And I wait for the page to be loaded @@ -137,7 +120,6 @@ Feature: Admin Platform management block Scenario: Open Contact form categories Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Contact form categories" And I wait for the page to be loaded @@ -145,7 +127,6 @@ Feature: Admin Platform management block Scenario: Open System templates Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "System templates" And I wait for the page to be loaded diff --git a/tests/behat/features/adminSecurityBlock.feature b/tests/behat/features/adminSecurityBlock.feature index 1f0e8bf8783..55865524589 100644 --- a/tests/behat/features/adminSecurityBlock.feature +++ b/tests/behat/features/adminSecurityBlock.feature @@ -5,11 +5,9 @@ Feature: Admin Security block navigation Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open Login attempts Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Login attempts" And I wait for the page to be loaded diff --git a/tests/behat/features/adminSessionBlock.feature b/tests/behat/features/adminSessionBlock.feature index 3865e986f0d..5039159342e 100644 --- a/tests/behat/features/adminSessionBlock.feature +++ b/tests/behat/features/adminSessionBlock.feature @@ -5,11 +5,9 @@ Feature: Admin Sessions management block Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open Training sessions list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Training sessions list" And I wait for the page to be loaded @@ -17,7 +15,6 @@ Feature: Admin Sessions management block Scenario: Open Add a training session Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Add a training session" And I wait for the page to be loaded @@ -25,7 +22,6 @@ Feature: Admin Sessions management block Scenario: Open Sessions categories list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Sessions categories list" And I wait for the page to be loaded @@ -33,7 +29,6 @@ Feature: Admin Sessions management block Scenario: Open Import sessions list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Import sessions list" And I wait for the page to be loaded @@ -41,7 +36,6 @@ Feature: Admin Sessions management block Scenario: Open Import list of HR directors into sessions Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Import list of HR directors into sessions" And I wait for the page to be loaded @@ -49,7 +43,6 @@ Feature: Admin Sessions management block Scenario: Open Export sessions list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Export sessions list" And I wait for the page to be loaded @@ -57,7 +50,6 @@ Feature: Admin Sessions management block Scenario: Open Copy from course in session to another session Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Copy from course in session to another session" And I wait for the page to be loaded @@ -65,7 +57,6 @@ Feature: Admin Sessions management block Scenario: Open Move users results from base course to a session Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Move users results from base course to a session" And I wait for the page to be loaded @@ -73,7 +64,6 @@ Feature: Admin Sessions management block Scenario: Open Careers and promotions Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Careers and promotions" And I wait for the page to be loaded @@ -81,7 +71,6 @@ Feature: Admin Sessions management block Scenario: Open Manage session fields Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Manage session fields" And I wait for the page to be loaded @@ -89,7 +78,6 @@ Feature: Admin Sessions management block Scenario: Open Resources sequencing (sessions) Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Resources sequencing" And I wait for the page to be loaded @@ -97,7 +85,6 @@ Feature: Admin Sessions management block Scenario: Open Export all results from an exercise Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Export all results from an exercise" And I wait for the page to be loaded diff --git a/tests/behat/features/adminSettings.feature b/tests/behat/features/adminSettings.feature index 5a7f924d4d3..7503f9836e4 100644 --- a/tests/behat/features/adminSettings.feature +++ b/tests/behat/features/adminSettings.feature @@ -6,7 +6,6 @@ Feature: Settings update Scenario: Update 'profile' setting Given I am a platform administrator And I am on "/admin/settings/search_settings?keyword=changeable_options" - And wait for the page to be loaded And I select "Name" from "form_changeable_options" And I additionally select "E-mail" from "form_changeable_options" And I additionally select "Official code" from "form_changeable_options" @@ -18,7 +17,6 @@ Feature: Settings update Scenario: Update 'allow_registration' setting Given I am a platform administrator And I am on "/admin/settings/search_settings?keyword=allow_registration" - And wait for the page to be loaded And I select "Yes" from "form_allow_registration" And I press "Save" And wait for the page to be loaded @@ -27,7 +25,6 @@ Feature: Settings update Scenario: Update 'allow_group_categories' setting Given I am a platform administrator And I am on "/admin/settings/search_settings?keyword=allow_group_categories" - And wait for the page to be loaded And I select "Yes" from "form_allow_group_categories" And I press "Save" And wait for the page to be loaded diff --git a/tests/behat/features/adminSkillsBlock.feature b/tests/behat/features/adminSkillsBlock.feature index 4eebe124e02..073e1d4d3e1 100644 --- a/tests/behat/features/adminSkillsBlock.feature +++ b/tests/behat/features/adminSkillsBlock.feature @@ -5,11 +5,9 @@ Feature: Admin Skills block navigation Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open Skills wheel Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Skills wheel" And I wait for the page to be loaded @@ -17,7 +15,6 @@ Feature: Admin Skills block navigation Scenario: Open Skills import Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Skills import" And I wait for the page to be loaded @@ -25,7 +22,6 @@ Feature: Admin Skills block navigation Scenario: Open Manage skills Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Manage skills" And I wait for the page to be loaded @@ -33,7 +29,6 @@ Feature: Admin Skills block navigation Scenario: Open Manage skills levels Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Manage skills levels" And I wait for the page to be loaded @@ -41,7 +36,6 @@ Feature: Admin Skills block navigation Scenario: Open Skills ranking Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Skills ranking" And I wait for the page to be loaded @@ -49,7 +43,6 @@ Feature: Admin Skills block navigation Scenario: Open Skills and assessments Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Skills and assessments" And I wait for the page to be loaded diff --git a/tests/behat/features/adminSystemBlock.feature b/tests/behat/features/adminSystemBlock.feature index ce30124adda..494b19e775b 100644 --- a/tests/behat/features/adminSystemBlock.feature +++ b/tests/behat/features/adminSystemBlock.feature @@ -5,11 +5,9 @@ Feature: Admin System block navigation Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open Clean temporary files Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Clean temporary files" And I wait for the page to be loaded @@ -17,7 +15,6 @@ Feature: Admin System block navigation Scenario: Open Special exports Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Special exports" And I wait for the page to be loaded @@ -25,7 +22,6 @@ Feature: Admin System block navigation Scenario: Open System status Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "System status" And I wait for the page to be loaded @@ -33,7 +29,6 @@ Feature: Admin System block navigation Scenario: Open Data filler Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Data filler" And I wait for the page to be loaded @@ -41,7 +36,6 @@ Feature: Admin System block navigation Scenario: Open E-mail tester Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "E-mail tester" And I wait for the page to be loaded @@ -49,7 +43,6 @@ Feature: Admin System block navigation Scenario: Open Tickets Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Tickets" And I wait for the page to be loaded @@ -57,7 +50,6 @@ Feature: Admin System block navigation Scenario: Open Update session status Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Update session status" And I wait for the page to be loaded @@ -65,7 +57,6 @@ Feature: Admin System block navigation Scenario: Open Colors Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Colors" And I wait for the page to be loaded @@ -73,7 +64,6 @@ Feature: Admin System block navigation Scenario: Open File info Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "File info" And I wait for the page to be loaded @@ -81,7 +71,6 @@ Feature: Admin System block navigation Scenario: Open Resources by type Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Resources by type" And I wait for the page to be loaded diff --git a/tests/behat/features/adminUserBlock.feature b/tests/behat/features/adminUserBlock.feature index 9b04001306c..d6ebf770c0a 100644 --- a/tests/behat/features/adminUserBlock.feature +++ b/tests/behat/features/adminUserBlock.feature @@ -5,11 +5,9 @@ Feature: Admin User management block Background: Given I am a platform administrator - And I wait for the page to be loaded Scenario: Open User list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "User list" And I wait for the page to be loaded @@ -17,7 +15,6 @@ Feature: Admin User management block Scenario: Open Add a user Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Add a user" And I wait for the page to be loaded @@ -25,7 +22,6 @@ Feature: Admin User management block Scenario: Open Export users list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Export users list" And I wait for the page to be loaded @@ -33,7 +29,6 @@ Feature: Admin User management block Scenario: Open Import users list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Import users list" And I wait for the page to be loaded @@ -41,7 +36,6 @@ Feature: Admin User management block Scenario: Open Edit users list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Edit users list" And I wait for the page to be loaded @@ -49,7 +43,6 @@ Feature: Admin User management block Scenario: Open Anonymise users list Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Anonymise users list" And I wait for the page to be loaded @@ -57,7 +50,6 @@ Feature: Admin User management block Scenario: Open Profiling Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Profiling" And I wait for the page to be loaded @@ -65,7 +57,6 @@ Feature: Admin User management block Scenario: Open Classes Given I am on "/admin" - And I wait for the page to be loaded And I zoom out to maximum And I follow "Classes" And I wait for the page to be loaded diff --git a/tests/behat/features/bootstrap/FeatureContext.php b/tests/behat/features/bootstrap/FeatureContext.php index 1141d17a6c9..cac67e6fe91 100644 --- a/tests/behat/features/bootstrap/FeatureContext.php +++ b/tests/behat/features/bootstrap/FeatureContext.php @@ -16,6 +16,48 @@ public function __construct() { } + /** + * Clean up test users created by createUser.feature before the feature runs. + * Prevents stale state from a previous aborted run from causing cascading failures. + * + * @BeforeFeature @administration + */ + public static function cleanUpTestUsers(\Behat\Behat\Hook\Scope\BeforeFeatureScope $scope): void + { + $testUsernames = ['smarshall', 'hrm', 'teacher', 'student']; + // Locate .env (two directories up from bootstrap/) + $envFile = __DIR__.'/../../../../.env'; + $cfg = ['DATABASE_HOST' => 'localhost', 'DATABASE_PORT' => '3306', 'DATABASE_NAME' => '', 'DATABASE_USER' => '', 'DATABASE_PASSWORD' => '']; + if (is_file($envFile)) { + foreach (file($envFile) as $line) { + $line = trim($line); + if ('' === $line || str_starts_with($line, '#')) { + continue; + } + foreach (array_keys($cfg) as $key) { + if (str_starts_with($line, $key.'=')) { + $val = substr($line, strlen($key) + 1); + $cfg[$key] = trim($val, "\"' \t"); + } + } + } + } + if ('' === $cfg['DATABASE_NAME']) { + return; + } + try { + $pdo = new \PDO( + "mysql:host={$cfg['DATABASE_HOST']};port={$cfg['DATABASE_PORT']};dbname={$cfg['DATABASE_NAME']};charset=utf8mb4", + $cfg['DATABASE_USER'], + $cfg['DATABASE_PASSWORD'] + ); + $placeholders = implode(',', array_fill(0, count($testUsernames), '?')); + $pdo->prepare("DELETE FROM user WHERE username IN ($placeholders)")->execute($testUsernames); + } catch (\Throwable $e) { + echo "\n[BeforeFeature] Could not clean up test users: ".$e->getMessage()."\n"; + } + } + /** * @Given /^I am a platform administrator$/ */ @@ -24,6 +66,77 @@ public function iAmAPlatformAdministrator() $this->iAmLoggedAs('admin'); } + /** + * Directly creates a USER_RELATION_TYPE_RRHH (type 7) relationship so an HRM + * user can "login as" the target user. Bypasses the legacy PHP dual-list UI + * which is brittle (option text includes "(username)" suffix that Mink can't match). + * + * @Given /^"([^"]*)" follows "([^"]*)" as HRM$/ + */ + public function userFollowsAsHrm(string $hrmUsername, string $targetUsername): void + { + $pdo = $this->getTestPdo(); + $stmt = $pdo->prepare( + 'SELECT id FROM user WHERE username = ?' + ); + $stmt->execute([$hrmUsername]); + $hrmId = $stmt->fetchColumn(); + $stmt->execute([$targetUsername]); + $targetId = $stmt->fetchColumn(); + if (!$hrmId || !$targetId) { + throw new \RuntimeException("Could not find hrm='$hrmUsername' (id=$hrmId) or target='$targetUsername' (id=$targetId)."); + } + // USER_RELATION_TYPE_RRHH = 7. + // Direction matches UserManager::subscribeUsersToUser: user_id=target, friend_user_id=HRM + // (getUsersFollowedByUser queries WHERE friend_user_id = HRM_ID) + $pdo->prepare( + 'INSERT IGNORE INTO user_rel_user (user_id, friend_user_id, relation_type) VALUES (?, ?, 7)' + )->execute([$targetId, $hrmId]); + } + + /** + * Navigate directly to the myStudents tracking page for a given username. + * Looks up the user ID from the database so tests don't need to hard-code IDs. + * + * @Given /^I am on the tracking page for "([^"]*)"$/ + */ + public function iAmOnTrackingPageFor(string $username): void + { + $pdo = $this->getTestPdo(); + $stmt = $pdo->prepare('SELECT id FROM user WHERE username = ?'); + $stmt->execute([$username]); + $userId = $stmt->fetchColumn(); + if (!$userId) { + throw new \RuntimeException("User '$username' not found in database."); + } + $this->visit('/main/my_space/myStudents.php?student='.(int) $userId); + $this->waitForThePageToBeLoaded(); + } + + private function getTestPdo(): \PDO + { + $envFile = __DIR__.'/../../../../.env'; + $cfg = ['DATABASE_HOST' => 'localhost', 'DATABASE_PORT' => '3306', 'DATABASE_NAME' => '', 'DATABASE_USER' => '', 'DATABASE_PASSWORD' => '']; + if (is_file($envFile)) { + foreach (file($envFile) as $line) { + $line = trim($line); + if ('' === $line || str_starts_with($line, '#')) { + continue; + } + foreach (array_keys($cfg) as $key) { + if (str_starts_with($line, $key.'=')) { + $cfg[$key] = trim(substr($line, strlen($key) + 1), "\"' \t"); + } + } + } + } + return new \PDO( + "mysql:host={$cfg['DATABASE_HOST']};port={$cfg['DATABASE_PORT']};dbname={$cfg['DATABASE_NAME']};charset=utf8mb4", + $cfg['DATABASE_USER'], + $cfg['DATABASE_PASSWORD'] + ); + } + /** * @Given /^I am a teacher$/ */ @@ -91,8 +204,8 @@ public function courseIsDeleted($argument): void public function iAmOnCourseXHomepage($courseCode): void { $this->visit('/main/course_home/redirect.php?cidReq='.$courseCode); - $this->waitForThePageToBeLoaded(); - //$this->visit('/courses/'.$courseCode.'/index.php'); + // Course tools are loaded asynchronously via API after Vue mounts + $this->waitForSelector('#course-tools a', 10000); $this->assertElementNotOnPage('.alert-danger'); } @@ -103,7 +216,7 @@ public function iAmOnCourseXHomepage($courseCode): void public function iAmOnCourseXHomepageInSessionY($courseCode, $sessionName): void { $this->visit('/main/course_home/redirect.php?cidReq='.$courseCode.'&session_name='.$sessionName); - $this->waitForThePageToBeLoaded(); + $this->waitForSelector('#course-tools a', 10000); $this->assertElementNotOnPage('.alert-danger'); } @@ -113,8 +226,7 @@ public function iAmOnCourseXHomepageInSessionY($courseCode, $sessionName): void public function iAmOnTheHomepageOfCourseX($courseId): void { $this->visit('/course/'.$courseId.'/home'); - $this->waitForThePageToBeLoaded(); - //$this->visit('/courses/'.$courseCode.'/index.php'); + $this->waitForSelector('#course-tools a', 10000); $this->assertElementNotOnPage('.alert-danger'); } @@ -124,7 +236,7 @@ public function iAmOnTheHomepageOfCourseX($courseId): void public function iAmOnTheHomepageOfCourseXInSessionY($courseId, $sessionId): void { $this->visit('/course/'.$courseId.'&sid='.$sessionId); - $this->waitForThePageToBeLoaded(); + $this->waitForSelector('#course-tools a', 10000); $this->assertElementNotOnPage('.alert-danger'); } @@ -142,14 +254,60 @@ public function iAmAXUser($argument) */ public function iAmLoggedAs($username) { - //$this->visit('/logout'); - $this->visit('/login'); - $this->waitForThePageToBeLoaded(); - $this->fillField('login', $username); - $this->fillField('password', $username); - $this->pressButton('Sign in'); + $passwords = [ + 'admin' => 'admin11+', + ]; + $password = $passwords[$username] ?? $username; + + if ($this->getSession()->isStarted()) { + parent::visit($this->getMinkParameter('base_url').'/logout'); + $this->getSession()->reset(); + } + + // Visit login to establish a fresh PHP session (creates the session cookie) + parent::visit($this->getMinkParameter('base_url').'/login'); + $this->getSession()->wait(4000, "document.readyState === 'complete'"); + + // Clear stale auth data from previous sessions so Vue starts fresh + $this->getSession()->executeScript( + 'try { localStorage.clear(); sessionStorage.clear(); } catch(e) {}' + ); + + // Authenticate via synchronous XHR — bypasses the Vue form entirely, + // immune to race conditions, throttle counter resets after success. + $u = addslashes($username); + $p = addslashes($password); + // Retry up to 3 times — PHP session GC intermittently causes 500 when + // /var/lib/php/sessions is not accessible (Permission denied on gc cleanup). + $status = 0; + $body = ''; + for ($attempt = 0; $attempt < 3; $attempt++) { + if ($attempt > 0) { + $this->getSession()->wait(1000); + } + $result = $this->getSession()->evaluateScript( + "(function(){ + var x = new XMLHttpRequest(); + x.open('POST', '/login_json', false); + x.setRequestHeader('Content-Type', 'application/json'); + x.send(JSON.stringify({username:'$u', password:'$p'})); + return {status: x.status, body: x.responseText.substring(0, 300)}; + })()" + ); + $status = (int) ($result['status'] ?? 0); + $body = (string) ($result['body'] ?? ''); + if (200 === $status) { + break; + } + } + + if (200 !== $status) { + throw new \Exception("Login failed for '$username' after 3 attempts — HTTP $status. Body: $body"); + } + + // Warm up the legacy PHP session bridge: LegacyListener sets _user in session + $this->visit('/admin'); $this->waitForThePageToBeLoaded(); - //$this->waitForThePageToBeLoaded(); } /** @@ -159,12 +317,28 @@ public function iAmLoggedAs($username) */ public function iShouldNotSeeAnError() { - $this->assertSession()->pageTextNotContains('Internal server error'); - $this->assertSession()->pageTextNotContains('error'); - $el = $this->getSession()->getPage()->find( - 'css', - '.alert-danger' + // Wait for page to have visible content before checking (avoids false empty-body reads) + $this->getSession()->wait( + 5000, + "document.readyState === 'complete' && document.body && (document.body.innerText || '').trim().length > 0" ); + // Use JS for text checks — atomic, avoids stale-element on Vue re-renders + $text = strtolower((string) $this->getSession()->evaluateScript( + 'return document.body ? (document.body.innerText || document.body.textContent || "") : ""' + )); + if (str_contains($text, 'internal server error')) { + throw new \Behat\Mink\Exception\ExpectationException( + 'Page contains "Internal server error"', + $this->getSession() + ); + } + if (str_contains($text, 'error')) { + throw new \Behat\Mink\Exception\ExpectationException( + 'Page contains "error"', + $this->getSession() + ); + } + $el = $this->getSession()->getPage()->find('css', '.alert-danger'); if (null !== $el) { $this->assertSession()->elementAttributeContains('css', '.alert-danger', 'style', 'display:none;'); } else { @@ -234,7 +408,9 @@ public function iHaveAPublicPasswordProtectedCourse($code, $password) */ public function iAmNotLogged() { - $this->visit('/logout'); + if ($this->getSession()->isStarted()) { + $this->getSession()->reset(); + } } /** @@ -395,52 +571,72 @@ public function iFillInAjaxSelectInputWithAndSelect($field, $id, $value) */ public function confirmPopup() { - $session = $this->getSession(); - // 1) accept_alert() (alert native) + $session = $this->getSession(); + + // 1) Native browser alert try { - $driver = $session->getDriver(); + $session->getDriver()->getWebDriverSession()->accept_alert(); + return; + } catch (\Exception $e) {} + + // 2) PrimeVue ConfirmDialog: wait for dialog to appear AND animation to finish + $session->wait(5000, "document.querySelector('.p-confirmdialog') !== null || document.querySelector('.swal2-container') !== null"); + // Wait until dialog is present AND its enter animation is complete + $session->wait(2000, + "(function(){ var d = document.querySelector('.p-confirmdialog'); " . + "return d && !d.classList.contains('p-dialog-enter-active') && !d.classList.contains('p-dialog-enter-from'); })()" + ); + $js = <<<'JS' + (function(){ + function click(el) { + if (!el) return false; + try { el.style.pointerEvents = 'auto'; el.style.zIndex = 999999; } catch(e){} try { - $driver->getWebDriverSession()->accept_alert(); - return; - } catch (\Exception $e) {} + el.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window})); + return true; + } catch(e) {} + try { el.click(); return true; } catch(e) { return false; } + } + // PrimeVue ConfirmDialog: target accept button by its specific class + var dlg = document.querySelector('.p-confirmdialog'); + if (dlg) { + var acceptBtn = dlg.querySelector('.p-confirmdialog-accept-button'); + if (click(acceptBtn)) return true; + // Fallback: button with text "Yes" or "Oui" + var btns = dlg.querySelectorAll('button'); + for (var i = 0; i < btns.length; i++) { + if ((btns[i].textContent||'').trim() === 'Yes' || (btns[i].textContent||'').trim() === 'Oui') { + if (click(btns[i])) return true; + } + } + } + // SweetAlert2 fallback + var swal = document.querySelector('.swal2-container'); + if (swal) { + var el = swal.querySelector('.swal2-confirm'); + if (click(el)) return true; + } + return false; + })(); + JS; + // executeScript may return null if the accept handler navigates away (form.submit()). + // In that case the confirmation DID succeed, so we treat null as "clicked". + try { + $result = $session->executeScript($js); } catch (\Exception $e) { - // ignore + // Page navigation during script execution — confirmation was accepted + return; } - // wait for the HTML modal - $session->wait(5000, "document.querySelector('.swal2-container') !== null"); + if (null === $result) { + // Page navigated away during script execution — confirmation was accepted + return; + } - // JS: attempt to click a visible confirmation button inside the modal - $js = <<<'JS' - (function(){ - function isVisible(el){ - if(!el) return false; - var rect = el.getBoundingClientRect(); - return !!(rect.width || rect.height) && window.getComputedStyle(el).visibility !== 'hidden' && window.getComputedStyle(el).display !== 'none'; - } - function clickEl(el){ - if(!el) return false; - try { el.style.pointerEvents = 'auto'; el.style.zIndex = 999999; } catch(e){} - try { if(el.focus) el.focus(); el.click(); return true; } catch(e){ - } - } - // attempt to click a visible confirmation button inside the modal - var modal = document.querySelector('.swal2-container'); - - var el = modal.querySelector('.swal2-confirm'); - if (el && isVisible(el)) { - if (clickEl(el)) return true; - } - return false; - })(); - JS; - try { - $clicked = (bool) $session->executeScript($js); - if ($clicked) - return; - } catch (\Exception $e) { + if (!(bool) $result) { + // Dialog was still present but nothing was clickable — true failure throw new \Exception('confirmPopup: no confirmation button found or clickable'); } } @@ -524,29 +720,287 @@ public function iFillInSelectWithOptionValue($field, $value, $class) /** * @When /^(?:|I )wait for the page to be loaded$/ + * @When /^wait the page to be loaded when ready$/ */ - public function waitForThePageToBeLoaded() + public function waitForThePageToBeLoaded(): void { - $this->getSession()->wait(8000); + // Brief sleep allows any in-flight navigation (form submit, redirect) to start + // before we begin polling; without it, the condition can fire on the old page. + $this->getSession()->wait(300); + $this->getSession()->wait( + 8000, + "document.readyState === 'complete' && " . + "(document.querySelector('#app') === null || document.querySelector('#app').children.length > 0) && " . + "(document.querySelector('#sectionMainContent') === null || document.querySelector('#sectionMainContent').style.display !== 'none')" + ); } /** * @When /^(?:|I )wait very long for the page to be loaded$/ */ - public function waitVeryLongForThePageToBeLoaded() + public function waitVeryLongForThePageToBeLoaded(): void { - //$this->getSession()->wait(10000, "document.readyState === 'complete'"); - $this->getSession()->wait(14000); + // Sleep gives the browser time to start any in-flight navigation (form submit, + // redirect) before we begin polling; without it the condition fires immediately + // on the old page (which already satisfies readyState=complete). + $this->getSession()->wait(1500); + $this->getSession()->wait( + 14000, + "document.readyState === 'complete' && " . + "(document.querySelector('#app') === null || document.querySelector('#app').children.length > 0) && " . + "(document.querySelector('#sectionMainContent') === null || document.querySelector('#sectionMainContent').style.display !== 'none')" + ); } /** * @When /^(?:|I )wait for the page to be loaded when ready$/ */ - public function waitForThePageToBeLoadedWhenReady() + public function waitForThePageToBeLoadedWhenReady(): void { $this->getSession()->wait(9000, "document.readyState === 'complete'"); } + /** + * @When /^(?:|I )wait for the "([^"]*)" element$/ + */ + public function waitForSelector(string $css, int $timeoutMs = 8000): void + { + $escaped = addslashes($css); + $this->getSession()->wait($timeoutMs, "document.querySelector('$escaped') !== null"); + } + + /** + * @When /^(?:|I )wait until the URL contains "([^"]*)"$/ + */ + public function waitUntilUrlContains(string $fragment): void + { + $escaped = addslashes($fragment); + $this->getSession()->wait(10000, "window.location.href.indexOf('$escaped') !== -1"); + } + + /** + * Trigger a Vue Router push to the current URL. + * Fixes the issue where lazy route components don't render on initial full-page load + * because the component factory is never called until a SPA navigation occurs. + * Uses a roundtrip via /home (eagerly loaded) to avoid NavigationDuplicated. + * + * @When /^I trigger Vue SPA navigation$/ + */ + public function triggerVueSpaNavigation(): void + { + $this->getSession()->executeScript( + '(function(){ + window.__vueSpaNavDone__ = false; + window.__vueSpaNavError__ = null; + var app = document.getElementById("app"); + var vueApp = app && app.__vue_app__; + if (!vueApp) { window.__vueSpaNavDone__ = true; return; } + var router = vueApp.config.globalProperties.$router; + if (!router) { window.__vueSpaNavDone__ = true; return; } + var targetPath = router.currentRoute.value.fullPath; + // Use force:true to bypass NavigationDuplicated and trigger a real re-navigation + router.push({ path: targetPath, force: true }).then(function() { + // Wait for nextTick to ensure DOM is committed after vnode update + var nextTick = vueApp.config.globalProperties.$nextTick || Promise.resolve.bind(Promise); + return nextTick(); + }).then(function() { + window.__vueSpaNavDone__ = true; + }).catch(function(err) { + window.__vueSpaNavError__ = err ? (err.message || String(err)) : "unknown"; + window.__vueSpaNavDone__ = true; + }); + })()' + ); + $result = $this->getSession()->wait(20000, "window.__vueSpaNavDone__ === true"); + if (!$result) { + throw new \RuntimeException('Vue SPA navigation did not complete within 20 seconds.'); + } + $error = $this->getSession()->evaluateScript('return window.__vueSpaNavError__'); + if ($error) { + echo "\n[Vue nav notice]: $error\n"; + } + // Wait for Vue DOM updates to commit (scheduler flushes async) + usleep(3000000); + } + + /** + * @When /^I wait (\d+) seconds for the "([^"]*)" element$/ + */ + public function waitSecondsForSelector(int $seconds, string $css): void + { + $this->waitForSelector($css, $seconds * 1000); + } + + /** + * Dump browser console logs (errors, warnings) captured by ChromeDriver. + * + * @When /^I dump browser console logs$/ + */ + public function iDumpBrowserConsoleLogs(): void + { + $driver = $this->getSession()->getDriver(); + if (!$driver instanceof \Behat\Mink\Driver\Selenium2Driver) { + echo "\n[console logs] Driver is not Selenium2\n"; + return; + } + try { + $logs = $driver->getWebDriverSession()->log('browser'); + echo "\n=== BROWSER CONSOLE LOGS (" . count($logs) . " entries) ===\n"; + foreach ($logs as $entry) { + $level = $entry['level'] ?? '?'; + $msg = $entry['message'] ?? ''; + echo "[$level] $msg\n"; + } + echo "=== END CONSOLE LOGS ===\n"; + } catch (\Throwable $e) { + echo "\n[console logs] Could not retrieve: " . $e->getMessage() . "\n"; + } + } + + /** + * Wait until the page's visible text contains the given string (polls until timeout). + * Use this instead of waitForSelector+assertPageContainsText when the content + * arrives asynchronously (Vue SPAs, lazy-loaded data) to avoid race conditions + * where the element exists but its text hasn't been populated yet. + * + * @When /^I wait until I see "([^"]*)"$/ + * @When /^wait until I see "([^"]*)"$/ + */ + public function iWaitUntilISee(string $text): void + { + $escaped = addslashes($text); + $result = $this->getSession()->wait( + 45000, + "(document.body ? (document.body.innerText || document.body.textContent || '') : '').indexOf('$escaped') !== -1" + ); + if (!$result) { + // Debug: dump final state before throwing + $debug = (string) $this->getSession()->evaluateScript( + '(function(){ + var app = document.getElementById("app"); + var vueApp = app && app.__vue_app__; + if (!vueApp) return "no vueApp"; + var router = vueApp.config.globalProperties.$router; + var route = router ? router.currentRoute.value.name : "no router"; + var pinia = vueApp.config.globalProperties.$pinia; + var isAdmin = false; + var isLoading = "?"; + if (pinia && pinia.state.value.security) { + var s = pinia.state.value.security; + isLoading = s.isLoading; + isAdmin = !!(s.user && s.user.roles && (s.user.roles.indexOf("ROLE_ADMIN") !== -1 || s.user.roles.indexOf("ROLE_GLOBAL_ADMIN") !== -1)); + } + var adminIdx = document.querySelector(".admin-index"); + var chunks = window.webpackChunkChamilo ? window.webpackChunkChamilo.length : "N/A"; + var bodyText = document.body ? (document.body.innerText || "").substring(0, 300) : "nobody"; + return "route="+route+" isAdmin="+isAdmin+" isLoading="+isLoading+" chunks="+chunks+" adminIdx="+(!!adminIdx)+" body="+bodyText; + })()' + ); + echo "\n[iWaitUntilISee debug] $debug\n"; + throw new \RuntimeException("Text '$text' did not appear on the page within 12 seconds."); + } + } + + /** + * @When /^I dump the page body text$/ + */ + public function iDumpThePageBodyText(): void + { + $text = (string) $this->getSession()->evaluateScript( + 'return document.body ? (document.body.innerText || document.body.textContent || "BODY_EMPTY") : "NO_BODY"' + ); + echo "\n=== PAGE BODY TEXT (first 2000 chars) ===\n"; + echo mb_substr($text, 0, 2000) . "\n"; + echo "=== URL: " . $this->getSession()->getCurrentUrl() . " ===\n"; + + $debug = (string) $this->getSession()->evaluateScript( + 'return (function() { + var info = {}; + info.url = window.location.href; + info.chunks = window.webpackChunkChamilo ? window.webpackChunkChamilo.length : "N/A"; + var app = document.getElementById("app"); + var vueApp = app && app.__vue_app__; + if (!vueApp) { info.vue = "no vueApp"; return JSON.stringify(info); } + var router = vueApp.config.globalProperties.$router; + if (router) { + info.route = router.currentRoute.value.name; + info.path = router.currentRoute.value.fullPath; + info.matched = router.currentRoute.value.matched.length; + // Check what component factories the matched records have + info.matchedComponents = router.currentRoute.value.matched.map(function(r) { + var c = r.components && r.components.default; + return typeof c === "function" ? "lazy:"+c.name : (typeof c === "object" ? "eager" : typeof c); + }); + } + var pinia = vueApp.config.globalProperties.$pinia; + if (pinia) { + var stores = Object.keys(pinia.state.value); + info.stores = stores; + if (pinia.state.value.security) { + info.isAuthenticated = !!(pinia.state.value.security.user && pinia.state.value.security.user.id); + info.isLoading = pinia.state.value.security.isLoading; + } + if (pinia.state.value.platformConfig) { + info.platformIsLoading = pinia.state.value.platformConfig.isLoading; + } + } + var adminIndex = document.querySelector(".admin-index"); + info.adminIndexExists = !!adminIndex; + // Check for AdminBlock/PrimeVue elements + info.pPanelCount = document.querySelectorAll(".p-panel, .p-card, [class*=admin]").length; + // Check app-main + var appMain = document.querySelector(".app-main"); + info.appMainChildCount = appMain ? appMain.childNodes.length : 0; + // Dump the full app-main innerHTML for analysis + info.appMainFull = appMain ? appMain.innerHTML.substring(0, 500) : "null"; + // Walk Vue component tree to find RouterView and inspect its state + try { + var root = vueApp._instance; + var treeLines = []; + function walkTree(vnode, depth) { + if (!vnode || depth > 15) return; + var typeName = "?"; + if (!vnode.type) typeName = "null"; + else if (typeof vnode.type === "string") typeName = "<"+vnode.type+">"; + else if (typeof vnode.type === "symbol") typeName = "Fragment"; + else if (vnode.type.__name) typeName = vnode.type.__name; + else if (vnode.type.name) typeName = vnode.type.name; + else typeName = typeof vnode.type; + var indent = " ".repeat(depth); + var extra = ""; + if (vnode.component && vnode.component.setupState) { + var ss = vnode.component.setupState; + if (ss.matchedRouteRef !== undefined) { + extra += " [RV matched="+(ss.matchedRouteRef && ss.matchedRouteRef.value ? (ss.matchedRouteRef.value.path || "ok") : "null")+"]"; + } + } + treeLines.push(indent + typeName + extra); + if (vnode.component) { + walkTree(vnode.component.subTree, depth + 1); + } else if (Array.isArray(vnode.children)) { + vnode.children.forEach(function(c) { walkTree(c, depth + 1); }); + } + } + walkTree(root.subTree, 0); + info.tree = treeLines.join("\n"); + } catch(e) { info.tree = "error: "+e.message; } + return JSON.stringify(info); + })()' + ); + echo "=== VUE STATE ===\n" . json_encode(json_decode($debug), JSON_PRETTY_PRINT) . "\n"; + } + + /** + * @When /^I wait for jqGrid to load$/ + */ + public function waitForJqGridToLoad(): void + { + // Step 1: wait for jqGrid to initialize (fires in $(document).ready, same tick as readyState===complete) + $this->getSession()->wait(5000, "document.querySelector('.ui-jqgrid') !== null"); + // Step 2: wait for jqGrid's AJAX data fetch to complete + $this->getSession()->wait(8000, "typeof jQuery !== 'undefined' && jQuery.active === 0"); + } + /** * @When /^(?:|I )wait one minute for the page to be loaded$/ */ @@ -692,7 +1146,7 @@ public function iAmStudentSubscribedToXSession($sessionName) $this->pressButton('Next step'); $this->assertPageContainsText('Update successful'); $this->fillField('user_to_add', 'acostea'); - $this->waitForThePageToBeLoaded(); + $this->getSession()->wait(3000); // wait for autocomplete results, not page load $this->clickLink('Costea Andrea (acostea)'); $this->pressButton('Finish session creation'); $this->assertPageContainsText('Session overview'); @@ -773,10 +1227,25 @@ public function assertPageContainsTable($tableId, TableNode $tableData) */ public function iClickTheElement($selector) { - $page = $this->getSession()->getPage(); - $element = $page->find('css', $selector); - - $element->click(); + $this->waitForSelector($selector, 8000); + $escaped = addslashes($selector); + // Scroll element into view so it is interactable even when off-screen, + // then use JavaScript click - avoids sticky-header occlusion issues with WebDriver physical clicks. + $exists = $this->getSession()->evaluateScript( + "!!document.querySelector('$escaped')" + ); + if (!$exists) { + throw new \RuntimeException("Element '$selector' not found on page."); + } + $this->getSession()->executeScript( + "(function(){ + var el = document.querySelector('$escaped'); + el.scrollIntoView({behavior:'instant',block:'center'}); + // If the element is inside a button, click the button so Vue event handlers fire. + var clickTarget = el.closest('button') || el.closest('a') || el; + clickTarget.click(); + })();" + ); } /** @@ -849,10 +1318,64 @@ public function zoomOutMax() return true; } + public function fillField($field, $value): void + { + $field = $this->fixStepArgument($field); + $value = $this->fixStepArgument($value); + + $usedNative = false; + try { + $this->getSession()->getPage()->fillField($field, $value); + $usedNative = true; + } catch (\Exception $e) { + if (false === strpos($e->getMessage(), 'interactable') && false === strpos($e->getMessage(), 'ElementNotInteractable')) { + throw $e; + } + } + + // After native fill, verify the value was actually set (Selenium sendKeys can silently + // drop non-ASCII characters like accented letters). If mismatch, fall through to JS. + if ($usedNative) { + $element = $this->getSession()->getPage()->findField($field); + if ($element) { + $actualValue = $element->getValue(); + if ($actualValue === $value) { + return; + } + } else { + return; + } + } + + // PrimeVue float-label elements have the