diff --git a/local_moodleappbehat/tests/behat/behat_app.php b/local_moodleappbehat/tests/behat/behat_app.php index 7a815ec17..04395fbaf 100644 --- a/local_moodleappbehat/tests/behat/behat_app.php +++ b/local_moodleappbehat/tests/behat/behat_app.php @@ -237,13 +237,21 @@ class behat_app extends behat_app_helper { /** * Trigger swipe gesture. * - * @When /^I swipe to the (left|right) in the app$/ + * @When /^I swipe to the (left|right) (in (".+") )?in the app$/ * @param string $direction Swipe direction + * @param bool $hasLocator Whether a reference locator is used. + * @param string $locator Reference locator. */ - public function i_swipe_in_the_app(string $direction) { - $method = 'swipe' . ucwords($direction); + public function i_swipe_in_the_app(string $direction, bool $hasLocator = false, string $locator = '') { + if ($hasLocator) { + $locator = $this->parse_element_locator($locator); + } - $this->zone_js("getAngularInstance('ion-content', 'CoreSwipeNavigationDirective').$method()"); + $result = $this->zone_js("swipe('$direction'" . ($hasLocator ? ", $locator" : '') . ')'); + + if ($result !== 'OK') { + throw new DriverException('Error when swiping - ' . $result); + } $this->wait_for_pending_js(); diff --git a/src/addons/mod/book/components/index/addon-mod-book-index.html b/src/addons/mod/book/components/index/addon-mod-book-index.html index 380582d58..b186dfb3c 100644 --- a/src/addons/mod/book/components/index/addon-mod-book-index.html +++ b/src/addons/mod/book/components/index/addon-mod-book-index.html @@ -24,8 +24,8 @@ (click)="openBook(chapter.id)">

- {{chapter.indexNumber}}  - •  + {{chapter.indexNumber}} +

diff --git a/src/addons/mod/book/components/toc/toc.html b/src/addons/mod/book/components/toc/toc.html index 42165ea28..663370ab8 100644 --- a/src/addons/mod/book/components/toc/toc.html +++ b/src/addons/mod/book/components/toc/toc.html @@ -17,8 +17,8 @@ [attr.aria-current]="selected == chapter.id ? 'page' : 'false'" button [class.item-dimmed]="chapter.hidden" detail="false">

- {{chapter.indexNumber}}  - •  + {{chapter.indexNumber}} +

diff --git a/src/addons/mod/book/services/book.ts b/src/addons/mod/book/services/book.ts index 8681ef369..2365c5291 100644 --- a/src/addons/mod/book/services/book.ts +++ b/src/addons/mod/book/services/book.ts @@ -291,7 +291,9 @@ export class AddonModBookProvider { }); } - chapterNumber++; + if (!parseInt(chapter.hidden, 10)) { + chapterNumber++; + } }); return chapters; diff --git a/src/addons/mod/book/tests/behat/basic_usage.feature b/src/addons/mod/book/tests/behat/basic_usage.feature index 6e24b7b2a..65a09b54e 100755 --- a/src/addons/mod/book/tests/behat/basic_usage.feature +++ b/src/addons/mod/book/tests/behat/basic_usage.feature @@ -27,6 +27,7 @@ Feature: Test basic usage of book activity in app | Basic book | Hidden chapter | This is a hidden chapter | 0 | 1 | 4 | | Basic book | Hidden subchapter | This is a hidden subchapter | 1 | 1 | 5 | | Basic book | Chapt 3 | This is the third chapter | 0 | 0 | 6 | + | Basic book | Last hidden | Another hidden subchapter | 1 | 1 | 7 | Scenario: View book table of contents (student) Given I entered the course "Course 1" as "student1" in the app @@ -39,6 +40,7 @@ Feature: Test basic usage of book activity in app And I should find "Start" in the app But I should not find "Hidden chapter" in the app And I should not find "Hidden subchapter" in the app + And I should not find "Last hidden" in the app And I should not find "This is the first chapter" in the app When I press "Start" in the app @@ -49,6 +51,7 @@ Feature: Test basic usage of book activity in app And I should find "Chapt 3" in the app But I should not find "Hidden chapter" in the app And I should not find "Hidden subchapter" in the app + And I should not find "Last hidden" in the app Scenario: View book table of contents (teacher) Given I entered the course "Course 1" as "teacher1" in the app @@ -60,6 +63,7 @@ Feature: Test basic usage of book activity in app And I should find "Hidden chapter" in the app And I should find "Hidden subchapter" in the app And I should find "Chapt 3" in the app + And I should find "Last hidden" in the app And I should find "Start" in the app And I should not find "This is the first chapter" in the app @@ -71,6 +75,7 @@ Feature: Test basic usage of book activity in app And I should find "Hidden chapter" in the app And I should find "Hidden subchapter" in the app And I should find "Chapt 3" in the app + And I should find "Last hidden" in the app Scenario: Open chapters from table of contents Given I entered the course "Course 1" as "student1" in the app @@ -127,7 +132,26 @@ Feature: Test basic usage of book activity in app And I should find "4 / 4" in the app But I should not find "This is the first chapter" in the app - # TODO: Test navigate using swipe. + # Navigate using swipe. + When I swipe to the left in "Chapt 3" "ion-slides" in the app + Then I should find "Chapt 3" in the app + And I should find "This is the third chapter" in the app + And I should find "4 / 4" in the app + + When I swipe to the right in "Chapt 3" "ion-slides" in the app + Then I should find "Chapt 2" in the app + And I should find "This is the second chapter" in the app + And I should find "3 / 4" in the app + + When I swipe to the right in "Chapt 2" "ion-slides" in the app + Then I should find "Chapt 1.1" in the app + And I should find "This is a subchapter" in the app + And I should find "2 / 4" in the app + + When I swipe to the left in "Chapt 1.1" "ion-slides" in the app + Then I should find "Chapt 2" in the app + And I should find "This is the second chapter" in the app + And I should find "3 / 4" in the app Scenario: View and navigate book contents (teacher) Given I entered the course "Course 1" as "teacher1" in the app @@ -135,36 +159,36 @@ Scenario: View and navigate book contents (teacher) And I press "Start" in the app Then I should find "Chapt 1" in the app And I should find "This is the first chapter" in the app - And I should find "1 / 6" in the app + And I should find "1 / 7" in the app When I press "Next" in the app Then I should find "Chapt 1.1" in the app And I should find "This is a subchapter" in the app - And I should find "2 / 6" in the app + And I should find "2 / 7" in the app But I should not find "This is the first chapter" in the app When I press "Next" in the app Then I should find "Chapt 2" in the app And I should find "This is the second chapter" in the app - And I should find "3 / 6" in the app + And I should find "3 / 7" in the app But I should not find "This is a subchapter" in the app When I press "Next" in the app Then I should find "Hidden chapter" in the app And I should find "This is a hidden chapter" in the app - And I should find "4 / 6" in the app + And I should find "4 / 7" in the app But I should not find "This is the second chapter" in the app When I press "Next" in the app Then I should find "Hidden subchapter" in the app And I should find "This is a hidden subchapter" in the app - And I should find "5 / 6" in the app + And I should find "5 / 7" in the app But I should not find "This is a hidden chapter" in the app When I press "Previous" in the app Then I should find "Hidden chapter" in the app And I should find "This is a hidden chapter" in the app - And I should find "4 / 6" in the app + And I should find "4 / 7" in the app But I should not find "This is a hidden subchapter" in the app # Navigate using TOC. @@ -172,20 +196,113 @@ Scenario: View and navigate book contents (teacher) And I press "Chapt 1" in the app Then I should find "Chapt 1" in the app And I should find "This is the first chapter" in the app - And I should find "1 / 6" in the app + And I should find "1 / 7" in the app But I should not find "This is a hidden chapter" in the app When I press "Table of contents" in the app And I press "Hidden subchapter" in the app Then I should find "Hidden subchapter" in the app And I should find "This is a hidden subchapter" in the app - And I should find "5 / 6" in the app + And I should find "5 / 7" in the app But I should not find "This is the first chapter" in the app - # TODO: Test navigate using swipe. + # Navigate using swipe. + When I swipe to the left in "Hidden subchapter" "ion-slides" in the app + Then I should find "Chapt 3" in the app + And I should find "This is the third chapter" in the app + And I should find "6 / 7" in the app + + When I swipe to the left in "Chapt 3" "ion-slides" in the app + Then I should find "Last hidden" in the app + And I should find "Another hidden subchapter" in the app + And I should find "7 / 7" in the app + + When I swipe to the left in "Last hidden" "ion-slides" in the app + Then I should find "Last hidden" in the app + And I should find "Another hidden subchapter" in the app + And I should find "7 / 7" in the app + + When I swipe to the right in "Last hidden" "ion-slides" in the app + Then I should find "Chapt 3" in the app + And I should find "This is the third chapter" in the app + And I should find "6 / 7" in the app Scenario: Link to book opens chapter content Given I entered the book activity "Basic book" on course "Course 1" as "student1" in the app Then I should find "This is the first chapter" in the app - # TODO: Scenario to test book numbering (numbers, bullets, etc.). + Scenario: Test numbering (student) + Given the following "activities" exist: + | activity | name | intro | course | idnumber | numbering | + | book | Bull book | Test book description | C1 | book2 | 2 | + | book | Ind book | Test book description | C1 | book2 | 3 | + | book | None book | Test book description | C1 | book2 | 0 | + And the following "mod_book > chapter" exist: + | book | title | content | subchapter | hidden | pagenum | + | Bull book | Chapt 1 | This is the first chapter | 0 | 0 | 1 | + | Ind book | Chapt 1 | This is the first chapter | 0 | 0 | 1 | + | None book | Chapt 1 | This is the first chapter | 0 | 0 | 1 | + And I entered the course "Course 1" as "student1" in the app + And I press "Basic book" in the app + Then I should find "1. Chapt 1" in the app + And I should find "1.1. Chapt 1.1" in the app + And I should find "2. Chapt 2" in the app + And I should find "3. Chapt 3" in the app + + When I press "Start" in the app + And I press "Table of contents" in the app + Then I should find "1. Chapt 1" in the app + And I should find "1.1. Chapt 1.1" in the app + And I should find "2. Chapt 2" in the app + And I should find "3. Chapt 3" in the app + + When I press "Close" in the app + And I press the back button in the app + And I press the back button in the app + And I press "Bull book" in the app + Then I should find "• Chapt 1" in the app + But I should not find "1. Chapt 1" in the app + + When I press "Start" in the app + And I press "Table of contents" in the app + Then I should find "• Chapt 1" in the app + But I should not find "1. Chapt 1" in the app + + When I press "Close" in the app + And I press the back button in the app + And I press the back button in the app + And I press "Ind book" in the app + Then I should find "Chapt 1" in the app + But I should not find "• Chapt 1" in the app + And I should not find "1. Chapt 1" in the app + + When I press "Start" in the app + And I press "Table of contents" in the app + Then I should find "Chapt 1" in the app + But I should not find "• Chapt 1" in the app + And I should not find "1. Chapt 1" in the app + + When I press "Close" in the app + And I press the back button in the app + And I press the back button in the app + And I press "None book" in the app + Then I should find "Chapt 1" in the app + But I should not find "• Chapt 1" in the app + And I should not find "1. Chapt 1" in the app + + When I press "Start" in the app + And I press "Table of contents" in the app + Then I should find "Chapt 1" in the app + But I should not find "• Chapt 1" in the app + And I should not find "1. Chapt 1" in the app + + Scenario: Test numbering (teacher) + Given I entered the course "Course 1" as "teacher1" in the app + And I press "Basic book" in the app + Then I should find "1. Chapt 1" in the app + And I should find "1.1. Chapt 1.1" in the app + And I should find "2. Chapt 2" in the app + And I should find "x. Hidden chapter" in the app + And I should find "x.x. Hidden subchapter" in the app + And I should find "3. Chapt 3" in the app + And I should find "3.x. Last hidden" in the app diff --git a/src/testing/services/behat-runtime.ts b/src/testing/services/behat-runtime.ts index 892667cca..0f7eb5052 100644 --- a/src/testing/services/behat-runtime.ts +++ b/src/testing/services/behat-runtime.ts @@ -28,6 +28,8 @@ import { CoreDom } from '@singletons/dom'; import { Injectable } from '@angular/core'; import { CoreSites, CoreSitesProvider } from '@services/sites'; import { CoreNavigator, CoreNavigatorService } from '@services/navigator'; +import { CoreSwipeNavigationDirective } from '@directives/swipe-navigation'; +import { IonSlides } from '@ionic/angular'; /** * Behat runtime servive with public API. @@ -493,13 +495,36 @@ export class TestingBehatRuntimeService { * * @param selector Element selector * @param className Constructor class name + * @param referenceLocator The locator to the reference element to start looking for. If not specified, document body. * @returns Component instance */ - getAngularInstance(selector: string, className: string): T | null { - this.log('Action - Get Angular instance ' + selector + ', ' + className); + getAngularInstance( + selector: string, + className: string, + referenceLocator?: TestingBehatElementLocator, + ): T | null { + this.log('Action - Get Angular instance ' + selector + ', ' + className, referenceLocator); + + let startingElement: HTMLElement | undefined = document.body; + let queryPrefix = ''; + + if (referenceLocator) { + startingElement = TestingBehatDomUtils.findElementBasedOnText(referenceLocator, { + onlyClickable: false, + containerName: '', + }); + + if (!startingElement) { + return null; + } + } else { + // Searching the whole DOM, search only in visible pages. + queryPrefix = '.ion-page:not(.ion-page-hidden) '; + } // eslint-disable-next-line @typescript-eslint/no-explicit-any - const activeElement = Array.from(document.querySelectorAll(`.ion-page:not(.ion-page-hidden) ${selector}`)).pop(); + const activeElement = Array.from(startingElement.querySelectorAll(`${queryPrefix}${selector}`)).pop() ?? + startingElement.closest(selector); if (!activeElement || !activeElement.__ngContext__) { return null; @@ -565,6 +590,42 @@ export class TestingBehatRuntimeService { return 'OK'; } + /** + * Swipe in the app. + * + * @param direction Left or right. + * @param locator Element locator to swipe. If not specified, swipe in the first ion-content found. + * @returns OK if successful, or ERROR: followed by message + */ + swipe(direction: string, locator?: TestingBehatElementLocator): string { + this.log('Action - Swipe', { direction, locator }); + + if (locator) { + // Locator specified, try to find ion-slides first. + const instance = this.getAngularInstance('ion-slides', 'IonSlides', locator); + if (instance) { + direction === 'left' ? instance.slideNext() : instance.slidePrev(); + + return 'OK'; + } + } + + // No locator specified or ion-slides not found, search swipe navigation now. + const instance = this.getAngularInstance( + 'ion-content', + 'CoreSwipeNavigationDirective', + locator, + ); + + if (!instance) { + return 'ERROR: Element to swipe not found.'; + } + + direction === 'left' ? instance.swipeLeft() : instance.swipeRight(); + + return 'OK'; + } + } export const TestingBehatRuntime = makeSingleton(TestingBehatRuntimeService);