commit
2b9c4316bb
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/node_modules/@angular/router/index.d.ts b/node_modules/@angular/router/index.d.ts
|
||||||
|
index b8d7cc8..6511edf 100755
|
||||||
|
--- a/node_modules/@angular/router/index.d.ts
|
||||||
|
+++ b/node_modules/@angular/router/index.d.ts
|
||||||
|
@@ -58,7 +58,7 @@ export declare class ActivatedRoute {
|
||||||
|
/** The component of the route, a constant. */
|
||||||
|
component: Type<any> | null;
|
||||||
|
/** The current snapshot of this route */
|
||||||
|
- snapshot: ActivatedRouteSnapshot;
|
||||||
|
+ snapshot?: ActivatedRouteSnapshot;
|
||||||
|
/** An Observable of the resolved route title */
|
||||||
|
readonly title: Observable<string | undefined>;
|
||||||
|
/** An observable of the URL segments matched by this route. */
|
|
@ -1,93 +0,0 @@
|
||||||
@addon_block_timeline @app @javascript @lms_upto3.11
|
|
||||||
Feature: Timeline block.
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username |
|
|
||||||
| student1 |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname |
|
|
||||||
| Course 1 | C1 |
|
|
||||||
| Course 2 | C2 |
|
|
||||||
| Course 3 | C3 |
|
|
||||||
| Course 4 | C4 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
| student1 | C2 | student |
|
|
||||||
| student1 | C3 | student |
|
|
||||||
| student1 | Acceptance test site | student |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | course | idnumber | name | duedate |
|
|
||||||
| assign | Acceptance test site | assign00 | Assignment 00 | ##tomorrow## |
|
|
||||||
| assign | C2 | assign01 | Assignment 01 | ##yesterday## |
|
|
||||||
| assign | C1 | assign02 | Assignment 02 | ##tomorrow## |
|
|
||||||
| assign | C1 | assign03 | Assignment 03 | ##tomorrow## |
|
|
||||||
| assign | C2 | assign04 | Assignment 04 | ##+2 days## |
|
|
||||||
| assign | C1 | assign05 | Assignment 05 | ##+5 days## |
|
|
||||||
| assign | C2 | assign06 | Assignment 06 | ##+31 days## |
|
|
||||||
| assign | C2 | assign07 | Assignment 07 | ##+31 days## |
|
|
||||||
| assign | C3 | assign08 | Assignment 08 | ##+31 days## |
|
|
||||||
| assign | C2 | assign09 | Assignment 09 | ##+31 days## |
|
|
||||||
| assign | C1 | assign10 | Assignment 10 | ##+31 days## |
|
|
||||||
| assign | C1 | assign11 | Assignment 11 | ##+6 months## |
|
|
||||||
| assign | C1 | assign12 | Assignment 12 | ##+6 months## |
|
|
||||||
| assign | C1 | assign13 | Assignment 13 | ##+6 months## |
|
|
||||||
| assign | C2 | assign14 | Assignment 14 | ##+6 months## |
|
|
||||||
| assign | C2 | assign15 | Assignment 15 | ##+6 months## |
|
|
||||||
| assign | C2 | assign16 | Assignment 16 | ##+6 months## |
|
|
||||||
| assign | C3 | assign17 | Assignment 17 | ##+6 months## |
|
|
||||||
| assign | C3 | assign18 | Assignment 18 | ##+6 months## |
|
|
||||||
| assign | C3 | assign19 | Assignment 19 | ##+6 months## |
|
|
||||||
| assign | C1 | assign20 | Assignment 20 | ##+1 year## |
|
|
||||||
| assign | C1 | assign21 | Assignment 21 | ##+1 year## |
|
|
||||||
| assign | C2 | assign22 | Assignment 22 | ##+1 year## |
|
|
||||||
| assign | C2 | assign23 | Assignment 23 | ##+1 year## |
|
|
||||||
| assign | C3 | assign24 | Assignment 24 | ##+1 year## |
|
|
||||||
| assign | C3 | assign25 | Assignment 25 | ##+1 year## |
|
|
||||||
|
|
||||||
Scenario: See courses inside block
|
|
||||||
Given I entered the app as "student1"
|
|
||||||
And I press "Open block drawer" in the app
|
|
||||||
Then I should find "Assignment 00" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Assignment 02" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Assignment 05" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Course 1" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Course 2" within "Timeline" "ion-card" in the app
|
|
||||||
But I should not find "Assignment 01" within "Timeline" "ion-card" in the app
|
|
||||||
And I should not find "Course 3" within "Timeline" "ion-card" in the app
|
|
||||||
|
|
||||||
When I press "Filter timeline by date" in the app
|
|
||||||
And I press "Overdue" in the app
|
|
||||||
Then I should find "Assignment 01" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Course 2" within "Timeline" "ion-card" in the app
|
|
||||||
But I should not find "Assignment 00" within "Timeline" "ion-card" in the app
|
|
||||||
And I should not find "Assignment 02" within "Timeline" "ion-card" in the app
|
|
||||||
And I should not find "Course 1" within "Timeline" "ion-card" in the app
|
|
||||||
And I should not find "Course 3" within "Timeline" "ion-card" in the app
|
|
||||||
|
|
||||||
When I press "Filter timeline by date" in the app
|
|
||||||
And I press "All" in the app
|
|
||||||
Then I should find "Assignment 19" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Course 3" within "Timeline" "ion-card" in the app
|
|
||||||
But I should not find "Assignment 20" within "Timeline" "ion-card" in the app
|
|
||||||
|
|
||||||
When I press "Load more" in the app
|
|
||||||
Then I should find "Assignment 21" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Assignment 25" within "Timeline" "ion-card" in the app
|
|
||||||
|
|
||||||
When I press "Filter timeline by date" in the app
|
|
||||||
And I press "Next 7 days" in the app
|
|
||||||
And I press "Sort by" in the app
|
|
||||||
And I press "Sort by courses" in the app
|
|
||||||
Then I should find "Course 1" "h3" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Course 2" "h3" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Assignment 02" within "Timeline" "ion-card" in the app
|
|
||||||
And I should find "Assignment 04" within "Timeline" "ion-card" in the app
|
|
||||||
But I should not find "Course 3" within "Timeline" "ion-card" in the app
|
|
||||||
|
|
||||||
When the following "activities" exist:
|
|
||||||
| activity | course | idnumber | name | duedate |
|
|
||||||
| assign | C1 | newassign | New Assignment | ##tomorrow## |
|
|
||||||
And I pull to refresh in the app
|
|
||||||
Then I should find "New Assignment" in the app
|
|
|
@ -46,7 +46,6 @@ Feature: Timeline block.
|
||||||
| assign | C3 | assign24 | Assignment 24 | ##+1 year## |
|
| assign | C3 | assign24 | Assignment 24 | ##+1 year## |
|
||||||
| assign | C3 | assign25 | Assignment 25 | ##+1 year## |
|
| assign | C3 | assign25 | Assignment 25 | ##+1 year## |
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: See courses inside block
|
Scenario: See courses inside block
|
||||||
Given I entered the app as "student1"
|
Given I entered the app as "student1"
|
||||||
Then I should find "Assignment 00" within "Timeline" "ion-card" in the app
|
Then I should find "Assignment 00" within "Timeline" "ion-card" in the app
|
||||||
|
@ -92,7 +91,6 @@ Feature: Timeline block.
|
||||||
And I pull to refresh in the app
|
And I pull to refresh in the app
|
||||||
Then I should find "New Assignment" in the app
|
Then I should find "New Assignment" in the app
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Search
|
Scenario: Search
|
||||||
Given I entered the app as "student1"
|
Given I entered the app as "student1"
|
||||||
Then I should find "Assignment 00" within "Timeline" "ion-card" in the app
|
Then I should find "Assignment 00" within "Timeline" "ion-card" in the app
|
||||||
|
|
|
@ -3,7 +3,8 @@ Feature: Edit blog entries
|
||||||
In order to add or edit blog entries as User
|
In order to add or edit blog entries as User
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname | email |
|
| username | firstname | lastname | email |
|
||||||
| testuser | Test | User | moodle@example.com |
|
| testuser | Test | User | moodle@example.com |
|
||||||
| testuser2 | Test | User2 | moodle@example.com |
|
| testuser2 | Test | User2 | moodle@example.com |
|
||||||
|
|
|
@ -4,7 +4,8 @@ Feature: Blog entries
|
||||||
As a user
|
As a user
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname | email |
|
| username | firstname | lastname | email |
|
||||||
| testuser | Test | User | moodle@example.com |
|
| testuser | Test | User | moodle@example.com |
|
||||||
And the following "core_blog > entries" exist:
|
And the following "core_blog > entries" exist:
|
||||||
|
|
|
@ -675,9 +675,7 @@ class AddonCalendarEventsSwipeItemsManager extends CoreSwipeNavigationItemsManag
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
return CoreNavigator.getRouteParams(route).id;
|
||||||
|
|
||||||
return snapshot.params.id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -351,9 +351,7 @@ class AddonCompetencyCompetenciesSwipeManager
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
return CoreNavigator.getRouteParams(route).competencyId;
|
||||||
|
|
||||||
return snapshot.params.competencyId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Test competency navigation
|
Feature: Test competency navigation
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname |
|
| username | firstname | lastname |
|
||||||
| student1 | Student | first |
|
| student1 | Student | first |
|
||||||
| student2 | Student | second |
|
| student2 | Student | second |
|
||||||
|
@ -475,8 +476,7 @@ Feature: Test competency navigation
|
||||||
|
|
||||||
@lms_from4.4
|
@lms_from4.4
|
||||||
Scenario: Disable features
|
Scenario: Disable features
|
||||||
Given the Moodle site is compatible with this feature
|
Given the following config values are set as admin:
|
||||||
And the following config values are set as admin:
|
|
||||||
| enabled | 0 | core_competency |
|
| enabled | 0 | core_competency |
|
||||||
|
|
||||||
When I entered the course "Course 1" as "student1" in the app
|
When I entered the course "Course 1" as "student1" in the app
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Course completion navigation
|
Feature: Course completion navigation
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname | email | idnumber |
|
| username | firstname | lastname | email | idnumber |
|
||||||
| teacher1 | Teacher | 1 | teacher1@example.com | T1 |
|
| teacher1 | Teacher | 1 | teacher1@example.com | T1 |
|
||||||
| student1 | Student | 1 | student1@example.com | S1 |
|
| student1 | Student | 1 | student1@example.com | S1 |
|
||||||
|
|
|
@ -246,9 +246,7 @@ class AddonModAssignSubmissionSwipeItemsManager extends CoreSwipeNavigationItems
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
return CoreNavigator.getRouteParams(route).submitId;
|
||||||
|
|
||||||
return snapshot.params.submitId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
@addon_mod_assign @app @javascript @lms_upto3.10
|
|
||||||
Feature: Test basic usage of assignment activity in app
|
|
||||||
In order to participate in the assignment while using the mobile app
|
|
||||||
I need basic assignment functionality to work
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname | email |
|
|
||||||
| teacher1 | Teacher | teacher | teacher1@example.com |
|
|
||||||
| student1 | Student | student | student1@example.com |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname | category |
|
|
||||||
| Course 1 | C1 | 0 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| teacher1 | C1 | editingteacher |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | attemptreopenmethod |
|
|
||||||
| assign | C1 | assign1 | assignment1 | Test assignment description1 | 1 | ## 20 August 2002 12:00 PM ## | manual |
|
|
||||||
|
|
||||||
Scenario: View assign description, due date & View list of student submissions (as teacher) & View own submission or student submission
|
|
||||||
# Create, edit and submit as a student
|
|
||||||
Given I entered the assign activity "assignment1" on course "Course 1" as "student1" in the app
|
|
||||||
Then the header should be "assignment1" in the app
|
|
||||||
And I should find "Test assignment description1" in the app
|
|
||||||
And I should find "Due date" in the app
|
|
||||||
And I should find "Tuesday, 20 August 2002, 12:00 PM" in the app
|
|
||||||
|
|
||||||
When I press "Add submission" in the app
|
|
||||||
And I set the field "Online text submissions" to "Submission test" in the app
|
|
||||||
And I press "Save" in the app
|
|
||||||
Then I should find "Draft (not submitted)" in the app
|
|
||||||
And I should find "Not graded" in the app
|
|
||||||
|
|
||||||
When I press "Edit submission" in the app
|
|
||||||
And I set the field "Online text submissions" to "Submission test edited" in the app
|
|
||||||
And I press "Save" in the app
|
|
||||||
And I press "OK" in the app
|
|
||||||
Then I should find "Submission test edited" in the app
|
|
||||||
|
|
||||||
When I press "Submit assignment" in the app
|
|
||||||
And I press "OK" in the app
|
|
||||||
Then I should find "Submitted for grading" in the app
|
|
||||||
And I should find "Not graded" in the app
|
|
||||||
And I should find "Submission test edited" in the app
|
|
||||||
|
|
||||||
# View as a teacher
|
|
||||||
Given I entered the assign activity "assignment1" on course "Course 1" as "teacher1" in the app
|
|
||||||
Then the header should be "assignment1" in the app
|
|
||||||
|
|
||||||
When I press "Submitted" in the app
|
|
||||||
Then I should find "Student student" in the app
|
|
||||||
And I should find "Not graded" in the app
|
|
||||||
|
|
||||||
When I press "Student student" near "assignment1" in the app
|
|
||||||
Then I should find "Online text submissions" in the app
|
|
||||||
And I should find "Submission test edited" in the app
|
|
|
@ -19,7 +19,6 @@ Feature: Test basic usage of assignment activity in app
|
||||||
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | attemptreopenmethod |
|
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | attemptreopenmethod |
|
||||||
| assign | C1 | assign1 | assignment1 | Test assignment description1 | 1 | ## 20 August 2002 12:00 PM ## | manual |
|
| assign | C1 | assign1 | assignment1 | Test assignment description1 | 1 | ## 20 August 2002 12:00 PM ## | manual |
|
||||||
|
|
||||||
@lms_from3.11
|
|
||||||
Scenario: View assign description, due date & View list of student submissions (as teacher) & View own submission or student submission
|
Scenario: View assign description, due date & View list of student submissions (as teacher) & View own submission or student submission
|
||||||
# Create, edit and submit as a student
|
# Create, edit and submit as a student
|
||||||
Given I entered the assign activity "assignment1" on course "Course 1" as "student1" in the app
|
Given I entered the assign activity "assignment1" on course "Course 1" as "student1" in the app
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@addon_mod_assign @app @javascript @lms_from4.0
|
@addon_mod_assign @app @javascript
|
||||||
Feature: Test marking workflow in assignment activity in app
|
Feature: Test marking workflow in assignment activity in app
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@addon_mod_bigbluebuttonbn @mod_bigbluebuttonbn @app @javascript @lms_from4.0
|
@addon_mod_bigbluebuttonbn @mod_bigbluebuttonbn @app @javascript
|
||||||
Feature: Test basic usage of BBB activity in app
|
Feature: Test basic usage of BBB activity in app
|
||||||
In order to join a BBB meeting while using the mobile app
|
In order to join a BBB meeting while using the mobile app
|
||||||
As a student
|
As a student
|
||||||
|
@ -97,7 +97,6 @@ Feature: Test basic usage of BBB activity in app
|
||||||
And I press "Join session" in the app
|
And I press "Join session" in the app
|
||||||
Then the app should have opened a browser tab with url "blindsidenetworks.com"
|
Then the app should have opened a browser tab with url "blindsidenetworks.com"
|
||||||
|
|
||||||
@lms_from4.1
|
|
||||||
Scenario: Display right info based on instance type
|
Scenario: Display right info based on instance type
|
||||||
Given the following "activities" exist:
|
Given the following "activities" exist:
|
||||||
| activity | name | course | idnumber | type |
|
| activity | name | course | idnumber | type |
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@addon_mod_bigbluebuttonbn @mod_bigbluebuttonbn @app @javascript @lms_from4.0
|
@addon_mod_bigbluebuttonbn @mod_bigbluebuttonbn @app @javascript
|
||||||
Feature: Test usage of BBB activity with groups in app
|
Feature: Test usage of BBB activity with groups in app
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
|
|
|
@ -4,7 +4,8 @@ Feature: Test basic usage of chat in app
|
||||||
I need basic chat functionality to work
|
I need basic chat functionality to work
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "courses" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "courses" exist:
|
||||||
| fullname | shortname |
|
| fullname | shortname |
|
||||||
| Course 1 | C1 |
|
| Course 1 | C1 |
|
||||||
And the following "users" exist:
|
And the following "users" exist:
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Test chat navigation
|
Feature: Test chat navigation
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "courses" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "courses" exist:
|
||||||
| fullname | shortname |
|
| fullname | shortname |
|
||||||
| Course 1 | C1 |
|
| Course 1 | C1 |
|
||||||
And the following "users" exist:
|
And the following "users" exist:
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
@addon_mod_choice @app @javascript @lms_upto3.11
|
|
||||||
Feature: Test basic usage of choice activity in app
|
|
||||||
In order to participate in the choice while using the mobile app
|
|
||||||
As a student
|
|
||||||
I need basic choice functionality to work
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname | email |
|
|
||||||
| teacher1 | Teacher | teacher | teacher1@example.com |
|
|
||||||
| student1 | Student | student | student1@example.com |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname | category |
|
|
||||||
| Course 1 | C1 | 0 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| teacher1 | C1 | editingteacher |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
|
|
||||||
Scenario: Download students choice in text format
|
|
||||||
# Submit answer as student
|
|
||||||
Given the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | option |
|
|
||||||
| choice | Choice name | Test choice description | C1 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
And I entered the choice activity "Choice name" on course "Course 1" as "student1" in the app
|
|
||||||
Then I select "Option 2" in the app
|
|
||||||
And I press "Save my choice" in the app
|
|
||||||
And I press "OK" in the app
|
|
||||||
|
|
||||||
# Download answers as teacher
|
|
||||||
Given I entered the choice activity "Choice name" on course "Course 1" as "teacher1" in the app
|
|
||||||
Then I should find "Test choice description" in the app
|
|
||||||
|
|
||||||
When I open a browser tab with url "$WWWROOT"
|
|
||||||
And I am on the "choice1" Activity page logged in as teacher1
|
|
||||||
And I press "Actions menu"
|
|
||||||
And I follow "View 1 responses"
|
|
||||||
And I press "Download in text format"
|
|
||||||
# TODO Then I should find "..." in the downloads folder
|
|
|
@ -165,7 +165,6 @@ Feature: Test basic usage of choice activity in app
|
||||||
But I should not find "This Choice has offline data to be synchronised." in the app
|
But I should not find "This Choice has offline data to be synchronised." in the app
|
||||||
|
|
||||||
# TODO remove LMS UI steps in app tests
|
# TODO remove LMS UI steps in app tests
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Download students choice in text format
|
Scenario: Download students choice in text format
|
||||||
# Submit answer as student
|
# Submit answer as student
|
||||||
Given the following "activities" exist:
|
Given the following "activities" exist:
|
||||||
|
|
|
@ -5,7 +5,8 @@ Feature: Users can manage entries in database activities
|
||||||
I need to add and manage entries to databases
|
I need to add and manage entries to databases
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname | email |
|
| username | firstname | lastname | email |
|
||||||
| student1 | Student | 1 | student1@example.com |
|
| student1 | Student | 1 | student1@example.com |
|
||||||
| student2 | Student | 2 | student2@example.com |
|
| student2 | Student | 2 | student2@example.com |
|
||||||
|
|
|
@ -5,7 +5,8 @@ Feature: Users can store entries in database activities when offline and sync wh
|
||||||
I need to add and manage entries to databases and sync then when online
|
I need to add and manage entries to databases and sync then when online
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname | email |
|
| username | firstname | lastname | email |
|
||||||
| student1 | Student | 1 | student1@example.com |
|
| student1 | Student | 1 | student1@example.com |
|
||||||
| student2 | Student | 2 | student2@example.com |
|
| student2 | Student | 2 | student2@example.com |
|
||||||
|
|
|
@ -188,9 +188,7 @@ class AddonModFeedbackAttemptsSwipeManager extends CoreSwipeNavigationItemsManag
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
return CoreNavigator.getRouteParams(route).attemptId;
|
||||||
|
|
||||||
return snapshot.params.attemptId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Test feedback navigation
|
Feature: Test feedback navigation
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname |
|
| username | firstname | lastname |
|
||||||
| teacher1 | Teacher | teacher |
|
| teacher1 | Teacher | teacher |
|
||||||
| student01 | Student | 01 |
|
| student01 | Student | 01 |
|
||||||
|
|
|
@ -134,7 +134,7 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes
|
||||||
|
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const routeData = this.route.snapshot.data;
|
const routeData = CoreNavigator.getRouteData(this.route);
|
||||||
this.courseId = CoreNavigator.getRouteNumberParam('courseId');
|
this.courseId = CoreNavigator.getRouteNumberParam('courseId');
|
||||||
this.cmId = CoreNavigator.getRouteNumberParam('cmId');
|
this.cmId = CoreNavigator.getRouteNumberParam('cmId');
|
||||||
this.forumId = CoreNavigator.getRouteNumberParam('forumId');
|
this.forumId = CoreNavigator.getRouteNumberParam('forumId');
|
||||||
|
@ -893,9 +893,9 @@ class AddonModForumDiscussionDiscussionsSwipeManager extends AddonModForumDiscus
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
const params = CoreNavigator.getRouteParams(route);
|
||||||
|
|
||||||
return this.getSource().DISCUSSIONS_PATH_PREFIX + snapshot.params.discussionId;
|
return this.getSource().DISCUSSIONS_PATH_PREFIX + params.discussionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy, CanLea
|
||||||
*/
|
*/
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const routeData = this.route.snapshot.data;
|
const routeData = CoreNavigator.getRouteData(this.route);
|
||||||
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
||||||
this.cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
|
this.cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
|
||||||
this.forumId = CoreNavigator.getRequiredRouteNumberParam('forumId');
|
this.forumId = CoreNavigator.getRequiredRouteNumberParam('forumId');
|
||||||
|
@ -700,9 +700,9 @@ class AddonModForumNewDiscussionDiscussionsSwipeManager extends AddonModForumDis
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
const params = CoreNavigator.getRouteParams(route);
|
||||||
|
|
||||||
return `${this.getSource().DISCUSSIONS_PATH_PREFIX}new/${snapshot.params.timeCreated}`;
|
return `${this.getSource().DISCUSSIONS_PATH_PREFIX}new/${params.timeCreated}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Test usage of forum activity with groups in app
|
Feature: Test usage of forum activity with groups in app
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "courses" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "courses" exist:
|
||||||
| fullname | shortname |
|
| fullname | shortname |
|
||||||
| Course 1 | C1 |
|
| Course 1 | C1 |
|
||||||
And the following "users" exist:
|
And the following "users" exist:
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Test Forum Search
|
Feature: Test Forum Search
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given solr is installed
|
Given the Moodle site is compatible with this feature
|
||||||
|
And solr is installed
|
||||||
And the following config values are set as admin:
|
And the following config values are set as admin:
|
||||||
| enableglobalsearch | 1 |
|
| enableglobalsearch | 1 |
|
||||||
| searchengine | solr |
|
| searchengine | solr |
|
||||||
|
|
|
@ -103,7 +103,7 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy {
|
||||||
this.cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
|
this.cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
|
||||||
|
|
||||||
const entrySlug = CoreNavigator.getRequiredRouteParam<string>('entrySlug');
|
const entrySlug = CoreNavigator.getRequiredRouteParam<string>('entrySlug');
|
||||||
const routeData = this.route.snapshot.data;
|
const routeData = CoreNavigator.getRouteData(this.route);
|
||||||
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
|
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
|
||||||
AddonModGlossaryEntriesSource,
|
AddonModGlossaryEntriesSource,
|
||||||
[this.courseId, this.cmId, routeData.glossaryPathPrefix ?? ''],
|
[this.courseId, this.cmId, routeData.glossaryPathPrefix ?? ''],
|
||||||
|
@ -368,9 +368,9 @@ class AddonModGlossaryEntryEntriesSwipeManager
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
const params = CoreNavigator.getRouteParams(route);
|
||||||
|
|
||||||
return `${this.getSource().GLOSSARY_PATH_PREFIX}entry/${snapshot.params.entrySlug}`;
|
return `${this.getSource().GLOSSARY_PATH_PREFIX}entry/${params.entrySlug}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,6 @@ Feature: Test basic usage of glossary in app
|
||||||
Then I should find "Garlic" in the app
|
Then I should find "Garlic" in the app
|
||||||
And I should find "Allium sativum" in the app
|
And I should find "Allium sativum" in the app
|
||||||
|
|
||||||
@lms_from3.10
|
|
||||||
Scenario: Edit entries
|
Scenario: Edit entries
|
||||||
Given I entered the glossary activity "Test glossary" on course "Course 1" as "student1" in the app
|
Given I entered the glossary activity "Test glossary" on course "Course 1" as "student1" in the app
|
||||||
|
|
||||||
|
@ -275,7 +274,6 @@ Feature: Test basic usage of glossary in app
|
||||||
But I should not find "stub2.txt" in the app
|
But I should not find "stub2.txt" in the app
|
||||||
And I should not find "Brassica oleracea var. italica" in the app
|
And I should not find "Brassica oleracea var. italica" in the app
|
||||||
|
|
||||||
@lms_from3.10
|
|
||||||
Scenario: Delete entries
|
Scenario: Delete entries
|
||||||
Given I entered the glossary activity "Test glossary" on course "Course 1" as "student1" in the app
|
Given I entered the glossary activity "Test glossary" on course "Course 1" as "student1" in the app
|
||||||
|
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
@addon_mod_lesson @app @javascript @lms_upto3.11
|
|
||||||
Feature: Test decimal separators in lesson
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the Moodle site is compatible with this feature
|
|
||||||
And the following "users" exist:
|
|
||||||
| username | firstname | lastname | email |
|
|
||||||
| teacher1 | Teacher | teacher | teacher1@example.com |
|
|
||||||
| student1 | Student | student | student1@example.com |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname | category |
|
|
||||||
| Course 1 | C1 | 0 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| teacher1 | C1 | editingteacher |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | modattempts | review | maxattempts | retake | allowofflineattempts |
|
|
||||||
| lesson | Basic lesson | Basic lesson descr | C1 | lesson | 1 | 1 | 9 | 1 | 0 |
|
|
||||||
| lesson | Offline lesson | Offline lesson descr | C1 | lesson | 1 | 1 | 9 | 1 | 1 |
|
|
||||||
# Currently there are no generators for pages. See MDL-77581.
|
|
||||||
And I log in as "teacher1"
|
|
||||||
And I change window size to "small"
|
|
||||||
And I am on "Course 1" course homepage
|
|
||||||
And I follow "Basic lesson"
|
|
||||||
And I follow "Add a question page"
|
|
||||||
And I set the field "Select a question type" to "Numerical"
|
|
||||||
And I press "Add a question page"
|
|
||||||
And I set the following fields to these values:
|
|
||||||
| Page title | Hardest question ever |
|
|
||||||
| Page contents | 1 + 1.87? |
|
|
||||||
| id_answer_editor_0 | 2.87 |
|
|
||||||
| id_response_editor_0 | Correct answer |
|
|
||||||
| id_jumpto_0 | End of lesson |
|
|
||||||
| id_score_0 | 1 |
|
|
||||||
| id_answer_editor_1 | 2.1:2.8 |
|
|
||||||
| id_response_editor_1 | Incorrect answer |
|
|
||||||
| id_jumpto_1 | This page |
|
|
||||||
| id_score_1 | 0 |
|
|
||||||
And I press "Save page"
|
|
||||||
And I am on "Course 1" course homepage
|
|
||||||
And I follow "Offline lesson"
|
|
||||||
And I follow "Add a question page"
|
|
||||||
And I set the field "Select a question type" to "Numerical"
|
|
||||||
And I press "Add a question page"
|
|
||||||
And I set the following fields to these values:
|
|
||||||
| Page title | Hardest question ever |
|
|
||||||
| Page contents | 1 + 1.87? |
|
|
||||||
| id_answer_editor_0 | 2.87 |
|
|
||||||
| id_response_editor_0 | Correct answer |
|
|
||||||
| id_jumpto_0 | End of lesson |
|
|
||||||
| id_score_0 | 1 |
|
|
||||||
| id_answer_editor_1 | 2.1:2.8 |
|
|
||||||
| id_response_editor_1 | Incorrect answer |
|
|
||||||
| id_jumpto_1 | This page |
|
|
||||||
| id_score_1 | 0 |
|
|
||||||
And I press "Save page"
|
|
||||||
And I log out
|
|
||||||
|
|
||||||
# This scenario needs to be duplicated because of MDL-77550
|
|
||||||
Scenario: Attempt an online lesson successfully as a student (custom separator) and review as teacher
|
|
||||||
Given the following "language customisations" exist:
|
|
||||||
| component | stringid | value |
|
|
||||||
| core_langconfig | decsep | , |
|
|
||||||
And the following config values are set as admin:
|
|
||||||
| customlangstrings | "core.decsep|,|en" | tool_mobile |
|
|
||||||
And I entered the course "Course 1" as "student1" in the app
|
|
||||||
And I press "Basic lesson" in the app
|
|
||||||
When I press "Start" in the app
|
|
||||||
Then I should find "1 + 1.87?" in the app
|
|
||||||
|
|
||||||
When I set the field "Your answer" to "2,87" in the app
|
|
||||||
And I press "Submit" in the app
|
|
||||||
Then I should find "Correct answer" in the app
|
|
||||||
And I should find "2.87" in the app
|
|
||||||
And I should not find "Incorrect answer" in the app
|
|
||||||
|
|
||||||
When I press "Continue" in the app
|
|
||||||
Then I should find "Congratulations - end of lesson reached" in the app
|
|
||||||
And I should find "Your score is 1 (out of 1)." in the app
|
|
||||||
|
|
||||||
When I press "Review lesson" in the app
|
|
||||||
Then the field "Your answer" matches value "2,87" in the app
|
|
||||||
|
|
||||||
When I press the back button in the app
|
|
||||||
And I press "Start" in the app
|
|
||||||
And I set the field "Your answer" to "2.87" in the app
|
|
||||||
And I press "Submit" in the app
|
|
||||||
Then I should find "Correct answer" in the app
|
|
||||||
And I should find "2.87" in the app
|
|
||||||
And I should not find "Incorrect answer" in the app
|
|
||||||
|
|
||||||
When I press "Continue" in the app
|
|
||||||
Then I should find "Congratulations - end of lesson reached" in the app
|
|
||||||
And I should find "Your score is 1 (out of 1)." in the app
|
|
||||||
|
|
||||||
When I press "Review lesson" in the app
|
|
||||||
Then the field "Your answer" matches value "2,87" in the app
|
|
|
@ -78,7 +78,6 @@ Feature: Test decimal separators in lesson
|
||||||
Then I should find "Congratulations - end of lesson reached" in the app
|
Then I should find "Congratulations - end of lesson reached" in the app
|
||||||
And I should find "Your score is 1 (out of 1)." in the app
|
And I should find "Your score is 1 (out of 1)." in the app
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Attempt an online lesson successfully as a student (custom separator) and review as teacher
|
Scenario: Attempt an online lesson successfully as a student (custom separator) and review as teacher
|
||||||
Given the following "language customisations" exist:
|
Given the following "language customisations" exist:
|
||||||
| component | stringid | value |
|
| component | stringid | value |
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: View list of attempts in the app
|
Feature: View list of attempts in the app
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "courses" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "courses" exist:
|
||||||
| fullname | shortname |
|
| fullname | shortname |
|
||||||
| Course 1 | C1 |
|
| Course 1 | C1 |
|
||||||
And the following "users" exist:
|
And the following "users" exist:
|
||||||
|
@ -45,6 +46,7 @@ Feature: View list of attempts in the app
|
||||||
And I should find "1/1" within "Marks" "ion-item" in the app
|
And I should find "1/1" within "Marks" "ion-item" in the app
|
||||||
And I should be able to press "Review" in the app
|
And I should be able to press "Review" in the app
|
||||||
|
|
||||||
|
@lms_from4.2
|
||||||
Scenario: View abandoned attempts
|
Scenario: View abandoned attempts
|
||||||
Given the attempt at "Quiz 1" by "student1" was never submitted
|
Given the attempt at "Quiz 1" by "student1" was never submitted
|
||||||
And I entered the quiz activity "Quiz 1" on course "Course 1" as "student1" in the app
|
And I entered the quiz activity "Quiz 1" on course "Course 1" as "student1" in the app
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@addon_mod_quiz @app @javascript @lms_from4.0 @lms_upto4.3
|
@addon_mod_quiz @app @javascript @lms_upto4.3
|
||||||
Feature: Attempt a quiz in app
|
Feature: Attempt a quiz in app
|
||||||
As a student
|
As a student
|
||||||
In order to demonstrate what I know
|
In order to demonstrate what I know
|
||||||
|
|
|
@ -1,211 +0,0 @@
|
||||||
@addon_mod_quiz @app @javascript @lms_from3.10 @lms_upto3.11
|
|
||||||
Feature: Attempt a quiz in app
|
|
||||||
As a student
|
|
||||||
In order to demonstrate what I know
|
|
||||||
I need to be able to attempt quizzes
|
|
||||||
|
|
||||||
# These scenarios are duplicated from main because the manual quiz setup is not
|
|
||||||
# equivalent before 4.0.
|
|
||||||
Background:
|
|
||||||
Given the Moodle site is compatible with this feature
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname |
|
|
||||||
| Course 1 | C1 |
|
|
||||||
And the following "users" exist:
|
|
||||||
| username |
|
|
||||||
| student1 |
|
|
||||||
| teacher1 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
| teacher1 | C1 | editingteacher |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber |
|
|
||||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
|
|
||||||
And the following "question categories" exist:
|
|
||||||
| contextlevel | reference | name |
|
|
||||||
| Course | C1 | Test questions |
|
|
||||||
And the following "questions" exist:
|
|
||||||
| questioncategory | qtype | name | questiontext |
|
|
||||||
| Test questions | truefalse | TF1 | Text of the first question |
|
|
||||||
| Test questions | truefalse | TF2 | Text of the second question |
|
|
||||||
And quiz "Quiz 1" contains the following questions:
|
|
||||||
| question | page |
|
|
||||||
| TF1 | 1 |
|
|
||||||
| TF2 | 2 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber |
|
|
||||||
| quiz | Quiz 2 | Quiz 2 description | C1 | quiz2 |
|
|
||||||
And the following "question categories" exist:
|
|
||||||
| contextlevel | reference | name |
|
|
||||||
| Course | C1 | Test questions 2 |
|
|
||||||
And the following "questions" exist:
|
|
||||||
| questioncategory | qtype | name | questiontext |
|
|
||||||
| Test questions | multichoice | TF3 | Text of the first question |
|
|
||||||
| Test questions | shortanswer | TF4 | Text of the second question |
|
|
||||||
| Test questions | numerical | TF5 | Text of the third question |
|
|
||||||
| Test questions | essay | TF6 | Text of the fourth question |
|
|
||||||
| Test questions | ddwtos | TF7 | The [[1]] brown [[2]] jumped over the [[3]] dog. |
|
|
||||||
| Test questions | truefalse | TF8 | Text of the sixth question |
|
|
||||||
| Test questions | match | TF9 | Text of the seventh question |
|
|
||||||
| Test questions | description | TF10 | Text of the eighth question |
|
|
||||||
# TODO test calculated question type.
|
|
||||||
# The calculatedsimple type is implemented using the calculated type.
|
|
||||||
# The calculatedmulti type is implemented using the multichoice type.
|
|
||||||
# The randomsamatch type is implemented using the match type.
|
|
||||||
And the following "questions" exist:
|
|
||||||
| questioncategory | qtype | name | template |
|
|
||||||
| Test questions | gapselect | TF11 | missingchoiceno |
|
|
||||||
| Test questions | ddimageortext | TF12 | xsection |
|
|
||||||
| Test questions | ddmarker | TF13 | mkmap |
|
|
||||||
And quiz "Quiz 2" contains the following questions:
|
|
||||||
| question | page |
|
|
||||||
| TF3 | 1 |
|
|
||||||
| TF4 | 2 |
|
|
||||||
| TF5 | 3 |
|
|
||||||
| TF6 | 4 |
|
|
||||||
| TF7 | 5 |
|
|
||||||
| TF8 | 6 |
|
|
||||||
| TF9 | 7 |
|
|
||||||
| TF10 | 8 |
|
|
||||||
| TF11 | 9 |
|
|
||||||
| TF12 | 10 |
|
|
||||||
| TF13 | 11 |
|
|
||||||
|
|
||||||
# TODO rewrite using generators.
|
|
||||||
And I am on the "Course 1" "core_question > course question bank" page logged in as teacher1
|
|
||||||
And I add a "Embedded answers (Cloze)" question filling the form with:
|
|
||||||
| Question name | multianswer |
|
|
||||||
| Question text | {1:SHORTANSWER:=Berlin} is the capital of Germany. |
|
|
||||||
| General feedback | The capital of Germany is Berlin. |
|
|
||||||
And I am on the "quiz2" "Activity" page
|
|
||||||
And I click on "Actions menu" "link"
|
|
||||||
And I click on "Edit quiz" "link"
|
|
||||||
And I click on "Add" "link"
|
|
||||||
And I click on "from question bank" "link"
|
|
||||||
And I set the field with xpath "//tr[contains(normalize-space(.), 'multianswer')]//input[@type='checkbox']" to "1"
|
|
||||||
And I click on "Add selected questions to the quiz" "button"
|
|
||||||
And I log out
|
|
||||||
|
|
||||||
Scenario: View a quiz entry page (attempts, status, etc.)
|
|
||||||
Given I entered the quiz activity "Quiz 1" on course "Course 1" as "student1" in the app
|
|
||||||
When I press "Attempt quiz now" in the app
|
|
||||||
Then I should find "Text of the first question" in the app
|
|
||||||
But I should not find "Text of the second question" in the app
|
|
||||||
|
|
||||||
When I press "Next" in the app
|
|
||||||
Then I should find "Text of the second question" in the app
|
|
||||||
But I should not find "Text of the first question" in the app
|
|
||||||
|
|
||||||
When I press "Previous" in the app
|
|
||||||
Then I should find "Text of the first question" in the app
|
|
||||||
But I should not find "Text of the second question" in the app
|
|
||||||
|
|
||||||
When I press "Next" in the app
|
|
||||||
Then I should find "Text of the second question" in the app
|
|
||||||
But I should not find "Text of the first question" in the app
|
|
||||||
|
|
||||||
When I press "Previous" in the app
|
|
||||||
Then I should find "Text of the first question" in the app
|
|
||||||
But I should not find "Text of the second question" in the app
|
|
||||||
|
|
||||||
When I press "Next" in the app
|
|
||||||
And I press "Submit" in the app
|
|
||||||
Then I should find "Summary of attempt" in the app
|
|
||||||
|
|
||||||
When I press "Not yet answered" within "2" "ion-item" in the app
|
|
||||||
Then I should find "Text of the second question" in the app
|
|
||||||
But I should not find "Text of the first question" in the app
|
|
||||||
|
|
||||||
When I press "Submit" in the app
|
|
||||||
And I press "Submit all and finish" in the app
|
|
||||||
Then I should find "Once you submit" in the app
|
|
||||||
|
|
||||||
When I press "Cancel" near "Once you submit" in the app
|
|
||||||
Then I should find "Summary of attempt" in the app
|
|
||||||
|
|
||||||
When I press "Submit all and finish" in the app
|
|
||||||
And I press "Submit" near "Once you submit" in the app
|
|
||||||
Then I should find "Review" in the app
|
|
||||||
And I should find "Started" in the app
|
|
||||||
And I should find "Status" in the app
|
|
||||||
And I should find "Completed" in the app
|
|
||||||
And I should find "Duration" in the app
|
|
||||||
And I should find "Marks" in the app
|
|
||||||
And I should find "Grade" in the app
|
|
||||||
And I should find "Question 1" in the app
|
|
||||||
And I should find "Question 2" in the app
|
|
||||||
|
|
||||||
Scenario: Attempt a quiz (all question types)
|
|
||||||
Given I entered the quiz activity "Quiz 2" on course "Course 1" as "student1" in the app
|
|
||||||
When I press "Attempt quiz now" in the app
|
|
||||||
And I press "Four" in the app
|
|
||||||
And I press "Three" in the app
|
|
||||||
And I set the field "Answer" to "Berlin" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I set the field "Answer" to "testing" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I set the field "Answer" to "5" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I set the field "Answer" to "Testing an essay" in the app
|
|
||||||
And I press "Next" "ion-button" in the app
|
|
||||||
And I press "quick" ".drag" in the app
|
|
||||||
And I click on ".place1.drop" "css"
|
|
||||||
And I press "fox" ".drag" in the app
|
|
||||||
And I click on ".place2.drop" "css"
|
|
||||||
And I press "lazy" ".drag" in the app
|
|
||||||
And I click on ".place3.drop" "css"
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I press "True" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I set the field "frog" to "amphibian" in the app
|
|
||||||
And I set the field "newt" to "insect" in the app
|
|
||||||
And I set the field "cat" to "mammal" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
Then I should find "Text of the eighth question" in the app
|
|
||||||
|
|
||||||
When I press "Next" in the app
|
|
||||||
And I set the field "Blank 1" to "cat" in the app
|
|
||||||
And I set the field "Blank 2" to "mat" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I press "abyssal" ".drag" in the app
|
|
||||||
And I click on ".place6.dropzone" "css"
|
|
||||||
And I press "trench" ".drag" in the app
|
|
||||||
And I click on ".place3.dropzone" "css"
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I press "Railway station" ".marker" in the app
|
|
||||||
And I click on "img.dropbackground" "css"
|
|
||||||
And I press "Submit" in the app
|
|
||||||
Then I should find "Answer saved" in the app
|
|
||||||
And I should find "Incomplete answer" within "10" "ion-item" in the app
|
|
||||||
But I should not find "Not yet answered" in the app
|
|
||||||
|
|
||||||
When I press "Submit all and finish" in the app
|
|
||||||
And I press "Submit" in the app
|
|
||||||
Then I should find "Review" in the app
|
|
||||||
And I should find "Finished" in the app
|
|
||||||
And I should find "Not yet graded" in the app
|
|
||||||
|
|
||||||
When I press "Correct" within "Question 2" "ion-card" in the app
|
|
||||||
Then I should find "The correct answer is: Berlin" in the app
|
|
||||||
And I should find "Mark 1.00 out of 1.00" in the app
|
|
||||||
|
|
||||||
Scenario: Submit a quiz & Review a quiz attempt
|
|
||||||
Given I entered the quiz activity "Quiz 1" on course "Course 1" as "student1" in the app
|
|
||||||
When I press "Attempt quiz now" in the app
|
|
||||||
Then I should find "Text of the first question" in the app
|
|
||||||
|
|
||||||
When I press "True" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I press "False" in the app
|
|
||||||
And I press "Submit" in the app
|
|
||||||
And I press "Submit all and finish" in the app
|
|
||||||
And I press "Submit" in the app
|
|
||||||
Then I should find "Review" in the app
|
|
||||||
|
|
||||||
Given I open a browser tab with url "$WWWROOT"
|
|
||||||
When I am on the "quiz1" Activity page logged in as teacher1
|
|
||||||
And I follow "Attempts: 1"
|
|
||||||
And I follow "Review attempt"
|
|
||||||
Then I should see "Finished"
|
|
||||||
And I should see "1.00/2.00"
|
|
|
@ -1,119 +0,0 @@
|
||||||
@addon_mod_quiz @app @javascript @lms_upto3.9
|
|
||||||
Feature: Attempt a quiz in app
|
|
||||||
As a student
|
|
||||||
In order to demonstrate what I know
|
|
||||||
I need to be able to attempt quizzes
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the Moodle site is compatible with this feature
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname |
|
|
||||||
| Course 1 | C1 |
|
|
||||||
And the following "users" exist:
|
|
||||||
| username |
|
|
||||||
| student1 |
|
|
||||||
| teacher1 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
| teacher1 | C1 | editingteacher |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber |
|
|
||||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
|
|
||||||
And the following "question categories" exist:
|
|
||||||
| contextlevel | reference | name |
|
|
||||||
| Course | C1 | Test questions |
|
|
||||||
And the following "questions" exist:
|
|
||||||
| questioncategory | qtype | name | questiontext |
|
|
||||||
| Test questions | truefalse | TF1 | Text of the first question |
|
|
||||||
| Test questions | truefalse | TF2 | Text of the second question |
|
|
||||||
And quiz "Quiz 1" contains the following questions:
|
|
||||||
| question | page |
|
|
||||||
| TF1 | 1 |
|
|
||||||
| TF2 | 2 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber |
|
|
||||||
| quiz | Quiz 2 | Quiz 2 description | C1 | quiz2 |
|
|
||||||
And the following "question categories" exist:
|
|
||||||
| contextlevel | reference | name |
|
|
||||||
| Course | C1 | Test questions 2 |
|
|
||||||
And the following "questions" exist:
|
|
||||||
| questioncategory | qtype | name | questiontext |
|
|
||||||
| Test questions | multichoice | TF3 | Text of the first question |
|
|
||||||
| Test questions | shortanswer | TF4 | Text of the second question |
|
|
||||||
| Test questions | numerical | TF5 | Text of the third question |
|
|
||||||
| Test questions | essay | TF6 | Text of the fourth question |
|
|
||||||
| Test questions | ddwtos | TF7 | The [[1]] brown [[2]] jumped over the [[3]] dog. |
|
|
||||||
| Test questions | truefalse | TF8 | Text of the sixth question |
|
|
||||||
| Test questions | match | TF9 | Text of the seventh question |
|
|
||||||
| Test questions | description | TF10 | Text of the eighth question |
|
|
||||||
And the following "questions" exist:
|
|
||||||
| questioncategory | qtype | name | template |
|
|
||||||
| Test questions | gapselect | TF11 | missingchoiceno |
|
|
||||||
| Test questions | ddimageortext | TF12 | xsection |
|
|
||||||
| Test questions | ddmarker | TF13 | mkmap |
|
|
||||||
And quiz "Quiz 2" contains the following questions:
|
|
||||||
| question | page |
|
|
||||||
| TF3 | 1 |
|
|
||||||
| TF4 | 2 |
|
|
||||||
| TF5 | 3 |
|
|
||||||
| TF6 | 4 |
|
|
||||||
| TF7 | 5 |
|
|
||||||
| TF8 | 6 |
|
|
||||||
| TF9 | 7 |
|
|
||||||
| TF10 | 8 |
|
|
||||||
| TF11 | 9 |
|
|
||||||
| TF12 | 10 |
|
|
||||||
| TF13 | 11 |
|
|
||||||
|
|
||||||
# This scenario is duplicated from main because the description type question (the eighth)
|
|
||||||
# cannot be filled in 3.9, since the selects are missing accessible labels.
|
|
||||||
Scenario: Attempt a quiz (all question types)
|
|
||||||
Given I entered the quiz activity "Quiz 2" on course "Course 1" as "student1" in the app
|
|
||||||
When I press "Attempt quiz now" in the app
|
|
||||||
And I press "Four" in the app
|
|
||||||
And I press "Three" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I set the field "Answer" to "testing" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I set the field "Answer" to "5" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I set the field "Answer" to "Testing an essay" in the app
|
|
||||||
And I press "Next" "ion-button" in the app
|
|
||||||
And I press "quick" ".drag" in the app
|
|
||||||
And I click on ".place1.drop" "css"
|
|
||||||
And I press "fox" ".drag" in the app
|
|
||||||
And I click on ".place2.drop" "css"
|
|
||||||
And I press "lazy" ".drag" in the app
|
|
||||||
And I click on ".place3.drop" "css"
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I press "True" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I press "Choose... , frog" in the app
|
|
||||||
And I press "amphibian" in the app
|
|
||||||
And I press "Choose... , newt" in the app
|
|
||||||
And I press "insect" in the app
|
|
||||||
And I press "Choose... , cat" in the app
|
|
||||||
And I press "mammal" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
Then I should find "Text of the eighth question" in the app
|
|
||||||
|
|
||||||
When I press "Next" in the app
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I press "abyssal" ".drag" in the app
|
|
||||||
And I click on ".place6.dropzone" "css"
|
|
||||||
And I press "trench" ".drag" in the app
|
|
||||||
And I click on ".place3.dropzone" "css"
|
|
||||||
And I press "Next" in the app
|
|
||||||
And I press "Railway station" ".marker" in the app
|
|
||||||
And I click on "img.dropbackground" "css"
|
|
||||||
And I press "Submit" in the app
|
|
||||||
Then I should find "Answer saved" in the app
|
|
||||||
And I should find "Not yet answered" within "8" "ion-item" in the app
|
|
||||||
And I should find "Incomplete answer" within "9" "ion-item" in the app
|
|
||||||
|
|
||||||
When I press "Submit all and finish" in the app
|
|
||||||
And I press "Submit" in the app
|
|
||||||
Then I should find "Review" in the app
|
|
||||||
And I should find "Finished" in the app
|
|
||||||
And I should find "Not yet graded" in the app
|
|
|
@ -609,7 +609,6 @@ Feature: Test attempts and grading settings of SCORM activity in app
|
||||||
# And I press the back button in the app
|
# And I press the back button in the app
|
||||||
# Then I should find "74%" within "Grade reported" "ion-item" in the app
|
# Then I should find "74%" within "Grade reported" "ion-item" in the app
|
||||||
|
|
||||||
# @lms_from4.1
|
|
||||||
# Scenario: SCORM grade is calculated right based on 'Attempts grading' setting
|
# Scenario: SCORM grade is calculated right based on 'Attempts grading' setting
|
||||||
# Given the following "activities" exist:
|
# Given the following "activities" exist:
|
||||||
# | activity | name | course | idnumber | packagefilepath | maxattempt | whatgrade | grademethod | forcenewattempt |
|
# | activity | name | course | idnumber | packagefilepath | maxattempt | whatgrade | grademethod | forcenewattempt |
|
||||||
|
|
|
@ -20,7 +20,6 @@ Feature: Test availability options of SCORM activity in app
|
||||||
| scorm | C1 | Current SCORM | mod/scorm/tests/packages/singlesco_scorm12.zip | ##yesterday## | ##tomorrow## |
|
| scorm | C1 | Current SCORM | mod/scorm/tests/packages/singlesco_scorm12.zip | ##yesterday## | ##tomorrow## |
|
||||||
| scorm | C1 | Future SCORM | mod/scorm/tests/packages/singlesco_scorm12.zip | ##tomorrow## | ##+2 days## |
|
| scorm | C1 | Future SCORM | mod/scorm/tests/packages/singlesco_scorm12.zip | ##tomorrow## | ##+2 days## |
|
||||||
|
|
||||||
@lms_from4.1
|
|
||||||
Scenario: Only open SCORMs can be played
|
Scenario: Only open SCORMs can be played
|
||||||
Given I entered the course "Course 1" as "student1" in the app
|
Given I entered the course "Course 1" as "student1" in the app
|
||||||
When I press "Past SCORM" in the app
|
When I press "Past SCORM" in the app
|
||||||
|
|
|
@ -5,7 +5,8 @@ Feature: Test basic usage of survey activity in app
|
||||||
I need basic survey functionality to work
|
I need basic survey functionality to work
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "courses" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "courses" exist:
|
||||||
| fullname | shortname |
|
| fullname | shortname |
|
||||||
| Course 1 | C1 |
|
| Course 1 | C1 |
|
||||||
And the following "users" exist:
|
And the following "users" exist:
|
||||||
|
|
|
@ -49,8 +49,8 @@ export class AddonModWikiCreateLinkHandlerService extends CoreContentLinksHandle
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = route.snapshot.params;
|
const params = CoreNavigator.getRouteParams(route);
|
||||||
const queryParams = route.snapshot.queryParams;
|
const queryParams = CoreNavigator.getRouteQueryParams(route);
|
||||||
|
|
||||||
if (queryParams.subwikiId == subwikiId) {
|
if (queryParams.subwikiId == subwikiId) {
|
||||||
// Same subwiki, so it's same wiki.
|
// Same subwiki, so it's same wiki.
|
||||||
|
@ -116,7 +116,9 @@ export class AddonModWikiCreateLinkHandlerService extends CoreContentLinksHandle
|
||||||
|
|
||||||
if (isSameWiki) {
|
if (isSameWiki) {
|
||||||
// User is seeing the wiki, we can get the module from the wiki params.
|
// User is seeing the wiki, we can get the module from the wiki params.
|
||||||
path = path + `/${route.snapshot.params.courseId}/${route.snapshot.params.cmId}/edit`;
|
const routeParams = CoreNavigator.getRouteParams(route);
|
||||||
|
|
||||||
|
path = path + `/${routeParams.courseId}/${routeParams.cmId}/edit`;
|
||||||
} else if (wikiId) {
|
} else if (wikiId) {
|
||||||
// The URL specifies which wiki it belongs to. Get the module.
|
// The URL specifies which wiki it belongs to. Get the module.
|
||||||
const module = await CoreCourse.getModuleBasicInfoByInstance(
|
const module = await CoreCourse.getModuleBasicInfoByInstance(
|
||||||
|
|
|
@ -212,9 +212,7 @@ class AddonNotificationSwipeItemsManager extends CoreSwipeNavigationItemsManager
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
return CoreNavigator.getRouteParams(route).id;
|
||||||
|
|
||||||
return snapshot.params.id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Notifications
|
Feature: Notifications
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname |
|
| username | firstname | lastname |
|
||||||
| student1 | First | Student |
|
| student1 | First | Student |
|
||||||
| student2 | Second | Student |
|
| student2 | Second | Student |
|
||||||
|
|
|
@ -245,9 +245,7 @@ export class CoreListItemsManager<
|
||||||
while (route.firstChild) {
|
while (route.firstChild) {
|
||||||
route = route.firstChild;
|
route = route.firstChild;
|
||||||
|
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
segments.push(...CoreNavigator.getRouteUrl(route));
|
||||||
|
|
||||||
segments.push(...snapshot.url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return segments.map(segment => segment.path).join('/').replace(/\/+/, '/').trim() || null;
|
return segments.map(segment => segment.path).join('/').replace(/\/+/, '/').trim() || null;
|
||||||
|
@ -276,7 +274,7 @@ export class CoreListItemsManager<
|
||||||
*/
|
*/
|
||||||
private buildRouteMatcher(): (route: ActivatedRouteSnapshot) => boolean {
|
private buildRouteMatcher(): (route: ActivatedRouteSnapshot) => boolean {
|
||||||
if (this.pageRouteLocator instanceof ActivatedRoute) {
|
if (this.pageRouteLocator instanceof ActivatedRoute) {
|
||||||
const pageRoutePath = CoreNavigator.getRouteFullPath(this.pageRouteLocator.snapshot);
|
const pageRoutePath = CoreNavigator.getRouteFullPath(this.pageRouteLocator);
|
||||||
|
|
||||||
return route => CoreNavigator.getRouteFullPath(route) === pageRoutePath;
|
return route => CoreNavigator.getRouteFullPath(route) === pageRoutePath;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,9 +85,7 @@ export class CoreSwipeNavigationItemsManager<
|
||||||
const segments: UrlSegment[] = [];
|
const segments: UrlSegment[] = [];
|
||||||
|
|
||||||
while (route) {
|
while (route) {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
segments.push(...CoreNavigator.getRouteUrl(route));
|
||||||
|
|
||||||
segments.push(...snapshot.url);
|
|
||||||
|
|
||||||
if (!route.firstChild) {
|
if (!route.firstChild) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -13,10 +13,11 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { mock, mockSingleton } from '@/testing/utils';
|
import { mock, mockSingleton } from '@/testing/utils';
|
||||||
import { ActivatedRoute, ActivatedRouteSnapshot, UrlSegment } from '@angular/router';
|
import { ActivatedRoute, UrlSegment } from '@angular/router';
|
||||||
import { CoreRoutedItemsManagerSource } from '@classes/items-management/routed-items-manager-source';
|
import { CoreRoutedItemsManagerSource } from '@classes/items-management/routed-items-manager-source';
|
||||||
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
interface Item {
|
interface Item {
|
||||||
path: string;
|
path: string;
|
||||||
|
@ -61,9 +62,7 @@ describe('CoreSwipeNavigationItemsManager', () => {
|
||||||
mockSingleton(CoreNavigator, {
|
mockSingleton(CoreNavigator, {
|
||||||
navigate: jest.fn(),
|
navigate: jest.fn(),
|
||||||
getCurrentRoute: () => mock<ActivatedRoute>({
|
getCurrentRoute: () => mock<ActivatedRoute>({
|
||||||
snapshot: mock<ActivatedRouteSnapshot>({
|
url: new BehaviorSubject([mock<UrlSegment>({ path: currentPath })]),
|
||||||
url: [mock<UrlSegment>({ path: currentPath })],
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,31 @@
|
||||||
<ng-container *ngIf="!loadingMore && position !== 'top'">
|
<ng-container *ngIf="!loadingMore && position !== 'top'">
|
||||||
<div *ngIf="enabled || error" class="ion-padding-horizontal" #bottombutton>
|
<div *ngIf="enabled || error" class="ion-padding-horizontal">
|
||||||
<ion-button *ngIf="!error" expand="block" (click)="loadMore()" fill="outline">
|
<ion-button *ngIf="!error" expand="block" (click)="loadMore(true)" fill="outline">
|
||||||
{{ 'core.loadmore' | translate }}
|
{{ 'core.loadmore' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button *ngIf="error" expand="block" (click)="loadMore()" fill="outline">
|
<ion-button *ngIf="error" expand="block" (click)="loadMore(true)" fill="outline">
|
||||||
{{ 'core.tryagain' | translate }}
|
{{ 'core.tryagain' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Don't allow disabling infinite-scroll while loading more items, otherwise infinite scroll stops working. -->
|
<!-- Don't allow disabling infinite-scroll while loading more items on scroll, otherwise infinite scroll stops working. -->
|
||||||
<ion-infinite-scroll [disabled]="!loadingMore && (!enabled || error)" (ionInfinite)="loadMore()" [position]="position">
|
<ion-infinite-scroll [disabled]="(loadingMore && loadingForced) || (!loadingMore && (!enabled || error))" (ionInfinite)="loadMore()"
|
||||||
|
[position]="position">
|
||||||
<ion-infinite-scroll-content />
|
<ion-infinite-scroll-content />
|
||||||
</ion-infinite-scroll>
|
</ion-infinite-scroll>
|
||||||
|
|
||||||
<ng-container *ngIf="!loadingMore && position === 'top'">
|
<ng-container *ngIf="!loadingMore && position === 'top'">
|
||||||
<div *ngIf="enabled || error" class="ion-padding-horizontal" #topbutton>
|
<div *ngIf="enabled || error" class="ion-padding-horizontal">
|
||||||
<ion-button *ngIf="!error" expand="block" (click)="loadMore()" fill="outline">
|
<ion-button *ngIf="!error" expand="block" (click)="loadMore(true)" fill="outline">
|
||||||
{{ 'core.loadmore' | translate }}
|
{{ 'core.loadmore' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button *ngIf="error" expand="block" (click)="loadMore()" fill="outline">
|
<ion-button *ngIf="error" expand="block" (click)="loadMore(true)" fill="outline">
|
||||||
{{ 'core.tryagain' | translate }}
|
{{ 'core.tryagain' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<div *ngIf="loadingMore" class="ion-padding ion-text-center" #spinnercontainer>
|
<div *ngIf="loadingMore && loadingForced" class="ion-padding ion-text-center">
|
||||||
<ion-spinner [attr.aria-label]="'core.loading' | translate" />
|
<ion-spinner [attr.aria-label]="'core.loading' | translate" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -38,6 +38,7 @@ export class CoreInfiniteLoadingComponent implements OnChanges {
|
||||||
@ViewChild(IonInfiniteScroll) infiniteScroll?: IonInfiniteScroll;
|
@ViewChild(IonInfiniteScroll) infiniteScroll?: IonInfiniteScroll;
|
||||||
|
|
||||||
loadingMore = false; // Hide button and avoid loading more.
|
loadingMore = false; // Hide button and avoid loading more.
|
||||||
|
loadingForced = false; // Whether loading is forced or happened on scroll.
|
||||||
hostElement: HTMLElement;
|
hostElement: HTMLElement;
|
||||||
|
|
||||||
constructor(element: ElementRef<HTMLElement>) {
|
constructor(element: ElementRef<HTMLElement>) {
|
||||||
|
@ -96,13 +97,17 @@ export class CoreInfiniteLoadingComponent implements OnChanges {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load More items calling the action provided.
|
* Load More items calling the action provided.
|
||||||
|
*
|
||||||
|
* @param forced Whether loading happened on scroll or was forced.
|
||||||
*/
|
*/
|
||||||
loadMore(): void {
|
loadMore(forced: boolean = false): void {
|
||||||
if (this.loadingMore) {
|
if (this.loadingMore) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadingMore = true;
|
this.loadingMore = true;
|
||||||
|
this.loadingForced = forced;
|
||||||
|
|
||||||
this.action.emit(() => this.complete());
|
this.action.emit(() => this.complete());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +126,8 @@ export class CoreInfiniteLoadingComponent implements OnChanges {
|
||||||
*/
|
*/
|
||||||
protected async completeLoadMore(): Promise<void> {
|
protected async completeLoadMore(): Promise<void> {
|
||||||
this.loadingMore = false;
|
this.loadingMore = false;
|
||||||
|
this.loadingForced = false;
|
||||||
|
|
||||||
await this.infiniteScroll?.complete();
|
await this.infiniteScroll?.complete();
|
||||||
|
|
||||||
// More items loaded. If the list doesn't fill the full height, infinite scroll isn't triggered automatically.
|
// More items loaded. If the list doesn't fill the full height, infinite scroll isn't triggered automatically.
|
||||||
|
|
|
@ -95,7 +95,7 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
this.updateClasses();
|
this.updateClasses();
|
||||||
|
|
||||||
this.outletRouteSubject.next(outletRoute);
|
this.outletRouteSubject.next(outletRoute ?? null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,7 +5,8 @@ Feature: Test basic usage of comments in app
|
||||||
I need basic comments functionality to work
|
I need basic comments functionality to work
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname | email |
|
| username | firstname | lastname | email |
|
||||||
| teacher1 | Teacher | teacher | teacher1@example.com |
|
| teacher1 | Teacher | teacher | teacher1@example.com |
|
||||||
| student1 | Student | student | student1@example.com |
|
| student1 | Student | student | student1@example.com |
|
||||||
|
|
|
@ -111,7 +111,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
|
||||||
*/
|
*/
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
// Increase route depth.
|
// Increase route depth.
|
||||||
const path = CoreNavigator.getRouteFullPath(this.route.snapshot);
|
const path = CoreNavigator.getRouteFullPath(this.route);
|
||||||
|
|
||||||
CoreNavigator.increaseRouteDepth(path.replace(/(\/deep)+/, ''));
|
CoreNavigator.increaseRouteDepth(path.replace(/(\/deep)+/, ''));
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
const path = CoreNavigator.getRouteFullPath(this.route.snapshot);
|
const path = CoreNavigator.getRouteFullPath(this.route);
|
||||||
|
|
||||||
CoreNavigator.decreaseRouteDepth(path.replace(/(\/deep)+/, ''));
|
CoreNavigator.decreaseRouteDepth(path.replace(/(\/deep)+/, ''));
|
||||||
this.selectTabObserver?.off();
|
this.selectTabObserver?.off();
|
||||||
|
|
|
@ -307,7 +307,7 @@ export class CoreCourseProvider {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Number(route.snapshot.params.courseId) == courseId;
|
return Number(CoreNavigator.getRouteParams(route).courseId) == courseId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,128 +0,0 @@
|
||||||
@core_course @app @javascript @lms_upto3.11
|
|
||||||
Feature: Test basic usage of one course in app
|
|
||||||
In order to participate in one course while using the mobile app
|
|
||||||
As a student
|
|
||||||
I need basic course functionality to work
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the Moodle site is compatible with this feature
|
|
||||||
And the following "users" exist:
|
|
||||||
| username | firstname | lastname | email |
|
|
||||||
| teacher1 | Teacher | teacher | teacher1@example.com |
|
|
||||||
| student1 | Student | student | student1@example.com |
|
|
||||||
| student2 | Student2 | student2 | student2@example.com |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname | category |
|
|
||||||
| Course 1 | C1 | 0 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| teacher1 | C1 | editingteacher |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | option | section |
|
|
||||||
| choice | Choice course 1 | Test choice description | C1 | choice1 | Option 1, Option 2, Option 3 | 1 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | section |
|
|
||||||
| assign | C1 | assign1 | assignment | Test assignment description | 1 | 1 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode | assessed | scale[modgrade_type] |
|
|
||||||
| forum | Test forum name | Test forum | C1 | forum | 0 | 5 | Point |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode | section |
|
|
||||||
| chat | Test chat name | Test chat | C1 | chat | 0 | 2 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | section |
|
|
||||||
| data | Web links | Useful links | C1 | data1 | 4 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode | section |
|
|
||||||
| lti | Test external name | Test external | C1 | external | 0 | 1 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode | section |
|
|
||||||
| feedback | Test feedback name | Test feedback | C1 | feedback | 0 | 3 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | section |
|
|
||||||
| glossary | Test glossary | glossary description | C1 | gloss1 | 5 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | section |
|
|
||||||
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | 2 |
|
|
||||||
And the following "question categories" exist:
|
|
||||||
| contextlevel | reference | name |
|
|
||||||
| Course | C1 | Test questions |
|
|
||||||
And the following "questions" exist:
|
|
||||||
| questioncategory | qtype | name | questiontext |
|
|
||||||
| Test questions | truefalse | TF1 | Text of the first question |
|
|
||||||
| Test questions | truefalse | TF2 | Text of the second question |
|
|
||||||
And quiz "Quiz 1" contains the following questions:
|
|
||||||
| question | page |
|
|
||||||
| TF1 | 1 |
|
|
||||||
| TF2 | 2 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode | section |
|
|
||||||
| survey | Test survey name | Test survey | C1 | survey | 0 | 1 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode |
|
|
||||||
| wiki | Test wiki name | Test wiki | C1 | wiki | 0 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode | section |
|
|
||||||
| lesson | Test lesson name | Test lesson | C1 | lesson | 0 | 3 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode | section |
|
|
||||||
| scorm | Test scorm name | Test scorm | C1 | scorm | 0 | 2 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | groupmode | section |
|
|
||||||
| workshop | Test workshop name | Test workshop | C1 | workshop | 0 | 3 |
|
|
||||||
|
|
||||||
Scenario: Self enrol
|
|
||||||
Given I log in as "teacher1"
|
|
||||||
And I am on "Course 1" course homepage
|
|
||||||
And I add "Self enrolment" enrolment method with:
|
|
||||||
| Custom instance name | Student self enrolment |
|
|
||||||
And I entered the app as "student2"
|
|
||||||
When I press "Site home" in the app
|
|
||||||
And I press "Available courses" in the app
|
|
||||||
And I press "Course 1" in the app
|
|
||||||
And I press "Enrol me" in the app
|
|
||||||
And I press "OK" in the app
|
|
||||||
And I wait loading to finish in the app
|
|
||||||
Then the header should be "Course 1" in the app
|
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test wiki name" in the app
|
|
||||||
And I should find "Choice course 1" in the app
|
|
||||||
And I should find "assignment" in the app
|
|
||||||
And I should find "Test external name" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test scorm name" in the app
|
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test lesson name" in the app
|
|
||||||
And I should find "Test workshop name" in the app
|
|
||||||
And I should not find "Web links" in the app
|
|
||||||
And I should not find "Test glossary" in the app
|
|
||||||
|
|
||||||
Scenario: Guest access
|
|
||||||
Given I am on the "Course 1" "enrolment methods" page logged in as "teacher1"
|
|
||||||
And I click on "Enable" "icon" in the "Guest access" "table_row"
|
|
||||||
And I entered the app as "student2"
|
|
||||||
When I press "Site home" in the app
|
|
||||||
And I press "Available courses" in the app
|
|
||||||
And I press "Course 1" in the app
|
|
||||||
|
|
||||||
Then I should find "Course summary" in the app
|
|
||||||
And I should find "Course" in the app
|
|
||||||
|
|
||||||
When I press "View course" "ion-button" in the app
|
|
||||||
Then the header should be "Course 1" in the app
|
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test wiki name" in the app
|
|
||||||
And I should find "Choice course 1" in the app
|
|
||||||
And I should find "assignment" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test scorm name" in the app
|
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test lesson name" in the app
|
|
||||||
And I should find "Test workshop name" in the app
|
|
||||||
And I should not find "Web links" in the app
|
|
||||||
And I should not find "Test glossary" in the app
|
|
|
@ -459,7 +459,6 @@ Feature: Test basic usage of one course in app
|
||||||
| \core\event\course_viewed | Course 1 | {"coursesectionnumber":4} |
|
| \core\event\course_viewed | Course 1 | {"coursesectionnumber":4} |
|
||||||
| \core\event\course_viewed | Course 1 | {"coursesectionnumber":5} |
|
| \core\event\course_viewed | Course 1 | {"coursesectionnumber":5} |
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Self enrol
|
Scenario: Self enrol
|
||||||
Given I log in as "teacher1"
|
Given I log in as "teacher1"
|
||||||
And I add "Self enrolment" enrolment method in "Course 1" with:
|
And I add "Self enrolment" enrolment method in "Course 1" with:
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
@core_course @app @javascript @lms_upto3.10
|
|
||||||
Feature: Check course completion feature.
|
|
||||||
In order to track the progress of the course on mobile device
|
|
||||||
As a student
|
|
||||||
I need to be able to update the activity completion status.
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname | email |
|
|
||||||
| student1 | Student | 1 | student1@example.com |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname | category | enablecompletion |
|
|
||||||
| Course 1 | C1 | 0 | 1 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
|
|
||||||
Scenario: Activity completion, marking the checkbox manually
|
|
||||||
Given the following "activities" exist:
|
|
||||||
| activity | name | course | idnumber | completion | completionview |
|
|
||||||
| forum | First forum | C1 | forum1 | 1 | 0 |
|
|
||||||
| forum | Second forum | C1 | forum2 | 1 | 0 |
|
|
||||||
And I entered the course "Course 1" as "student1" in the app
|
|
||||||
# Set activities as completed.
|
|
||||||
Then I should find "0%" in the app
|
|
||||||
And I click on "ion-button[title=\"Not completed: First forum. Select to mark as complete.\"]" "css"
|
|
||||||
And I should find "50%" in the app
|
|
||||||
And I click on "ion-button[title=\"Not completed: Second forum. Select to mark as complete.\"]" "css"
|
|
||||||
And I should find "100%" in the app
|
|
||||||
# Set activities as not completed.
|
|
||||||
And I click on "ion-button[title=\"Completed: First forum. Select to mark as not complete.\"]" "css"
|
|
||||||
And I should find "50%" in the app
|
|
||||||
And I click on "ion-button[title=\"Completed: Second forum. Select to mark as not complete.\"]" "css"
|
|
||||||
And I should find "0%" in the app
|
|
|
@ -15,7 +15,6 @@ Feature: Check course completion feature.
|
||||||
| user | course | role |
|
| user | course | role |
|
||||||
| student1 | C1 | student |
|
| student1 | C1 | student |
|
||||||
|
|
||||||
@lms_from3.11
|
|
||||||
Scenario: Activity completion, marking the checkbox manually
|
Scenario: Activity completion, marking the checkbox manually
|
||||||
Given the following "activities" exist:
|
Given the following "activities" exist:
|
||||||
| activity | name | course | idnumber | completion | completionview |
|
| activity | name | course | idnumber | completion | completionview |
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
@core_course @app @javascript @lms_upto3.11
|
|
||||||
Feature: Test course list shown on app start tab
|
|
||||||
In order to select a course
|
|
||||||
As a student
|
|
||||||
I need to see the correct list of courses
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "courses" exist:
|
|
||||||
| fullname | shortname |
|
|
||||||
| Course 1 | C1 |
|
|
||||||
| Course 2 | C2 |
|
|
||||||
And the following "users" exist:
|
|
||||||
| username |
|
|
||||||
| student1 |
|
|
||||||
| student2 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
| student2 | C1 | student |
|
|
||||||
| student2 | C2 | student |
|
|
||||||
|
|
||||||
Scenario: View courses (shortnames not displayed)
|
|
||||||
Given I entered the app as "student1"
|
|
||||||
When I should find "Course 1" in the app
|
|
||||||
But I should not find "Course 2" in the app
|
|
||||||
But I should not find "C1" in the app
|
|
||||||
But I should not find "C2" in the app
|
|
||||||
|
|
||||||
Given I entered the app as "student2"
|
|
||||||
When I should find "Course 1" in the app
|
|
||||||
And I should find "Course 2" in the app
|
|
||||||
But I should not find "C1" in the app
|
|
||||||
But I should not find "C2" in the app
|
|
||||||
|
|
||||||
Scenario: Filter courses
|
|
||||||
Given the following config values are set as admin:
|
|
||||||
| courselistshortnames | 1 |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname |
|
|
||||||
| Frog 3 | C3 |
|
|
||||||
| Frog 4 | C4 |
|
|
||||||
| Course 5 | C5 |
|
|
||||||
| Toad 6 | C6 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student2 | C3 | student |
|
|
||||||
| student2 | C4 | student |
|
|
||||||
| student2 | C5 | student |
|
|
||||||
| student2 | C6 | student |
|
|
||||||
# Create bogus courses so that the main ones aren't shown in the 'recently accessed' part.
|
|
||||||
# Because these come later in alphabetical order, they may not be displayed in the lower part
|
|
||||||
# which is OK.
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname |
|
|
||||||
| Zogus 1 | Z1 |
|
|
||||||
| Zogus 2 | Z2 |
|
|
||||||
| Zogus 3 | Z3 |
|
|
||||||
| Zogus 4 | Z4 |
|
|
||||||
| Zogus 5 | Z5 |
|
|
||||||
| Zogus 6 | Z6 |
|
|
||||||
| Zogus 7 | Z7 |
|
|
||||||
| Zogus 8 | Z8 |
|
|
||||||
| Zogus 9 | Z9 |
|
|
||||||
| Zogus 10 | Z10 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student2 | Z1 | student |
|
|
||||||
| student2 | Z2 | student |
|
|
||||||
| student2 | Z3 | student |
|
|
||||||
| student2 | Z4 | student |
|
|
||||||
| student2 | Z5 | student |
|
|
||||||
| student2 | Z6 | student |
|
|
||||||
| student2 | Z7 | student |
|
|
||||||
| student2 | Z8 | student |
|
|
||||||
| student2 | Z9 | student |
|
|
||||||
| student2 | Z10 | student |
|
|
||||||
Given I entered the app as "student2"
|
|
||||||
When I should find "C1" in the app
|
|
||||||
And I should find "C2" in the app
|
|
||||||
And I should find "C3" in the app
|
|
||||||
And I should find "C4" in the app
|
|
||||||
And I should find "C5" in the app
|
|
||||||
And I should find "C6" in the app
|
|
||||||
And I should find "Course 1" in the app
|
|
||||||
And I should find "Course 2" in the app
|
|
||||||
And I should find "Frog 3" in the app
|
|
||||||
And I should find "Frog 4" in the app
|
|
||||||
And I should find "Course 5" in the app
|
|
||||||
And I should find "Toad 6" in the app
|
|
||||||
|
|
||||||
And I set the field "search text" to "fr" in the app
|
|
||||||
|
|
||||||
Then I should find "C3" in the app
|
|
||||||
And I should find "C4" in the app
|
|
||||||
And I should find "Frog 3" in the app
|
|
||||||
And I should find "Frog 4" in the app
|
|
||||||
But I should not find "C1" in the app
|
|
||||||
And I should not find "C2" in the app
|
|
||||||
And I should not find "C5" in the app
|
|
||||||
And I should not find "C6" in the app
|
|
||||||
And I should not find "Course 1" in the app
|
|
||||||
And I should not find "Course 2" in the app
|
|
||||||
And I should not find "Course 5" in the app
|
|
||||||
And I should not find "Toad 6" in the app
|
|
||||||
|
|
||||||
When I set the field "search text" to "" in the app
|
|
||||||
Then I should find "C1" in the app
|
|
||||||
And I should find "C2" in the app
|
|
||||||
And I should find "C3" in the app
|
|
||||||
And I should find "C4" in the app
|
|
||||||
And I should find "C5" in the app
|
|
||||||
And I should find "C6" in the app
|
|
||||||
And I should find "Course 1" in the app
|
|
||||||
And I should find "Course 2" in the app
|
|
||||||
And I should find "Frog 3" in the app
|
|
||||||
And I should find "Frog 4" in the app
|
|
||||||
And I should find "Course 5" in the app
|
|
||||||
And I should find "Toad 6" in the app
|
|
|
@ -19,7 +19,6 @@ Feature: Test course list shown on app start tab
|
||||||
| student2 | C1 | student |
|
| student2 | C1 | student |
|
||||||
| student2 | C2 | student |
|
| student2 | C2 | student |
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: View courses (shortnames not displayed)
|
Scenario: View courses (shortnames not displayed)
|
||||||
Given I entered the app as "student1"
|
Given I entered the app as "student1"
|
||||||
When I press "My courses" in the app
|
When I press "My courses" in the app
|
||||||
|
@ -35,7 +34,6 @@ Feature: Test course list shown on app start tab
|
||||||
But I should not find "C1" in the app
|
But I should not find "C1" in the app
|
||||||
But I should not find "C2" in the app
|
But I should not find "C2" in the app
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Filter courses
|
Scenario: Filter courses
|
||||||
Given the following config values are set as admin:
|
Given the following config values are set as admin:
|
||||||
| courselistshortnames | 1 |
|
| courselistshortnames | 1 |
|
||||||
|
|
|
@ -20,8 +20,6 @@ Feature: Test basic usage of guest access course in app
|
||||||
| activity | name | intro | course | idnumber | groupmode |
|
| activity | name | intro | course | idnumber | groupmode |
|
||||||
| wiki | Test wiki name | Test wiki | C1 | wiki | 0 |
|
| wiki | Test wiki name | Test wiki | C1 | wiki | 0 |
|
||||||
|
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Guest access without password (student)
|
Scenario: Guest access without password (student)
|
||||||
Given I am on the "Course 1" "enrolment methods" page logged in as "teacher1"
|
Given I am on the "Course 1" "enrolment methods" page logged in as "teacher1"
|
||||||
And I click on "Edit" "link" in the "Guest access" "table_row"
|
And I click on "Edit" "link" in the "Guest access" "table_row"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@core_course @app @javascript @lms_from4.0 @lms_upto4.3
|
@core_course @app @javascript @lms_upto4.3
|
||||||
Feature: Check relative dates feature.
|
Feature: Check relative dates feature.
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
|
|
|
@ -38,7 +38,6 @@ Feature: Test basic usage of courses in app
|
||||||
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | gradingduedate |
|
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | gradingduedate |
|
||||||
| assign | C1 | assign1 | assignment | Test assignment description | 1 | ##tomorrow## | ##tomorrow## |
|
| assign | C1 | assign1 | assignment | Test assignment description | 1 | ##tomorrow## | ##tomorrow## |
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: See my courses
|
Scenario: See my courses
|
||||||
Given I entered the app as "student1"
|
Given I entered the app as "student1"
|
||||||
When the header should be "Acceptance test site" in the app
|
When the header should be "Acceptance test site" in the app
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
@core_courses @app @javascript @lms_upto3.10
|
|
||||||
Feature: Test basic usage of courses in app
|
|
||||||
In order to participate in the courses while using the mobile app
|
|
||||||
As a student
|
|
||||||
I need basic courses functionality to work
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname | email |
|
|
||||||
| teacher1 | Teacher | teacher | teacher1@example.com |
|
|
||||||
| student1 | Student | student | student1@example.com |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname | category |
|
|
||||||
| Course 1 | C1 | 0 |
|
|
||||||
| Course 2 | C2 | 0 |
|
|
||||||
| Course 3 | C3 | 0 |
|
|
||||||
| Course 4 | C4 | 0 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| teacher1 | C1 | editingteacher |
|
|
||||||
| teacher1 | C2 | editingteacher |
|
|
||||||
| teacher1 | C3 | editingteacher |
|
|
||||||
| teacher1 | C4 | editingteacher |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
| student1 | C2 | student |
|
|
||||||
| student1 | C3 | student |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | option |
|
|
||||||
| choice | Choice course 1 | Test choice description | C1 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
| choice | Choice course 2 | Test choice description | C2 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
| choice | Choice course 3 | Test choice description | C3 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
| choice | Choice course 4 | Test choice description | C4 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | gradingduedate |
|
|
||||||
| assign | C1 | assign1 | assignment | Test assignment description | 1 | ##tomorrow## | ##tomorrow## |
|
|
||||||
|
|
||||||
Scenario: Links to actions in Timeline work for teachers/students
|
|
||||||
# Submit assignment as student
|
|
||||||
Given I entered the app as "student1"
|
|
||||||
When I press "Open block drawer" in the app
|
|
||||||
And I press "Add submission" in the app
|
|
||||||
Then the header should be "assignment" in the app
|
|
||||||
And I should find "Test assignment description" in the app
|
|
||||||
And I should find "No attempt" in the app
|
|
||||||
And I should find "Due date" in the app
|
|
||||||
|
|
||||||
When I press "Add submission" in the app
|
|
||||||
And I set the field "Online text submissions" to "test" in the app
|
|
||||||
And I press "Save" in the app
|
|
||||||
And I press "Submit assignment" in the app
|
|
||||||
And I press "OK" in the app
|
|
||||||
Then the header should be "assignment" in the app
|
|
||||||
And I should find "Test assignment description" in the app
|
|
||||||
And I should find "Submitted for grading" in the app
|
|
||||||
And I should find "Due date" in the app
|
|
||||||
|
|
||||||
# Grade assignment as teacher
|
|
||||||
Given I entered the app as "teacher1"
|
|
||||||
When I press "Open block drawer" in the app
|
|
||||||
And I press "Grade" in the app
|
|
||||||
Then the header should be "assignment" in the app
|
|
||||||
|
|
||||||
When I pull to refresh in the app
|
|
||||||
Then I should find "Test assignment description" in the app
|
|
||||||
And I should find "Time remaining" in the app
|
|
||||||
|
|
||||||
When I press "Needs grading" in the app
|
|
||||||
Then I should find "Student student" in the app
|
|
||||||
And I should find "Not graded" in the app
|
|
|
@ -1,113 +0,0 @@
|
||||||
@core_courses @app @javascript @lms_upto3.11
|
|
||||||
Feature: Test basic usage of courses in app
|
|
||||||
In order to participate in the courses while using the mobile app
|
|
||||||
As a student
|
|
||||||
I need basic courses functionality to work
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname | email |
|
|
||||||
| teacher1 | Teacher | teacher | teacher1@example.com |
|
|
||||||
| student1 | Student | student | student1@example.com |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname | category |
|
|
||||||
| Course 1 | C1 | 0 |
|
|
||||||
| Course 2 | C2 | 0 |
|
|
||||||
| Course 3 | C3 | 0 |
|
|
||||||
| Course 4 | C4 | 0 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| teacher1 | C1 | editingteacher |
|
|
||||||
| teacher1 | C2 | editingteacher |
|
|
||||||
| teacher1 | C3 | editingteacher |
|
|
||||||
| teacher1 | C4 | editingteacher |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
| student1 | C2 | student |
|
|
||||||
| student1 | C3 | student |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | course | idnumber | option |
|
|
||||||
| choice | Choice course 1 | Test choice description | C1 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
| choice | Choice course 2 | Test choice description | C2 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
| choice | Choice course 3 | Test choice description | C3 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
| choice | Choice course 4 | Test choice description | C4 | choice1 | Option 1, Option 2, Option 3 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | gradingduedate |
|
|
||||||
| assign | C1 | assign1 | assignment | Test assignment description | 1 | ##tomorrow## | ##tomorrow## |
|
|
||||||
|
|
||||||
Scenario: "Dashboard" tab displayed
|
|
||||||
Given I entered the app as "student1"
|
|
||||||
When I should see "Dashboard"
|
|
||||||
And the header should be "Acceptance test site" in the app
|
|
||||||
And I should find "Course 1" in the app
|
|
||||||
And I should find "Course 2" in the app
|
|
||||||
And I should find "Course 3" in the app
|
|
||||||
|
|
||||||
When I press "Site home" in the app
|
|
||||||
Then I should find "Dashboard" in the app
|
|
||||||
And the header should be "Acceptance test site" in the app
|
|
||||||
|
|
||||||
When I press "Dashboard" in the app
|
|
||||||
Then I should find "Course 1" in the app
|
|
||||||
And I should find "Course 2" in the app
|
|
||||||
And I should find "Course 3" in the app
|
|
||||||
|
|
||||||
Scenario: See my courses
|
|
||||||
Given I entered the app as "student1"
|
|
||||||
When the header should be "Acceptance test site" in the app
|
|
||||||
And I should find "Course 1" in the app
|
|
||||||
And I should find "Course 2" in the app
|
|
||||||
And I should find "Course 3" in the app
|
|
||||||
|
|
||||||
When I press "Course 1" in the app
|
|
||||||
Then I should find "Choice course 1" in the app
|
|
||||||
And the header should be "Course 1" in the app
|
|
||||||
|
|
||||||
When I press "Choice course 1" in the app
|
|
||||||
Then I should find "Test choice description" in the app
|
|
||||||
And the header should be "Choice course 1" in the app
|
|
||||||
|
|
||||||
When I press the back button in the app
|
|
||||||
And I press the back button in the app
|
|
||||||
And I press "Course 2" in the app
|
|
||||||
Then I should find "Choice course 2" in the app
|
|
||||||
And the header should be "Course 2" in the app
|
|
||||||
|
|
||||||
When I press the back button in the app
|
|
||||||
And I press "Course 3" in the app
|
|
||||||
Then I should find "Choice course 3" in the app
|
|
||||||
And the header should be "Course 3" in the app
|
|
||||||
|
|
||||||
@lms_from3.11
|
|
||||||
Scenario: Links to actions in Timeline work for teachers/students
|
|
||||||
# Submit assignment as student
|
|
||||||
Given I entered the app as "student1"
|
|
||||||
When I press "Open block drawer" in the app
|
|
||||||
And I press "Add submission" in the app
|
|
||||||
Then the header should be "assignment" in the app
|
|
||||||
And I should find "Test assignment description" in the app
|
|
||||||
And I should find "No attempt" in the app
|
|
||||||
And I should find "Due:" in the app
|
|
||||||
|
|
||||||
When I press "Add submission" in the app
|
|
||||||
And I set the field "Online text submissions" to "test" in the app
|
|
||||||
And I press "Save" in the app
|
|
||||||
And I press "Submit assignment" in the app
|
|
||||||
And I press "OK" in the app
|
|
||||||
Then the header should be "assignment" in the app
|
|
||||||
And I should find "Test assignment description" in the app
|
|
||||||
And I should find "Submitted for grading" in the app
|
|
||||||
And I should find "Due:" in the app
|
|
||||||
|
|
||||||
# Grade assignment as teacher
|
|
||||||
Given I entered the app as "teacher1"
|
|
||||||
When I press "Open block drawer" in the app
|
|
||||||
And I press "Grade" in the app
|
|
||||||
Then the header should be "assignment" in the app
|
|
||||||
|
|
||||||
When I pull to refresh in the app
|
|
||||||
Then I should find "Test assignment description" in the app
|
|
||||||
And I should find "Time remaining" in the app
|
|
||||||
|
|
||||||
When I press "Needs grading" in the app
|
|
||||||
Then I should find "Student student" in the app
|
|
||||||
And I should find "Not graded" in the app
|
|
|
@ -37,7 +37,6 @@ Feature: Test basic usage of courses in app
|
||||||
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | gradingduedate |
|
| activity | course | idnumber | name | intro | assignsubmission_onlinetext_enabled | duedate | gradingduedate |
|
||||||
| assign | C1 | assign1 | assignment | Test assignment description | 1 | ##tomorrow## | ##tomorrow## |
|
| assign | C1 | assign1 | assignment | Test assignment description | 1 | ##tomorrow## | ##tomorrow## |
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: "Dashboard" tab displayed
|
Scenario: "Dashboard" tab displayed
|
||||||
Given I entered the app as "student1"
|
Given I entered the app as "student1"
|
||||||
When I should see "Dashboard"
|
When I should see "Dashboard"
|
||||||
|
@ -52,7 +51,6 @@ Feature: Test basic usage of courses in app
|
||||||
And I should find "Course 2" in the app
|
And I should find "Course 2" in the app
|
||||||
And I should find "Course 3" in the app
|
And I should find "Course 3" in the app
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Hidden course is only accessible for teachers
|
Scenario: Hidden course is only accessible for teachers
|
||||||
Given I entered the app as "teacher1"
|
Given I entered the app as "teacher1"
|
||||||
And I press "My courses" in the app
|
And I press "My courses" in the app
|
||||||
|
@ -118,7 +116,6 @@ Feature: Test basic usage of courses in app
|
||||||
And I should find "Course 3" in the app
|
And I should find "Course 3" in the app
|
||||||
And I should find "Course 4" in the app
|
And I should find "Course 4" in the app
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Links to actions in Timeline work for teachers/students
|
Scenario: Links to actions in Timeline work for teachers/students
|
||||||
# Submit assignment as student
|
# Submit assignment as student
|
||||||
Given I entered the app as "student1"
|
Given I entered the app as "student1"
|
||||||
|
|
|
@ -97,7 +97,6 @@ export class CoreEnrolService {
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
site.invalidateWsCacheForKey(this.getCourseEnrolmentMethodsCacheKey(courseId)),
|
site.invalidateWsCacheForKey(this.getCourseEnrolmentMethodsCacheKey(courseId)),
|
||||||
site.invalidateWsCacheForKey(`mmCourses:enrolmentmethods:${courseId}`), // @todo 4.4 Remove after 4.3 release.
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy {
|
||||||
this.collapseLabel = Translate.instant('core.collapse');
|
this.collapseLabel = Translate.instant('core.collapse');
|
||||||
this.useLegacyLayout = !CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('4.1');
|
this.useLegacyLayout = !CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('4.1');
|
||||||
|
|
||||||
switch (route.snapshot.data.swipeManagerSource ?? route.snapshot.parent?.data.swipeManagerSource) {
|
switch (route.snapshot?.data.swipeManagerSource ?? route.snapshot?.parent?.data.swipeManagerSource) {
|
||||||
case 'courses':
|
case 'courses':
|
||||||
this.swipeManager = new CoreGradesCourseCoursesSwipeManager(
|
this.swipeManager = new CoreGradesCourseCoursesSwipeManager(
|
||||||
CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(CoreGradesCoursesSource, []),
|
CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(CoreGradesCoursesSource, []),
|
||||||
|
@ -331,9 +331,7 @@ class CoreGradesCourseParticipantsSwipeManager extends CoreSwipeNavigationItemsM
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
return CoreNavigator.getRouteParams(route).userId;
|
||||||
|
|
||||||
return snapshot.params.userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Grades navigation
|
Feature: Grades navigation
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname |
|
| username | firstname | lastname |
|
||||||
| student1 | Student | first |
|
| student1 | Student | first |
|
||||||
| student2 | Student | second |
|
| student2 | Student | second |
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Grades navigation
|
Feature: Grades navigation
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname |
|
| username | firstname | lastname |
|
||||||
| student1 | Student | first |
|
| student1 | Student | first |
|
||||||
| student2 | Student | second |
|
| student2 | Student | second |
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
@core_grades @app @javascript @lms_upto3.11
|
|
||||||
Feature: View grades
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname |
|
|
||||||
| student1 | Student | first |
|
|
||||||
And the following "scales" exist:
|
|
||||||
| name | scale |
|
|
||||||
| Scale | Good, Bad |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname |
|
|
||||||
| Course 1 | C1 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
And the following "grade categories" exist:
|
|
||||||
| fullname | course |
|
|
||||||
| Category 1 | C1 |
|
|
||||||
| Category 2 | C1 |
|
|
||||||
And the following "grade outcomes" exist:
|
|
||||||
| fullname | shortname | course | scale |
|
|
||||||
| Outcome | outcome | C1 | Scale |
|
|
||||||
And the following "grade items" exist:
|
|
||||||
| gradecategory | itemname | course | grademin | grademax |
|
|
||||||
| Category 1 | Item 1.1 | C1 | 60 | 80 |
|
|
||||||
| Category 1 | Item 1.2 | C1 | 10 | 90 |
|
|
||||||
| Category 2 | Item 2.1 | C1 | 0 | 100 |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| gradecategory | name | course | activity | idnumber | grade | gradepass |
|
|
||||||
| Category 1 | Assignment 1 | C1 | assign | assign1 | 100 | 50 |
|
|
||||||
| Category 1 | Assignment 2 | C1 | assign | assign2 | 100 | 50 |
|
|
||||||
And the following "grade items" exist:
|
|
||||||
| gradecategory | itemname | course | outcome |
|
|
||||||
| Category 1 | Outcome | C1 | outcome |
|
|
||||||
And the following "grade grades" exist:
|
|
||||||
| gradeitem | user | grade |
|
|
||||||
| Item 1.1 | student1 | 70 |
|
|
||||||
| Item 1.2 | student1 | 20 |
|
|
||||||
| Item 2.1 | student1 | 40 |
|
|
||||||
| Assignment 1 | student1 | 80 |
|
|
||||||
| Assignment 2 | student1 | 35 |
|
|
||||||
| Outcome | student1 | 1 |
|
|
||||||
And the following config values are set as admin:
|
|
||||||
| enableoutcomes | 1 |
|
|
||||||
|
|
||||||
Scenario: View individual grades and the grade report
|
|
||||||
Given I entered the course "Course 1" as "student1" in the app
|
|
||||||
|
|
||||||
When I press "Assignment 1" in the app
|
|
||||||
And I press "Information" in the app
|
|
||||||
Then I should find "80" within "Gradebook" "ion-list" in the app
|
|
||||||
|
|
||||||
When I press "Close" in the app
|
|
||||||
And I press the back button in the app
|
|
||||||
And I press "Assignment 2" in the app
|
|
||||||
And I press "Information" in the app
|
|
||||||
Then I should find "35" within "Gradebook" "ion-list" in the app
|
|
||||||
|
|
||||||
When I press "Close" in the app
|
|
||||||
And I press the back button in the app
|
|
||||||
And I press "Grades" in the app
|
|
||||||
Then I should find "Category 1" in the app
|
|
||||||
And I should find "70" within "Item 1.1" "tr" in the app
|
|
||||||
And I should find "20" within "Item 1.2" "tr" in the app
|
|
||||||
And I should find "80" within "Assignment 1" "tr" in the app
|
|
||||||
And I should find "35" within "Assignment 2" "tr" in the app
|
|
||||||
And I should find "Good" within "Outcome" "tr" in the app
|
|
||||||
And I should find "205" within "Category 1 total" "tr" in the app
|
|
||||||
And I should find "Category 2" in the app
|
|
||||||
And I should find "40" within "Item 2.1" "tr" in the app
|
|
||||||
And I should find "40" within "Category 2 total" "tr" in the app
|
|
||||||
And I should find "245" within "Course total" "tr" in the app
|
|
|
@ -1,8 +1,9 @@
|
||||||
@core_grades @app @javascript @lms_from4.0
|
@core_grades @app @javascript
|
||||||
Feature: View grades
|
Feature: View grades
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname |
|
| username | firstname | lastname |
|
||||||
| student1 | Student | first |
|
| student1 | Student | first |
|
||||||
And the following "scales" exist:
|
And the following "scales" exist:
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
@core_login @app @javascript @lms_from4.0 @lms_upto4.0
|
|
||||||
Feature: Test basic usage of login in app
|
|
||||||
I need basic login functionality to work
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname |
|
|
||||||
| student1 | david | student |
|
|
||||||
|
|
||||||
Scenario: Forgot password
|
|
||||||
When I enter the app
|
|
||||||
And I press "Lost password?" in the app
|
|
||||||
And I set the field "Enter either username or email address" to "student1"
|
|
||||||
And I press "Search" in the app
|
|
||||||
Then I should find "Success" in the app
|
|
||||||
|
|
||||||
When I press "OK" in the app
|
|
||||||
And I press "Lost password?" in the app
|
|
||||||
Then I should find "Contact support" in the app
|
|
|
@ -1,19 +0,0 @@
|
||||||
@core_login @app @javascript @lms_upto3.11
|
|
||||||
Feature: Test basic usage of login in app
|
|
||||||
I need basic login functionality to work
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname |
|
|
||||||
| student1 | david | student |
|
|
||||||
|
|
||||||
Scenario: Forgot password
|
|
||||||
When I enter the app
|
|
||||||
And I press "Lost password?" in the app
|
|
||||||
And I set the field "Enter either username or email address" to "student1"
|
|
||||||
And I press "Search" in the app
|
|
||||||
Then I should find "Success" in the app
|
|
||||||
|
|
||||||
When I press "OK" in the app
|
|
||||||
And I press "Lost password?" in the app
|
|
||||||
Then I should not find "Contact support" in the app
|
|
|
@ -146,7 +146,6 @@ Feature: Test basic usage of login in app
|
||||||
When I press "Reconnect" in the app
|
When I press "Reconnect" in the app
|
||||||
Then I should find "Acceptance test site" in the app
|
Then I should find "Acceptance test site" in the app
|
||||||
|
|
||||||
@lms_from4.1
|
|
||||||
Scenario: Forgot password
|
Scenario: Forgot password
|
||||||
Given the following config values are set as admin:
|
Given the following config values are set as admin:
|
||||||
| supportavailability | 2 |
|
| supportavailability | 2 |
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
@core_login @app @javascript @lms_upto3.9
|
|
||||||
Feature: Test signup in app
|
|
||||||
I need basic signup functionality to work
|
|
||||||
|
|
||||||
# These scenarios are duplicated from main because the error message about
|
|
||||||
# non alpha-numeric characters has changed.
|
|
||||||
Background:
|
|
||||||
Given the following config values are set as admin:
|
|
||||||
| registerauth | email |
|
|
||||||
| auth_instructions | These are the authentication instructions. |
|
|
||||||
| passwordpolicy | 0 |
|
|
||||||
|
|
||||||
Scenario: Check password policy in signup
|
|
||||||
Given the following config values are set as admin:
|
|
||||||
| passwordpolicy | 1 |
|
|
||||||
| minpasswordlength | 8 |
|
|
||||||
| minpassworddigits | 1 |
|
|
||||||
| minpasswordlower | 1 |
|
|
||||||
| minpasswordupper | 1 |
|
|
||||||
| minpasswordnonalphanum | 1 |
|
|
||||||
When I launch the app
|
|
||||||
And I set the field "Your site" to "$WWWROOT" in the app
|
|
||||||
And I press "Connect to your site" in the app
|
|
||||||
And I press "Create new account" in the app
|
|
||||||
Then I should find "The password must have at least 8 characters" in the app
|
|
||||||
And I set the following fields to these values in the app:
|
|
||||||
| Username | u1 |
|
|
||||||
| Password | pu1 |
|
|
||||||
| Email address | u1@u1.com |
|
|
||||||
| Email (again) | u1@u1.com |
|
|
||||||
| First name | User |
|
|
||||||
| Last name | Test |
|
|
||||||
| City/town | Barcelona |
|
|
||||||
| Country | Spain |
|
|
||||||
And I press "Create my new account" in the app
|
|
||||||
Then I should find "Error" in the app
|
|
||||||
And I should find "Passwords must be at least 8 characters long" in the app
|
|
||||||
And I should find "Passwords must have at least 1 upper case letter(s)" in the app
|
|
||||||
And I should find "Passwords must have at least 1 non-alphanumeric character(s)" in the app
|
|
||||||
But I should not find "An email should have been sent to your address" in the app
|
|
||||||
|
|
||||||
When I press "OK" in the app
|
|
||||||
And I set the field "Password" to "Password1$" in the app
|
|
||||||
And I press "Create my new account" in the app
|
|
||||||
Then I should find "An email should have been sent to your address" in the app
|
|
|
@ -3,7 +3,8 @@ Feature: Test signup in app
|
||||||
I need basic signup functionality to work
|
I need basic signup functionality to work
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following config values are set as admin:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following config values are set as admin:
|
||||||
| registerauth | email |
|
| registerauth | email |
|
||||||
| auth_instructions | These are the authentication instructions. |
|
| auth_instructions | These are the authentication instructions. |
|
||||||
| passwordpolicy | 0 |
|
| passwordpolicy | 0 |
|
||||||
|
@ -79,7 +80,6 @@ Feature: Test signup in app
|
||||||
Then I should find "Spain" in the app
|
Then I should find "Spain" in the app
|
||||||
And I should find "u1@u1.com" in the app
|
And I should find "u1@u1.com" in the app
|
||||||
|
|
||||||
@lms_from3.10
|
|
||||||
Scenario: Check password policy in signup
|
Scenario: Check password policy in signup
|
||||||
Given the following config values are set as admin:
|
Given the following config values are set as admin:
|
||||||
| passwordpolicy | 1 |
|
| passwordpolicy | 1 |
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
@core_mainmenu @app @javascript @lms_upto3.11
|
|
||||||
Feature: Main Menu opens the right page
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username |
|
|
||||||
| student |
|
|
||||||
|
|
||||||
Scenario: Opens Site Home when defaulthomepage is set to Site
|
|
||||||
Given the following config values are set as admin:
|
|
||||||
| defaulthomepage | 0 |
|
|
||||||
Given I entered the app as "student"
|
|
||||||
When "Site home" should be selected in the app
|
|
||||||
And I should find "Available courses" in the app
|
|
||||||
And "Site home" "text" should appear before "Dashboard" "text" in the ".core-tabs-bar" "css_element"
|
|
||||||
|
|
||||||
Scenario: Opens Dashboard when defaulthomepage is set to Dashboard
|
|
||||||
Given the following config values are set as admin:
|
|
||||||
| defaulthomepage | 1 |
|
|
||||||
Given I entered the app as "student"
|
|
||||||
When "Dashboard" should be selected in the app
|
|
||||||
And I should find "Course overview" in the app
|
|
||||||
And "Dashboard" "text" should appear before "Site home" "text" in the ".core-tabs-bar" "css_element"
|
|
|
@ -12,7 +12,6 @@ Feature: Main Menu opens the right page
|
||||||
| user | course | role |
|
| user | course | role |
|
||||||
| student | C1 | student |
|
| student | C1 | student |
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Opens Site Home when defaulthomepage is set to Site
|
Scenario: Opens Site Home when defaulthomepage is set to Site
|
||||||
Given the following config values are set as admin:
|
Given the following config values are set as admin:
|
||||||
| defaulthomepage | 0 |
|
| defaulthomepage | 0 |
|
||||||
|
@ -22,7 +21,6 @@ Feature: Main Menu opens the right page
|
||||||
And "Site home" "text" should appear before "Dashboard" "text" in the ".core-tabs-bar" "css_element"
|
And "Site home" "text" should appear before "Dashboard" "text" in the ".core-tabs-bar" "css_element"
|
||||||
And "Home" "text" should appear before "My courses" "text" in the ".mainmenu-tabs" "css_element"
|
And "Home" "text" should appear before "My courses" "text" in the ".mainmenu-tabs" "css_element"
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Opens Dashboard when defaulthomepage is set to Dashboard
|
Scenario: Opens Dashboard when defaulthomepage is set to Dashboard
|
||||||
Given the following config values are set as admin:
|
Given the following config values are set as admin:
|
||||||
| defaulthomepage | 1 |
|
| defaulthomepage | 1 |
|
||||||
|
@ -32,7 +30,6 @@ Feature: Main Menu opens the right page
|
||||||
And "Dashboard" "text" should appear before "Site home" "text" in the ".core-tabs-bar" "css_element"
|
And "Dashboard" "text" should appear before "Site home" "text" in the ".core-tabs-bar" "css_element"
|
||||||
And "Home" "text" should appear before "My courses" "text" in the ".mainmenu-tabs" "css_element"
|
And "Home" "text" should appear before "My courses" "text" in the ".mainmenu-tabs" "css_element"
|
||||||
|
|
||||||
@lms_from4.0
|
|
||||||
Scenario: Opens My Courses when defaulthomepage is set to My Courses
|
Scenario: Opens My Courses when defaulthomepage is set to My Courses
|
||||||
Given the following config values are set as admin:
|
Given the following config values are set as admin:
|
||||||
| defaulthomepage | 3 |
|
| defaulthomepage | 3 |
|
||||||
|
@ -42,7 +39,6 @@ Feature: Main Menu opens the right page
|
||||||
And "My courses" "text" should appear before "Home" "text" in the ".mainmenu-tabs" "css_element"
|
And "My courses" "text" should appear before "Home" "text" in the ".mainmenu-tabs" "css_element"
|
||||||
|
|
||||||
# @todo MOBILE-4119: This test is too flaky to run in CI until the race condition is fixed.
|
# @todo MOBILE-4119: This test is too flaky to run in CI until the race condition is fixed.
|
||||||
# @lms_from4.0
|
|
||||||
# Scenario: Opens first tab after Site Home, Dashboard, and My Courses are disabled
|
# Scenario: Opens first tab after Site Home, Dashboard, and My Courses are disabled
|
||||||
# Given I entered the app as "student"
|
# Given I entered the app as "student"
|
||||||
# Then "Dashboard" should be selected in the app
|
# Then "Dashboard" should be selected in the app
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@core_reminders @app @javascript @lms_from4.0
|
@core_reminders @app @javascript
|
||||||
Feature: Set a new reminder on activity
|
Feature: Set a new reminder on activity
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@core_reportbuilder @app @javascript @lms_from4.1
|
@core_reportbuilder @app @javascript
|
||||||
Feature: Report builder
|
Feature: Report builder
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
|
|
|
@ -40,8 +40,9 @@ Feature: It synchronise sites properly
|
||||||
|
|
||||||
# Check synced
|
# Check synced
|
||||||
When I press "Synchronise now" "button" in the app
|
When I press "Synchronise now" "button" in the app
|
||||||
And I wait loading to finish in the app
|
Then I should find "Site synchronisation completed" in the app
|
||||||
And I switch network connection to offline
|
|
||||||
|
When I switch network connection to offline
|
||||||
And I press the back button in the app
|
And I press the back button in the app
|
||||||
And I entered the course "Course 1" in the app
|
And I entered the course "Course 1" in the app
|
||||||
And I press "Sync choice" in the app
|
And I press "Sync choice" in the app
|
||||||
|
|
|
@ -117,7 +117,7 @@ export class CoreUserProfilePage implements OnInit, OnDestroy {
|
||||||
this.courseId = undefined;
|
this.courseId = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.courseId && this.route.snapshot.data.swipeManagerSource === 'participants') {
|
if (this.courseId && CoreNavigator.getRouteData(this.route).swipeManagerSource === 'participants') {
|
||||||
const search = CoreNavigator.getRouteParam('search');
|
const search = CoreNavigator.getRouteParam('search');
|
||||||
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
|
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
|
||||||
CoreUserParticipantsSource,
|
CoreUserParticipantsSource,
|
||||||
|
@ -252,9 +252,7 @@ class CoreUserSwipeItemsManager extends CoreSwipeNavigationItemsManager {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot | ActivatedRoute): string | null {
|
||||||
const snapshot = route instanceof ActivatedRouteSnapshot ? route : route.snapshot;
|
return CoreNavigator.getRouteParams(route).userId;
|
||||||
|
|
||||||
return snapshot.params.userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: Test basic usage of user features
|
Feature: Test basic usage of user features
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username | firstname | lastname | timezone |
|
| username | firstname | lastname | timezone |
|
||||||
| student1 | Student | Student | 99 |
|
| student1 | Student | Student | 99 |
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
@ -1,13 +0,0 @@
|
||||||
@core_user @app @javascript @lms_upto3.11
|
|
||||||
Feature: Site support
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username | firstname | lastname |
|
|
||||||
| student1 | Student | Student |
|
|
||||||
|
|
||||||
Scenario: Cannot contact support
|
|
||||||
Given I entered the app as "student1"
|
|
||||||
When I press the user menu button in the app
|
|
||||||
Then I should find "Blog entries" in the app
|
|
||||||
But I should not find "Support" in the app
|
|
|
@ -1,4 +1,4 @@
|
||||||
@core_user @app @javascript @lms_from4.0
|
@core_user @app @javascript
|
||||||
Feature: Site support
|
Feature: Site support
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Params } from '@angular/router';
|
import { ActivatedRoute, ActivatedRouteSnapshot, Data, NavigationEnd, Params, UrlSegment } from '@angular/router';
|
||||||
|
|
||||||
import { NavigationOptions } from '@ionic/angular/common/providers/nav-controller';
|
import { NavigationOptions } from '@ionic/angular/common/providers/nav-controller';
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import { CoreMainMenuDelegate } from '@features/mainmenu/services/mainmenu-deleg
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { filter } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect payload.
|
* Redirect payload.
|
||||||
|
@ -459,7 +460,7 @@ export class CoreNavigatorService {
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routeData && CoreUtils.basicLeftCompare(routeData, route.snapshot.data, 3)) {
|
if (routeData && CoreUtils.basicLeftCompare(routeData, this.getRouteData(route), 3)) {
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,11 +478,11 @@ export class CoreNavigatorService {
|
||||||
* @returns Whether the route is active or not.
|
* @returns Whether the route is active or not.
|
||||||
*/
|
*/
|
||||||
isRouteActive(route: ActivatedRoute): boolean {
|
isRouteActive(route: ActivatedRoute): boolean {
|
||||||
const routePath = this.getRouteFullPath(route.snapshot);
|
const routePath = this.getRouteFullPath(route);
|
||||||
let activeRoute: ActivatedRoute | null = Router.routerState.root;
|
let activeRoute: ActivatedRoute | null = Router.routerState.root;
|
||||||
|
|
||||||
while (activeRoute) {
|
while (activeRoute) {
|
||||||
if (this.getRouteFullPath(activeRoute.snapshot) === routePath) {
|
if (this.getRouteFullPath(activeRoute) === routePath) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,13 +651,13 @@ export class CoreNavigatorService {
|
||||||
* @param route Route snapshot.
|
* @param route Route snapshot.
|
||||||
* @returns Path.
|
* @returns Path.
|
||||||
*/
|
*/
|
||||||
getRouteFullPath(route: ActivatedRouteSnapshot | null): string {
|
getRouteFullPath(route: ActivatedRouteSnapshot | ActivatedRoute | null): string {
|
||||||
if (!route) {
|
if (!route) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentPath = this.getRouteFullPath(route.parent);
|
const parentPath = this.getRouteFullPath(this.getRouteParent(route));
|
||||||
const routePath = route.url.join('/');
|
const routePath = this.getRouteUrl(route).join('/');
|
||||||
|
|
||||||
if (!parentPath && !routePath) {
|
if (!parentPath && !routePath) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -669,13 +670,63 @@ export class CoreNavigatorService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a route, get url segments.
|
||||||
|
*
|
||||||
|
* @param route Route.
|
||||||
|
* @returns Url segments.
|
||||||
|
*/
|
||||||
|
getRouteUrl(route: ActivatedRouteSnapshot | ActivatedRoute): UrlSegment[] {
|
||||||
|
return this.getRouteProperty(route, 'url', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a route, get its parent.
|
||||||
|
*
|
||||||
|
* @param route Route.
|
||||||
|
* @returns Parent.
|
||||||
|
*/
|
||||||
|
getRouteParent(route: ActivatedRouteSnapshot | ActivatedRoute): ActivatedRouteSnapshot | ActivatedRoute | null {
|
||||||
|
return this.getRouteProperty(route, 'parent', null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a route, get its data.
|
||||||
|
*
|
||||||
|
* @param route Route.
|
||||||
|
* @returns Data.
|
||||||
|
*/
|
||||||
|
getRouteData(route: ActivatedRouteSnapshot | ActivatedRoute): Data {
|
||||||
|
return this.getRouteProperty(route, 'data', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a route, get its params.
|
||||||
|
*
|
||||||
|
* @param route Route.
|
||||||
|
* @returns Params.
|
||||||
|
*/
|
||||||
|
getRouteParams(route: ActivatedRouteSnapshot | ActivatedRoute): Params {
|
||||||
|
return this.getRouteProperty(route, 'params', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a route, get its query params.
|
||||||
|
*
|
||||||
|
* @param route Route.
|
||||||
|
* @returns Query params.
|
||||||
|
*/
|
||||||
|
getRouteQueryParams(route: ActivatedRouteSnapshot | ActivatedRoute): Params {
|
||||||
|
return this.getRouteProperty(route, 'queryParams', {});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the current route page can block leaving the route.
|
* Check if the current route page can block leaving the route.
|
||||||
*
|
*
|
||||||
* @returns Whether the current route page can block leaving the route.
|
* @returns Whether the current route page can block leaving the route.
|
||||||
*/
|
*/
|
||||||
currentRouteCanBlockLeave(): boolean {
|
currentRouteCanBlockLeave(): boolean {
|
||||||
return !!this.getCurrentRoute().snapshot.routeConfig?.canDeactivate?.length;
|
return !!this.getCurrentRoute().snapshot?.routeConfig?.canDeactivate?.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -725,6 +776,36 @@ export class CoreNavigatorService {
|
||||||
return '../'.repeat(depth);
|
return '../'.repeat(depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a route, get one of its properties.
|
||||||
|
*
|
||||||
|
* @param route Route.
|
||||||
|
* @param property Route property.
|
||||||
|
* @param defaultValue Fallback value if the property is not set.
|
||||||
|
* @returns Property value.
|
||||||
|
*/
|
||||||
|
private getRouteProperty<T extends keyof ActivatedRouteSnapshot>(
|
||||||
|
route: ActivatedRouteSnapshot | ActivatedRoute,
|
||||||
|
property: T,
|
||||||
|
defaultValue: ActivatedRouteSnapshot[T],
|
||||||
|
): ActivatedRouteSnapshot[T] {
|
||||||
|
if (route instanceof ActivatedRouteSnapshot) {
|
||||||
|
return route[property];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (route.snapshot instanceof ActivatedRouteSnapshot) {
|
||||||
|
return route.snapshot[property];
|
||||||
|
}
|
||||||
|
|
||||||
|
const propertyObservable = route[property];
|
||||||
|
|
||||||
|
if (propertyObservable instanceof BehaviorSubject) {
|
||||||
|
return propertyObservable.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CoreNavigator = makeSingleton(CoreNavigatorService);
|
export const CoreNavigator = makeSingleton(CoreNavigatorService);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@core @app @javascript @lms_from4.0
|
@core @app @javascript
|
||||||
Feature: Custom lang strings
|
Feature: Custom lang strings
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
@core @app @javascript @lms_upto3.9
|
|
||||||
Feature: It opens files properly.
|
|
||||||
|
|
||||||
Background:
|
|
||||||
Given the following "users" exist:
|
|
||||||
| username |
|
|
||||||
| student1 |
|
|
||||||
And the following "courses" exist:
|
|
||||||
| fullname | shortname |
|
|
||||||
| Course 1 | C1 |
|
|
||||||
And the following "course enrolments" exist:
|
|
||||||
| user | course | role |
|
|
||||||
| student1 | C1 | student |
|
|
||||||
And the following "activities" exist:
|
|
||||||
| activity | name | intro | display | course | defaultfilename |
|
|
||||||
| resource | Test TXT | Test TXT description | 5 | C1 | A txt.txt |
|
|
||||||
| resource | Test RTF | Test RTF description | 5 | C1 | A rtf.rtf |
|
|
||||||
| resource | Test DOC | Test DOC description | 5 | C1 | A doc.doc |
|
|
||||||
|
|
||||||
Scenario: Open a file
|
|
||||||
Given I entered the resource activity "Test TXT" on course "Course 1" as "student1" in the app
|
|
||||||
When I press "Open" in the app
|
|
||||||
Then the app should have opened a browser tab with url "^blob:"
|
|
||||||
|
|
||||||
When I switch to the browser tab opened by the app
|
|
||||||
Then I should see "Test resource A txt.txt file"
|
|
||||||
|
|
||||||
When I close the browser tab opened by the app
|
|
||||||
And I press the back button in the app
|
|
||||||
And I press "Test RTF" in the app
|
|
||||||
And I press "Open" in the app
|
|
||||||
Then the app should have opened a browser tab with url "^blob:"
|
|
||||||
|
|
||||||
When I switch to the browser tab opened by the app
|
|
||||||
Then I should see "Test resource A rtf.rtf file"
|
|
||||||
|
|
||||||
When I close the browser tab opened by the app
|
|
||||||
And I press the back button in the app
|
|
||||||
And I press "Test DOC" in the app
|
|
||||||
And I press "Open" in the app
|
|
||||||
Then the app should have opened a browser tab with url "^blob:"
|
|
||||||
|
|
||||||
When I switch to the browser tab opened by the app
|
|
||||||
Then I should see "Test resource A doc.doc file"
|
|
|
@ -2,7 +2,8 @@
|
||||||
Feature: It opens files properly.
|
Feature: It opens files properly.
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the following "users" exist:
|
Given the Moodle site is compatible with this feature
|
||||||
|
And the following "users" exist:
|
||||||
| username |
|
| username |
|
||||||
| student1 |
|
| student1 |
|
||||||
And the following "courses" exist:
|
And the following "courses" exist:
|
||||||
|
@ -12,7 +13,6 @@ Feature: It opens files properly.
|
||||||
| user | course | role |
|
| user | course | role |
|
||||||
| student1 | C1 | student |
|
| student1 | C1 | student |
|
||||||
|
|
||||||
@lms_from3.10
|
|
||||||
Scenario: Open a file
|
Scenario: Open a file
|
||||||
Given the following "activities" exist:
|
Given the following "activities" exist:
|
||||||
| activity | name | intro | display | course | defaultfilename |
|
| activity | name | intro | display | course | defaultfilename |
|
||||||
|
|
|
@ -509,16 +509,16 @@ export class TestingBehatRuntimeService {
|
||||||
getHeader(): string {
|
getHeader(): string {
|
||||||
this.log('Action - Get header');
|
this.log('Action - Get header');
|
||||||
|
|
||||||
let titles = Array.from(document.querySelectorAll<HTMLElement>('.ion-page:not(.ion-page-hidden) > ion-header h1'))
|
const getBySelector = (selector: string ) => Array.from(document.querySelectorAll<HTMLElement>(selector))
|
||||||
.filter((title) => TestingBehatDomUtils.isElementVisible(title, document.body))
|
.filter((title) => TestingBehatDomUtils.isElementVisible(title, document.body))
|
||||||
.map((title) => title.innerText.trim());
|
.map((title) => title.innerText.trim())
|
||||||
|
.filter((title) => title.length > 0);
|
||||||
|
|
||||||
|
let titles = getBySelector('.ion-page:not(.ion-page-hidden) > ion-header h1');
|
||||||
|
|
||||||
// Collapsed title, get the floating title.
|
// Collapsed title, get the floating title.
|
||||||
if (titles.length < 0 || (titles.length === 1 && titles[0] === '')) {
|
if (titles.length === 0) {
|
||||||
titles = Array.from(document.querySelectorAll<HTMLElement>(
|
titles = getBySelector('.ion-page:not(.ion-page-hidden) h1.collapsible-header-floating-title');
|
||||||
'.ion-page:not(.ion-page-hidden) h1.collapsible-header-floating-title',
|
|
||||||
)).filter((title) => TestingBehatDomUtils.isElementVisible(title, document.body))
|
|
||||||
.map((title) => title.innerText.trim());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (titles.length > 1) {
|
if (titles.length > 1) {
|
||||||
|
|
|
@ -108,8 +108,9 @@ body:not(.core-iframe-fullscreen) .collapsible-header-page {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsible-header-expanded h1 {
|
.collapsible-header-expanded .collapsible-header-original-title {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue