MOBILE-3947 reminders: Fix tests
parent
21d0dc6821
commit
44606242fd
|
@ -781,13 +781,10 @@ class behat_app extends behat_app_helper {
|
|||
/**
|
||||
* Sets a field to the given text value in the app.
|
||||
*
|
||||
* Currently this only works for input fields which must be identified using a partial or
|
||||
* exact match on the placeholder text.
|
||||
*
|
||||
* @Given /^I set the field "((?:[^"]|\\")+)" to "((?:[^"]|\\")*)" in the app$/
|
||||
* @param string $field Text identifying field
|
||||
* @param string $value Value for field
|
||||
* @throws DriverException If the field set doesn't work
|
||||
* @param string $field Text identifying the field.
|
||||
* @param string $value Value to set. In select fields, this can be either the value or text included in the select option.
|
||||
* @throws DriverException If the field set doesn't work.
|
||||
*/
|
||||
public function i_set_the_field_in_the_app(string $field, string $value) {
|
||||
$field = addslashes_js($field);
|
||||
|
|
|
@ -16,52 +16,48 @@ Feature: Set a new reminder on activity
|
|||
| assign | C1 | assign01 | Assignment 01 | ## yesterday ## | ## now +70 minutes ## |
|
||||
| assign | C1 | assign02 | Assignment 02 | ## yesterday ## | ## 1 January 2050 ## |
|
||||
|
||||
@ionic7_failure
|
||||
Scenario: Add, delete and update reminder on activity
|
||||
Given I entered the assign activity "Assignment 01" on course "Course 1" as "student1" in the app
|
||||
|
||||
Then I should not find "Set a reminder for \"Assignment 01\" (Opened)" in the app
|
||||
And I should find "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
And "Set a reminder for \"Assignment 01\" (Due)" should not be selected in the app
|
||||
And I should not find "Reminder set for" in the app
|
||||
But I should find "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
|
||||
# Default set
|
||||
When I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
And "Set a reminder for \"Assignment 01\" (Due)" should be selected in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
|
||||
# Set from list
|
||||
When I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
Then I should find "Set a reminder" in the app
|
||||
And "At the time of the event" should be selected in the app
|
||||
And "1 hour before" should not be selected in the app
|
||||
But "1 hour before" should not be selected in the app
|
||||
When I press "1 hour before" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
And "Set a reminder for \"Assignment 01\" (Due)" should be selected in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
|
||||
# Custom set
|
||||
When I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
Then I should find "Set a reminder" in the app
|
||||
And "At the time of the event" should not be selected in the app
|
||||
And "1 hour before" should be selected in the app
|
||||
But "At the time of the event" should not be selected in the app
|
||||
When I press "Custom..." in the app
|
||||
Then I should find "Custom reminder" in the app
|
||||
When I set the following fields to these values in the app:
|
||||
| Value | 4 |
|
||||
| Units | minutes |
|
||||
And I press "Set reminder" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
And "Set a reminder for \"Assignment 01\" (Due)" should be selected in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
|
||||
# Remove
|
||||
When I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
Then "4 minutes before" should be selected in the app
|
||||
When I press "Delete reminder" in the app
|
||||
Then I should find "Reminder deleted" in the app
|
||||
And "Set a reminder for \"Assignment 01\" (Due)" should not be selected in the app
|
||||
But I should not find "Reminder set for" in the app
|
||||
|
||||
# Set and check reminder
|
||||
When I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
When I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
And I press "Custom..." in the app
|
||||
Then I should find "Custom reminder" in the app
|
||||
|
@ -69,7 +65,7 @@ Feature: Set a new reminder on activity
|
|||
| Value | 69 |
|
||||
| Units | minutes |
|
||||
And I press "Set reminder" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
When I wait "50" seconds
|
||||
Then a notification with title "Due: Assignment 01" is present in the app
|
||||
And I close a notification with title "Due: Assignment 01" in the app
|
||||
|
@ -82,9 +78,9 @@ Feature: Set a new reminder on activity
|
|||
| Value | 68 |
|
||||
| Units | minutes |
|
||||
And I press "Set reminder" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
When I press "Set a reminder for \"Assignment 01\" (Due)" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
Then I should find "Reminder set for" in the app
|
||||
When I press "Delete reminder" in the app
|
||||
Then I should find "Reminder deleted" in the app
|
||||
When I wait "50" seconds
|
||||
|
|
|
@ -12,34 +12,33 @@ Feature: Set a new reminder on course
|
|||
| user | course | role |
|
||||
| student1 | C1 | student |
|
||||
|
||||
@ionic7_failure
|
||||
Scenario: Add, delete and update reminder on course
|
||||
Given I entered the course "Course 1" as "student1" in the app
|
||||
And I press "Course summary" in the app
|
||||
|
||||
Then I should not find "Set a reminder for \"Course 1\" (Course start date)" in the app
|
||||
And I should find "Set a reminder for \"Course 1\" (Course end date)" in the app
|
||||
And "Set a reminder for \"Course 1\" (Course end date)" should not be selected in the app
|
||||
And I should not find "Reminder set for" in the app
|
||||
But I should find "Set a reminder for \"Course 1\" (Course end date)" in the app
|
||||
|
||||
# Default set
|
||||
When I press "Set a reminder for \"Course 1\" (Course end date)" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
And "Set a reminder for \"Course 1\" (Course end date)" should be selected in the app
|
||||
And I should find "Reminder set for" in the app
|
||||
|
||||
# Set from list
|
||||
When I press "Set a reminder for \"Course 1\" (Course end date)" in the app
|
||||
Then I should find "Set a reminder" in the app
|
||||
And "At the time of the event" should be selected in the app
|
||||
And "12 hours before" should not be selected in the app
|
||||
But "12 hours before" should not be selected in the app
|
||||
When I press "12 hours before" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
And "Set a reminder for \"Course 1\" (Course end date)" should be selected in the app
|
||||
And I should find "Reminder set for" in the app
|
||||
|
||||
# Custom set
|
||||
When I press "Set a reminder for \"Course 1\" (Course end date)" in the app
|
||||
Then I should find "Set a reminder" in the app
|
||||
And "At the time of the event" should not be selected in the app
|
||||
And "12 hours before" should be selected in the app
|
||||
But "12 hours before" should be selected in the app
|
||||
When I press "Custom..." in the app
|
||||
Then I should find "Custom reminder" in the app
|
||||
When I set the following fields to these values in the app:
|
||||
|
@ -47,11 +46,11 @@ Feature: Set a new reminder on course
|
|||
| Units | hours |
|
||||
And I press "Set reminder" in the app
|
||||
Then I should find "Reminder set for " in the app
|
||||
And "Set a reminder for \"Course 1\" (Course end date)" should be selected in the app
|
||||
And I should find "Reminder set for" in the app
|
||||
|
||||
# Remove
|
||||
When I press "Set a reminder for \"Course 1\" (Course end date)" in the app
|
||||
Then "2 hours before" should be selected in the app
|
||||
When I press "Delete reminder" in the app
|
||||
Then I should find "Reminder deleted" in the app
|
||||
And "Set a reminder for \"Course 1\" (Course end date)" should not be selected in the app
|
||||
But I should not find "Reminder set for" in the app
|
||||
|
|
|
@ -276,7 +276,7 @@ export class TestingBehatDomUtilsService {
|
|||
/**
|
||||
* Given a list of elements, get the top ancestors among all of them.
|
||||
*
|
||||
* This will remote duplicates and drop any elements nested within each other.
|
||||
* This will remove duplicates and drop any elements nested within each other.
|
||||
*
|
||||
* @param elements Elements list.
|
||||
* @returns Top ancestors.
|
||||
|
@ -480,6 +480,34 @@ export class TestingBehatDomUtilsService {
|
|||
return this.findElementsBasedOnText(locator, options)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until an element with the given selector is found.
|
||||
*
|
||||
* @param selector Element selector.
|
||||
* @param timeout Timeout after which an error is thrown.
|
||||
* @param retryFrequency Frequency for retries when the element is not found.
|
||||
* @returns Element.
|
||||
*/
|
||||
async waitForElement<T extends HTMLElement = HTMLElement>(
|
||||
selector: string,
|
||||
timeout: number = 2000,
|
||||
retryFrequency: number = 100,
|
||||
): Promise<T> {
|
||||
const element = document.querySelector<T>(selector);
|
||||
|
||||
if (!element) {
|
||||
if (timeout < retryFrequency) {
|
||||
throw new Error(`Element with '${selector}' selector not found`);
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, retryFrequency));
|
||||
|
||||
return this.waitForElement<T>(selector, timeout - retryFrequency, retryFrequency);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to find elements based on their text or Aria label.
|
||||
*
|
||||
|
@ -515,7 +543,7 @@ export class TestingBehatDomUtilsService {
|
|||
protected findElementsBasedOnTextInContainer(
|
||||
locator: TestingBehatElementLocator,
|
||||
topContainer: HTMLElement,
|
||||
options: TestingBehatFindOptions,
|
||||
options: TestingBehatFindOptions = {},
|
||||
): HTMLElement[] {
|
||||
let container: HTMLElement | null = topContainer;
|
||||
|
||||
|
@ -667,37 +695,26 @@ export class TestingBehatDomUtilsService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set an element value.
|
||||
* Set an input element value.
|
||||
*
|
||||
* @param element HTML to set.
|
||||
* @param value Value to be set.
|
||||
* @param element Input element.
|
||||
* @param value Value.
|
||||
*/
|
||||
async setElementValue(element: HTMLInputElement | HTMLElement, value: string): Promise<void> {
|
||||
async setInputValue(element: HTMLInputElement | HTMLElement, value: string): Promise<void> {
|
||||
await NgZone.run(async () => {
|
||||
const promise = new CorePromisedValue<void>();
|
||||
|
||||
// Functions to get/set value depending on field type.
|
||||
const setValue = (text: string) => {
|
||||
if (! ('value' in element)) {
|
||||
element.innerHTML = text;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const setValue = async (text: string) => {
|
||||
if (element.tagName === 'ION-SELECT') {
|
||||
value = value.trim();
|
||||
const optionValue = Array.from(element.querySelectorAll('ion-select-option'))
|
||||
.find((option) => option.innerHTML.trim() === value);
|
||||
|
||||
if (optionValue) {
|
||||
element.value = optionValue.value;
|
||||
}
|
||||
} else {
|
||||
this.setIonSelectInputValue(element, value);
|
||||
} else if ('value' in element) {
|
||||
element.value = text;
|
||||
} else {
|
||||
element.innerHTML = text;
|
||||
}
|
||||
|
||||
element.dispatchEvent(new Event('ionChange'));
|
||||
};
|
||||
|
||||
const getValue = () => {
|
||||
if ('value' in element) {
|
||||
return element.value;
|
||||
|
@ -707,38 +724,79 @@ export class TestingBehatDomUtilsService {
|
|||
};
|
||||
|
||||
// Pretend we have cut and pasted the new text.
|
||||
let event: InputEvent;
|
||||
if (getValue() !== '') {
|
||||
event = new InputEvent('input', {
|
||||
if (element.tagName !== 'ION-SELECT' && getValue() !== '') {
|
||||
await CoreUtils.nextTick();
|
||||
await setValue('');
|
||||
|
||||
element.dispatchEvent(new InputEvent('input', {
|
||||
bubbles: true,
|
||||
view: window,
|
||||
cancelable: true,
|
||||
inputType: 'deleteByCut',
|
||||
});
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
setValue('');
|
||||
element.dispatchEvent(event);
|
||||
}));
|
||||
}
|
||||
|
||||
if (value !== '') {
|
||||
event = new InputEvent('input', {
|
||||
await CoreUtils.nextTick();
|
||||
await setValue(value);
|
||||
|
||||
element.dispatchEvent(new InputEvent('input', {
|
||||
bubbles: true,
|
||||
view: window,
|
||||
cancelable: true,
|
||||
inputType: 'insertFromPaste',
|
||||
data: value,
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
await CoreUtils.nextTick();
|
||||
setValue(value);
|
||||
element.dispatchEvent(event);
|
||||
}
|
||||
|
||||
promise.resolve();
|
||||
/**
|
||||
* Select an option in an ion-select element.
|
||||
*
|
||||
* @param element IonSelect element.
|
||||
* @param value Value.
|
||||
*/
|
||||
protected async setIonSelectInputValue(element: HTMLElement, value: string): Promise<void> {
|
||||
// Press select.
|
||||
await TestingBehatDomUtils.pressElement(element);
|
||||
|
||||
return promise;
|
||||
});
|
||||
// Press option.
|
||||
type IonSelectInterface = 'alert' | 'action-sheet' | 'popover';
|
||||
const selectInterface = element.getAttribute('interface') as IonSelectInterface ?? 'alert';
|
||||
const containerSelector = ({
|
||||
'alert': 'ion-alert.select-alert',
|
||||
'action-sheet': 'ion-action-sheet.select-action-sheet',
|
||||
'popover': 'ion-popover.select-popover',
|
||||
})[selectInterface];
|
||||
const optionSelector = ({
|
||||
'alert': 'button',
|
||||
'action-sheet': 'button',
|
||||
'popover': 'ion-radio',
|
||||
})[selectInterface] ?? '';
|
||||
const optionsContainer = await TestingBehatDomUtils.waitForElement(containerSelector);
|
||||
const options = this.findElementsBasedOnTextInContainer(
|
||||
{ text: value, selector: optionSelector },
|
||||
optionsContainer,
|
||||
{},
|
||||
);
|
||||
|
||||
if (options.length === 0) {
|
||||
throw new Error('Couldn\'t find ion-select option.');
|
||||
}
|
||||
|
||||
await TestingBehatDomUtils.pressElement(options[0]);
|
||||
|
||||
// Press options submit.
|
||||
if (selectInterface === 'alert') {
|
||||
const submitButton = optionsContainer.querySelector<HTMLElement>('.alert-button-group button:last-child');
|
||||
|
||||
if (!submitButton) {
|
||||
throw new Error('Couldn\'t find ion-select submit button.');
|
||||
}
|
||||
|
||||
await TestingBehatDomUtils.pressElement(submitButton);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { TestingBehatDomUtils } from './behat-dom';
|
||||
import { TestingBehatDomUtils, TestingBehatDomUtilsService } from './behat-dom';
|
||||
import { TestingBehatBlocking } from './behat-blocking';
|
||||
import { CoreCustomURLSchemes, CoreCustomURLSchemesProvider } from '@services/urlschemes';
|
||||
import { ONBOARDING_DONE } from '@features/login/constants';
|
||||
|
@ -63,6 +63,10 @@ export class TestingBehatRuntimeService {
|
|||
return CoreNavigator.instance;
|
||||
}
|
||||
|
||||
get domUtils(): TestingBehatDomUtilsService {
|
||||
return TestingBehatDomUtils.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init behat functions and set options like skipping onboarding.
|
||||
*
|
||||
|
@ -468,11 +472,22 @@ export class TestingBehatRuntimeService {
|
|||
?? options.find(option => option.text === value)?.value
|
||||
?? options.find(option => option.text.includes(value))?.value
|
||||
?? value;
|
||||
} else if (input.tagName === 'ION-SELECT') {
|
||||
const options = Array.from(input.querySelectorAll('ion-select-option'));
|
||||
|
||||
value = options.find(option => option.value?.toString() === value)?.textContent?.trim()
|
||||
?? options.find(option => option.textContent?.trim() === value)?.textContent?.trim()
|
||||
?? options.find(option => option.textContent?.includes(value))?.textContent?.trim()
|
||||
?? value;
|
||||
}
|
||||
|
||||
await TestingBehatDomUtils.setElementValue(input, value);
|
||||
try {
|
||||
await TestingBehatDomUtils.setInputValue(input, value);
|
||||
|
||||
return 'OK';
|
||||
} catch (error) {
|
||||
return `ERROR: ${error.message ?? 'Unknown error'}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue