Repeat a task or action until a condition #1641
Replies: 4 comments
-
|
I shared my code here, if t helps. #251 But it's a silly 'repeat n times', not a 'repeat until this condition is matched' so probably not quite what you search for. |
Beta Was this translation helpful? Give feedback.
-
|
Here you can find another solution to this issue: I'm copying-pasting the output, but if you want more context, check the link. export class NavigateThroughItemList implements Task {
static untilFinds(itemName: string): NavigateThroughItemList {
return new NavigateThroughItemList(itemName);
}
constructor(private itemName: string) {
}
@step('{0} navigates through the list until #itemName is found')
performAs(actor: PerformsTasks): PromiseLike<void> {
return actor.attemptsTo(
See.if(Text.ofAll(ItemList.items), include(this.itemName)),
).catch(() => actor
.attemptsTo(
See.if(
WebElement.of(ItemList.nextButton),
isEnabled(),
),
)
.then(() => actor
.attemptsTo(
Click.on(ItemList.nextButton),
))
// Looping until it finds the item
.then(() => this.performAs(actor)));
}
}``` |
Beta Was this translation helpful? Give feedback.
-
|
@jan-molak any update on this topic? is there something that we can use from v3 to achieve this? or needs to be created from scratch? |
Beta Was this translation helpful? Give feedback.
-
|
I've created this and it works fine. You might need to improve it for handling timeout or configure max attempts, but it should work by just copy pasting. Or you might want to switch order of methods so it reads like import {
Activity,
Answerable,
AnswersQuestions,
AssertionError,
Duration,
Expectation,
ExpectationMet,
PerformsActivities,
RaiseErrors,
Task,
the,
UsesAbilities,
Wait
} from '@serenity-js/core';
export class Repeat<Actual> {
static until<Actual>(
actual: Answerable<Actual>,
expectation: Expectation<Actual>
): Repeat<Actual> {
return new Repeat(actual, expectation);
}
constructor(
private readonly actual: Answerable<Actual>,
private readonly expectation: Expectation<Actual>
) {}
doing(...activities: Activity[]) {
return new RepeatDoing(
activities,
this.actual,
this.expectation,
Wait.defaultPollingInterval,
120
);
}
}
class RepeatDoing<Actual> extends Task {
private attempts = 0;
constructor(
private readonly activities: Activity[],
private readonly actual: Answerable<Actual>,
private readonly expectation: Expectation<Actual>,
private readonly pollingInterval: Duration,
private readonly maxAttempts: number
) {
super(the`#actor repeats activities until ${actual} does ${expectation}`);
}
every(pollingInterval: Duration) {
return new RepeatDoing(
this.activities,
this.actual,
this.expectation,
pollingInterval,
this.maxAttempts
);
}
async performAs(
actor: UsesAbilities & AnswersQuestions & PerformsActivities
): Promise<void> {
const outcome = await actor.answer(this.expectation.isMetFor(this.actual));
if (outcome instanceof ExpectationMet) {
return Promise.resolve();
}
if (this.attempts >= this.maxAttempts) {
throw RaiseErrors.as(actor).create(AssertionError, {
message: 'too many attempts to perform activities',
expectation: outcome?.expectation,
diff: outcome && {
expected: outcome?.expected,
actual: outcome?.actual
},
location: this.instantiationLocation()
});
}
this.attempts++;
await actor.attemptsTo(Wait.for(this.pollingInterval), ...this.activities);
return this.performAs(actor);
}
}Use like this: Repeat.until(totalRecords().of(runningTasksTable()), equals(0)).doing(
Click.on(refreshButton().of(runningTasksTable())),
Wait.until(refreshButton().of(runningTasksTable()), isClickable())
).every(Duration.ofSeconds(3)), |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi everyone I'm trying to do the following.
I forced a user to change their password executing a database query, then when I interact with the UI I saw that sometimes the test failed because the expected screen doesn't appear, so I decided first to call a service in order to know if the user has the expected condition to change their pass, my idea isrun the service three times and wait, but if in the first call has the condition I expect I need break the loop:
This is my task:
in the WaitUntilUserIsForceToChangeThePassword
I would like to create a taks something like:
If in the result the property changePsw is true I would like to break the loop if is not I would like to wait a few seconds and call again the service, but in the first function I have an arrow function and the second I don't but the second has a parameter actor,
Could someone give some advices about how to accomplish this?
Thanks.
Beta Was this translation helpful? Give feedback.
All reactions