Docs: https://serenity-js.org | Issues: https://github.com/serenity-js/serenity-js/issues | Backlog: https://github.com/orgs/serenity-js/projects
renovate[bot] on configure
Add renovate.json (compare)
dependabot[bot] on npm_and_yarn
chore(deps): bump chai from 4.3… (compare)
dependabot[bot] on npm_and_yarn
chore(deps-dev): bump lerna fro… (compare)
jan-molak on gh-pages
Updates (compare)
jan-molak on master
Update the-trouble-with-test-sc… Merge pull request #743 from ma… (compare)
CallAnApi
ability.
const ScenarioName = (scenario: HookScenarioResult) =>
Question.about('The name of the scenario', actor => scenario.pickle.name);
Before( scenario => actorCalled('User').attemptsTo(
MaximizeBrowser.start(),
TakeNote.of(ScenarioName(scenario)).as('scenarioName'),
));
// code in an async interaction gets the name to use
const scenarioName: string = await actorCalled('User').answer(Note.of('scenarioName'));
Hey folks! I've added a neat little Question
in version 2.19.5, it's called q
and works just like string templates, but with other Serenity/JS questions:
import { q, actorCalled } from '@serenity-js/core';
import { Send, DeleteRequest } from '@serenity-js/rest';
actorCalled('Alice').attemptsTo(
Send.a(DeleteRequest.to(
q `/articles/${ Text.of(Article.id()) }`
))
)
Thoughts and feedback welcome!
Hi, is there a #result or something that can be used in the question string to display value of the question? i can only see #actor... i am trying to write a question that can be chained like tasks
class DateText extends Question {
static of(target) {
return new DateText(target);
}
as(dateFormat) {
this.dateFormat = dateFormat;
return this;
}
constructor(target) {
super();
this.target = target;
}
async performAs(actor) {
/*more fancy stuff here*/
const result = '2020/12/15';
return result;
}
}
but without toString method this throws and exception in formatter. If i return const string then it is being used in the calling Ensure as value...
Serenity/JS 2.20 has arrived with support for Cucumber 7 (including the new Rule/Example syntax) and the latest Serenity BDD reporting CLI.
There's also a brand new reporting guide on the website, and updates to the integration guide around integrating Serenity/JS with Cucumber, Jasmine, Mocha and Protractor
Take it all for a spin and let me know what you think!
Hi, how to get the parent of a Target with Serenity/JS?
Imagine two dialogs on a page, and I want to close the one with title "Awesome Title 2" it by clicking the X.
<div>
<div class="dialog">
<div class="dialog-title">Awesome Title 1</div>
<div class="dialog-content">Some information in here.</div>
<div class="close">X</div>
</div>
<div class="dialog">
<div class="dialog-title">Awesome Title 2</div>
<div class="dialog-content">Some other information in here.</div>
<div class="close">X</div>
</div>
</div>
I can target both dialogs:
const Dialogs = () => Target.all('dialogs').located(by.css('dialog'));
But I can just distinguish both dialogs by their titles.
const DialogTitle = (title: string) => Target.the(`dialog title ${title}`).located(by.cssContainingText('.dialog-title', title));
I won't use Pick
with get(index)
because the positions may change.
'Target of' won't work either because I'm not searching the child, but the parent.
I could try to use a located(by.xpath(''))
but this will be a mess in my specific case.
In Protractor there is the possibility the getDriver()
method to get the parent of an element: Protracor API
This seems not to be implemented in Serenity/JS.
I tried some things, but nothing worked out.
How to solve this? Am I missing something?
Thanks, Jan
Pick
would be an appropriate choice in your case; you could say:const DialogTitle = () => Target.the(`dialog title`).located(by.css('.dialog-title'))
const CloseButton = () => Target.the(`close button`).located(by.css('.close'))
CloseButton.of(Pick.from(Dialogs()).where(Text.of(DialogTitle()), includes('Awesome Title 1')).first())
Hi @jan-molak !
I'm having some problems with a post
method which needs an authentication token.
One previous post was suggesting to create a question in order to access the token, so I prepared my own version:
const Authorization = {
from: (
responseBody: Answerable<any> // you might want to introduce an interface to describe the response rather than `any`
) =>
Question.about(
`session token`,
actor =>
actor
.answer(responseBody)
.then(body => 'Bearer '.concat(body.access_token)) // or wherever the token is on the response body
),
}
I have a task that obtains the token:
export const RequestAuthentication = (): Task =>
Task.where(
`#actor requests auth token`,
Send.a(PostRequest.to('yyyy').with(formData)),
Log.the(LastResponse.status()),
Ensure.that(LastResponse.status(), equals(200)),
TakeNote.of(Authorization.from(LastResponse.body()))
)
And, finally, a task that performs a GET using the authorization previously obtained:
export const Search = (): Task => {
return Task.where(
`#actor searches for a case`,
Log.the(Note.of(Authorization.from(LastResponse.body()))),
Send.a(
GetRequest.to('https://xxxx').using({
headers: {
Authorization: Note.of(Authorization.from(LastResponse.body())),
},
})
),
Log.the(LastResponse.body()),
Ensure.that(LastResponse.status(), equals(200))
)
}
Since I have logged the token in a note, I can see that it is a valid one but it is not working (401 error). Maybe I need my question to return a whole AxiosRequestConfig and inject it to the using method?
Hey folks!
Quite a few people have asked me to create a dedicated Serenity/JS JUnit reporter to make it easier to integrate Serenity/JS with popular CI/CD toolchains like Jenkins CI, GitLab CI, Azure DevOps and others. It will require changes to how Serenity/JS artifacts work internally and making the mechanism more flexible to support JUnit and other custom report and artifact types in the future.
If you think that it's a worthwhile effort, and you too would like to see this feature added, please consider buying me a coffee to keep me awake while I get this done ;-)