Merge pull request #3928 from NoelDeMartin/MOBILE-4339
MOBILE-4339 quiz: Add unanswered questions warningmain
commit
7a9013c2e9
|
@ -930,6 +930,7 @@
|
||||||
"addon.mod_quiz.stateoverdue": "quiz",
|
"addon.mod_quiz.stateoverdue": "quiz",
|
||||||
"addon.mod_quiz.stateoverduedetails": "quiz",
|
"addon.mod_quiz.stateoverduedetails": "quiz",
|
||||||
"addon.mod_quiz.status": "quiz",
|
"addon.mod_quiz.status": "quiz",
|
||||||
|
"addon.mod_quiz.submission_confirmation_unanswered": "quiz",
|
||||||
"addon.mod_quiz.submitallandfinish": "quiz",
|
"addon.mod_quiz.submitallandfinish": "quiz",
|
||||||
"addon.mod_quiz.summaryofattempt": "quiz",
|
"addon.mod_quiz.summaryofattempt": "quiz",
|
||||||
"addon.mod_quiz.summaryofattempts": "quiz",
|
"addon.mod_quiz.summaryofattempts": "quiz",
|
||||||
|
|
|
@ -68,6 +68,7 @@
|
||||||
"stateoverdue": "Overdue",
|
"stateoverdue": "Overdue",
|
||||||
"stateoverduedetails": "Must be submitted by {{$a}}",
|
"stateoverduedetails": "Must be submitted by {{$a}}",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
|
"submission_confirmation_unanswered": "Questions without a response: {{$a}}",
|
||||||
"submitallandfinish": "Submit all and finish",
|
"submitallandfinish": "Submit all and finish",
|
||||||
"summaryofattempt": "Summary of attempt",
|
"summaryofattempt": "Summary of attempt",
|
||||||
"summaryofattempts": "Summary of your previous attempts",
|
"summaryofattempts": "Summary of your previous attempts",
|
||||||
|
|
|
@ -406,7 +406,34 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
|
||||||
try {
|
try {
|
||||||
// Show confirm if the user clicked the finish button and the quiz is in progress.
|
// Show confirm if the user clicked the finish button and the quiz is in progress.
|
||||||
if (!timeUp && this.attempt.state == AddonModQuizProvider.ATTEMPT_IN_PROGRESS) {
|
if (!timeUp && this.attempt.state == AddonModQuizProvider.ATTEMPT_IN_PROGRESS) {
|
||||||
await CoreDomUtils.showConfirm(Translate.instant('addon.mod_quiz.confirmclose'));
|
let message = Translate.instant('addon.mod_quiz.confirmclose');
|
||||||
|
|
||||||
|
const unansweredCount = this.summaryQuestions
|
||||||
|
.filter(question => AddonModQuiz.isQuestionUnanswered(question))
|
||||||
|
.length;
|
||||||
|
|
||||||
|
if (unansweredCount > 0) {
|
||||||
|
const warning = Translate.instant(
|
||||||
|
'addon.mod_quiz.submission_confirmation_unanswered',
|
||||||
|
{ $a: unansweredCount },
|
||||||
|
);
|
||||||
|
|
||||||
|
message += `
|
||||||
|
<ion-card class="core-warning-card">
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>
|
||||||
|
${ warning }
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
await CoreDomUtils.showConfirm(
|
||||||
|
message,
|
||||||
|
Translate.instant('addon.mod_quiz.submitallandfinish'),
|
||||||
|
Translate.instant('core.submit'),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
modal = await CoreDomUtils.showModalLoading('core.sending', true);
|
modal = await CoreDomUtils.showModalLoading('core.sending', true);
|
||||||
|
|
|
@ -41,6 +41,7 @@ import { AddonModQuizAttempt } from './quiz-helper';
|
||||||
import { AddonModQuizOffline, AddonModQuizQuestionsWithAnswers } from './quiz-offline';
|
import { AddonModQuizOffline, AddonModQuizQuestionsWithAnswers } from './quiz-offline';
|
||||||
import { AddonModQuizAutoSyncData, AddonModQuizSyncProvider } from './quiz-sync';
|
import { AddonModQuizAutoSyncData, AddonModQuizSyncProvider } from './quiz-sync';
|
||||||
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
||||||
|
import { QUESTION_INVALID_STATE_CLASSES, QUESTION_TODO_STATE_CLASSES } from '@features/question/constants';
|
||||||
|
|
||||||
const ROOT_CACHE_KEY = 'mmaModQuiz:';
|
const ROOT_CACHE_KEY = 'mmaModQuiz:';
|
||||||
|
|
||||||
|
@ -1517,6 +1518,21 @@ export class AddonModQuizProvider {
|
||||||
return !!element.querySelector('.mod_quiz-blocked_question_warning');
|
return !!element.querySelector('.mod_quiz-blocked_question_warning');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a question is unanswered.
|
||||||
|
*
|
||||||
|
* @param question Question.
|
||||||
|
* @returns Whether it's unanswered.
|
||||||
|
*/
|
||||||
|
isQuestionUnanswered(question: CoreQuestionQuestionParsed): boolean {
|
||||||
|
if (!question.stateclass) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QUESTION_TODO_STATE_CLASSES.some(stateClass => stateClass === question.stateclass)
|
||||||
|
|| QUESTION_INVALID_STATE_CLASSES.some(stateClass => stateClass === question.stateclass);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a quiz is enabled to be used in offline.
|
* Check if a quiz is enabled to be used in offline.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
@addon_mod_quiz @app @javascript @lms_from4.0 @lms_upto4.3
|
||||||
|
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 unanswered questions warning
|
||||||
|
# is not available before 4.4.
|
||||||
|
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 "Questions" "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 on" in the app
|
||||||
|
And I should find "State" in the app
|
||||||
|
And I should find "Completed on" in the app
|
||||||
|
And I should find "Time taken" 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
|
||||||
|
And the UI should match the snapshot
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
When I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(1) p:nth-child(2)" with "[Started on date]"
|
||||||
|
And I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(3) p:nth-child(2)" with "[Completed on date]"
|
||||||
|
Then the UI should match the snapshot
|
||||||
|
|
||||||
|
Given I entered the quiz activity "Quiz 1" on course "Course 1" as "teacher1" in the app
|
||||||
|
When I press "Information" in the app
|
||||||
|
And I press "Open in browser" in the app
|
||||||
|
And I switch to the browser tab opened by the app
|
||||||
|
And I log 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"
|
|
@ -125,7 +125,7 @@ Feature: Attempt a quiz in app
|
||||||
Then I should find "Summary of attempt" in the app
|
Then I should find "Summary of attempt" in the app
|
||||||
|
|
||||||
When I press "Submit all and finish" in the app
|
When I press "Submit all and finish" in the app
|
||||||
And I press "OK" near "Once you submit" in the app
|
And I press "Submit" near "Once you submit" in the app
|
||||||
Then I should find "Review" in the app
|
Then I should find "Review" in the app
|
||||||
And I should find "Started on" in the app
|
And I should find "Started on" in the app
|
||||||
And I should find "State" in the app
|
And I should find "State" in the app
|
||||||
|
@ -181,7 +181,7 @@ Feature: Attempt a quiz in app
|
||||||
But I should not find "Not yet answered" in the app
|
But I should not find "Not yet answered" in the app
|
||||||
|
|
||||||
When I press "Submit all and finish" in the app
|
When I press "Submit all and finish" in the app
|
||||||
And I press "OK" in the app
|
And I press "Submit" in the app
|
||||||
Then I should find "Review" in the app
|
Then I should find "Review" in the app
|
||||||
And I should find "Finished" in the app
|
And I should find "Finished" in the app
|
||||||
And I should find "Not yet graded" in the app
|
And I should find "Not yet graded" in the app
|
||||||
|
@ -200,7 +200,7 @@ Feature: Attempt a quiz in app
|
||||||
And I press "False" in the app
|
And I press "False" in the app
|
||||||
And I press "Submit" in the app
|
And I press "Submit" in the app
|
||||||
And I press "Submit all and finish" in the app
|
And I press "Submit all and finish" in the app
|
||||||
And I press "OK" in the app
|
And I press "Submit" in the app
|
||||||
Then I should find "Review" in the app
|
Then I should find "Review" in the app
|
||||||
|
|
||||||
When I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(1) p:nth-child(2)" with "[Started on date]"
|
When I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(1) p:nth-child(2)" with "[Started on date]"
|
||||||
|
|
|
@ -113,7 +113,7 @@ Feature: Attempt a quiz in app
|
||||||
And I should find "Incomplete answer" within "9" "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
|
When I press "Submit all and finish" in the app
|
||||||
And I press "OK" in the app
|
And I press "Submit" in the app
|
||||||
Then I should find "Review" in the app
|
Then I should find "Review" in the app
|
||||||
And I should find "Finished" in the app
|
And I should find "Finished" in the app
|
||||||
And I should find "Not yet graded" in the app
|
And I should find "Not yet graded" in the app
|
||||||
|
|
|
@ -117,12 +117,13 @@ Feature: Attempt a quiz in app
|
||||||
When I press "Submit" in the app
|
When I press "Submit" in the app
|
||||||
And I press "Submit all and finish" in the app
|
And I press "Submit all and finish" in the app
|
||||||
Then I should find "Once you submit" in the app
|
Then I should find "Once you submit" in the app
|
||||||
|
And I should find "Questions without a response: 2" in the app
|
||||||
|
|
||||||
When I press "Cancel" near "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
|
Then I should find "Summary of attempt" in the app
|
||||||
|
|
||||||
When I press "Submit all and finish" in the app
|
When I press "Submit all and finish" in the app
|
||||||
And I press "OK" near "Once you submit" in the app
|
And I press "Submit" near "Once you submit" in the app
|
||||||
Then I should find "Review" in the app
|
Then I should find "Review" in the app
|
||||||
And I should find "Started on" in the app
|
And I should find "Started on" in the app
|
||||||
And I should find "State" in the app
|
And I should find "State" in the app
|
||||||
|
@ -178,7 +179,9 @@ Feature: Attempt a quiz in app
|
||||||
But I should not find "Not yet answered" in the app
|
But I should not find "Not yet answered" in the app
|
||||||
|
|
||||||
When I press "Submit all and finish" in the app
|
When I press "Submit all and finish" in the app
|
||||||
And I press "OK" in the app
|
Then I should find "Questions without a response: 1" in the app
|
||||||
|
|
||||||
|
When I press "Submit" in the app
|
||||||
Then I should find "Review" in the app
|
Then I should find "Review" in the app
|
||||||
And I should find "Finished" in the app
|
And I should find "Finished" in the app
|
||||||
And I should find "Not yet graded" in the app
|
And I should find "Not yet graded" in the app
|
||||||
|
@ -198,7 +201,10 @@ Feature: Attempt a quiz in app
|
||||||
And I press "False" in the app
|
And I press "False" in the app
|
||||||
And I press "Submit" in the app
|
And I press "Submit" in the app
|
||||||
And I press "Submit all and finish" in the app
|
And I press "Submit all and finish" in the app
|
||||||
And I press "OK" in the app
|
Then I should find "Once you submit" in the app
|
||||||
|
But I should not find "Questions without a response" in the app
|
||||||
|
|
||||||
|
When I press "Submit" in the app
|
||||||
Then I should find "Review" in the app
|
Then I should find "Review" in the app
|
||||||
|
|
||||||
When I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(1) p:nth-child(2)" with "[Started on date]"
|
When I replace "/.*/" within "page-addon-mod-quiz-review core-loading > ion-card ion-item:nth-child(1) p:nth-child(2)" with "[Started on date]"
|
||||||
|
|
|
@ -46,7 +46,7 @@ Feature: Use quizzes with different behaviours in the app
|
||||||
|
|
||||||
When I press "Submit" in the app
|
When I press "Submit" in the app
|
||||||
And I press "Submit all and finish" in the app
|
And I press "Submit all and finish" in the app
|
||||||
And I press "OK" near "Once you submit" in the app
|
And I press "Submit" near "Once you submit" in the app
|
||||||
Then I should find "Mark 0.33 out of 1.00" in the app
|
Then I should find "Mark 0.33 out of 1.00" in the app
|
||||||
|
|
||||||
Scenario: Immediate feedback behaviour
|
Scenario: Immediate feedback behaviour
|
||||||
|
@ -85,7 +85,7 @@ Feature: Use quizzes with different behaviours in the app
|
||||||
|
|
||||||
When I press "Submit" in the app
|
When I press "Submit" in the app
|
||||||
And I press "Submit all and finish" in the app
|
And I press "Submit all and finish" in the app
|
||||||
And I press "OK" near "Once you submit" in the app
|
And I press "Submit" near "Once you submit" in the app
|
||||||
Then I should find "Mark 1.00 out of 1.00" in the app
|
Then I should find "Mark 1.00 out of 1.00" in the app
|
||||||
|
|
||||||
Scenario: Deferred feedback with CBM behaviour
|
Scenario: Deferred feedback with CBM behaviour
|
||||||
|
@ -103,7 +103,7 @@ Feature: Use quizzes with different behaviours in the app
|
||||||
And I press "Quite sure" in the app
|
And I press "Quite sure" in the app
|
||||||
And I press "Submit" in the app
|
And I press "Submit" in the app
|
||||||
And I press "Submit all and finish" in the app
|
And I press "Submit all and finish" in the app
|
||||||
And I press "OK" near "Once you submit" in the app
|
And I press "Submit" near "Once you submit" in the app
|
||||||
Then I should find "CBM mark 1.50" in the app
|
Then I should find "CBM mark 1.50" in the app
|
||||||
And I should find "Parts, but only parts, of your response are correct" in the app
|
And I should find "Parts, but only parts, of your response are correct" in the app
|
||||||
|
|
||||||
|
@ -147,5 +147,5 @@ Feature: Use quizzes with different behaviours in the app
|
||||||
|
|
||||||
When I press "Submit" in the app
|
When I press "Submit" in the app
|
||||||
And I press "Submit all and finish" in the app
|
And I press "Submit all and finish" in the app
|
||||||
And I press "OK" near "Once you submit" in the app
|
And I press "Submit" near "Once you submit" in the app
|
||||||
Then I should find "Mark 0.33 out of 1.00" in the app
|
Then I should find "Mark 0.33 out of 1.00" in the app
|
||||||
|
|
|
@ -78,7 +78,7 @@ Feature: Navigate through a quiz in the app
|
||||||
Then I should find "Summary of attempt" in the app
|
Then I should find "Summary of attempt" in the app
|
||||||
|
|
||||||
When I press "Submit all and finish" in the app
|
When I press "Submit all and finish" in the app
|
||||||
And I press "OK" near "Once you submit" in the app
|
And I press "Submit" near "Once you submit" in the app
|
||||||
Then I should find "Review" in the app
|
Then I should find "Review" in the app
|
||||||
And I should find "Text of the first question" in the app
|
And I should find "Text of the first question" in the app
|
||||||
And I should find "Text of the second question" in the app
|
And I should find "Text of the second question" in the app
|
||||||
|
@ -129,7 +129,7 @@ Feature: Navigate through a quiz in the app
|
||||||
# # And I should find "Not yet answered" within "3" "ion-item" in the app
|
# # And I should find "Not yet answered" within "3" "ion-item" in the app
|
||||||
|
|
||||||
# When I press "Submit all and finish" in the app
|
# When I press "Submit all and finish" in the app
|
||||||
# And I press "OK" near "Once you submit" in the app
|
# And I press "Submit" near "Once you submit" in the app
|
||||||
# Then I should find "Review" in the app
|
# Then I should find "Review" in the app
|
||||||
# # @todo MOBILE-4350: Uncomment these.
|
# # @todo MOBILE-4350: Uncomment these.
|
||||||
# # And I should find "Text of the first question" in the app
|
# # And I should find "Text of the first question" in the app
|
||||||
|
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
@ -0,0 +1,21 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
export const QUESTION_TODO_STATE_CLASSES = ['notyetanswered'] as const;
|
||||||
|
export const QUESTION_INVALID_STATE_CLASSES = ['invalidanswer'] as const;
|
||||||
|
export const QUESTION_COMPLETE_STATE_CLASSES = ['answersaved'] as const;
|
||||||
|
export const QUESTION_NEEDS_GRADING_STATE_CLASSES = ['requiresgrading', 'complete'] as const;
|
||||||
|
export const QUESTION_FINISHED_STATE_CLASSES = ['complete'] as const;
|
||||||
|
export const QUESTION_GAVE_UP_STATE_CLASSES = ['notanswered'] as const;
|
||||||
|
export const QUESTION_GRADED_STATE_CLASSES = ['complete', 'incorrect', 'partiallycorrect', 'correct'] as const;
|
|
@ -28,6 +28,15 @@ import {
|
||||||
QUESTION_ANSWERS_TABLE_NAME,
|
QUESTION_ANSWERS_TABLE_NAME,
|
||||||
QUESTION_TABLE_NAME,
|
QUESTION_TABLE_NAME,
|
||||||
} from './database/question';
|
} from './database/question';
|
||||||
|
import {
|
||||||
|
QUESTION_COMPLETE_STATE_CLASSES,
|
||||||
|
QUESTION_FINISHED_STATE_CLASSES,
|
||||||
|
QUESTION_GAVE_UP_STATE_CLASSES,
|
||||||
|
QUESTION_GRADED_STATE_CLASSES,
|
||||||
|
QUESTION_INVALID_STATE_CLASSES,
|
||||||
|
QUESTION_NEEDS_GRADING_STATE_CLASSES,
|
||||||
|
QUESTION_TODO_STATE_CLASSES,
|
||||||
|
} from '@features/question/constants';
|
||||||
|
|
||||||
const QUESTION_PREFIX_REGEX = /q\d+:(\d+)_/;
|
const QUESTION_PREFIX_REGEX = /q\d+:(\d+)_/;
|
||||||
const STATES: Record<string, CoreQuestionState> = {
|
const STATES: Record<string, CoreQuestionState> = {
|
||||||
|
@ -598,6 +607,14 @@ export type CoreQuestionQuestionWSData = {
|
||||||
questionnumber?: string; // @since 4.2. Question ordering number in the quiz.
|
questionnumber?: string; // @since 4.2. Question ordering number in the quiz.
|
||||||
state?: string; // The state where the question is in. It won't be returned if the user cannot see it.
|
state?: string; // The state where the question is in. It won't be returned if the user cannot see it.
|
||||||
status?: string; // Current formatted state of the question.
|
status?: string; // Current formatted state of the question.
|
||||||
|
stateclass?: // @since 4.4. A machine-readable class name for the state that this question attempt is in.
|
||||||
|
typeof QUESTION_TODO_STATE_CLASSES[number] |
|
||||||
|
typeof QUESTION_INVALID_STATE_CLASSES[number] |
|
||||||
|
typeof QUESTION_COMPLETE_STATE_CLASSES[number] |
|
||||||
|
typeof QUESTION_NEEDS_GRADING_STATE_CLASSES[number] |
|
||||||
|
typeof QUESTION_FINISHED_STATE_CLASSES[number] |
|
||||||
|
typeof QUESTION_GAVE_UP_STATE_CLASSES[number] |
|
||||||
|
typeof QUESTION_GRADED_STATE_CLASSES[number];
|
||||||
blockedbyprevious?: boolean; // Whether the question is blocked by the previous question.
|
blockedbyprevious?: boolean; // Whether the question is blocked by the previous question.
|
||||||
mark?: string; // The mark awarded. It will be returned only if the user is allowed to see it.
|
mark?: string; // The mark awarded. It will be returned only if the user is allowed to see it.
|
||||||
maxmark?: number; // The maximum mark possible for this question attempt.
|
maxmark?: number; // The maximum mark possible for this question attempt.
|
||||||
|
|
|
@ -514,6 +514,12 @@ ion-alert {
|
||||||
.alert-message {
|
.alert-message {
|
||||||
user-select: text;
|
user-select: text;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
ion-card {
|
||||||
|
margin: 0;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue