Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Apr 18 00:39
    jan-molak edited #805
  • Apr 18 00:38

    jan-molak on webdriverio

    fix(webdriverio): implemented W… refactor(core): removed unused … (compare)

  • Apr 16 22:36

    jan-molak on webdriverio

    chore(webdriverio): run webdriv… (compare)

  • Apr 16 22:11

    jan-molak on webdriverio

    feat(webdriverio): initial draf… Merge branch 'master' into feat… fix(webdriverio): webdriverIONo… (compare)

  • Apr 16 05:47
    renovate[bot] commented #810
  • Apr 16 05:47
    renovate[bot] opened #810
  • Apr 16 05:47

    renovate[bot] on chromedriver-90.x

    chore(deps): update dependency … (compare)

  • Apr 15 18:58
    renovate[bot] edited #809
  • Apr 15 18:58
    renovate[bot] edited #809
  • Apr 15 18:58
    renovate[bot] synchronize #809
  • Apr 15 18:58

    renovate[bot] on node-14.x

    chore(deps): update dependency … (compare)

  • Apr 15 15:11
    renovate[bot] opened #809
  • Apr 15 15:11

    renovate[bot] on node-14.x

    chore(deps): update dependency … (compare)

  • Apr 15 09:59
    viper3400 commented #802
  • Apr 15 09:27
    jan-molak labeled #807
  • Apr 15 09:27
    jan-molak labeled #807
  • Apr 15 01:37
    jan-molak edited #805
  • Apr 15 01:37
    jan-molak edited #805
  • Apr 15 01:37
    jan-molak edited #805
  • Apr 15 01:33

    jan-molak on gh-pages

    Updates (compare)

Josh McVey
@y3rsh_gitlab
Awesome ty, got me going in the right direction. I was able to get what I wanted in the hooks Before and take note of it.
I typed this below so it may be missing something but for posterity:
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'));
Jan Molak
@jan-molak
Nice one!
By the way, there's a built in interaction to resize browser window if you need it https://serenity-js.org/modules/protractor/class/src/screenplay/interactions/ResizeBrowserWindow.ts~ResizeBrowserWindow.html
Jan Molak
@jan-molak

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!

Also, @cnishina (Angular/Protractor team) will be giving an update on some cool new features coming up for Protractor on his Twitch channel on the 18th of December - twitch.tv/cnishina
eyesopen
@eyesopen

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...

9 replies
Jan Molak
@jan-molak
Hey folks! I've updated the Cucumber project template and would love to hear your thoughts - https://github.com/serenity-js/serenity-js-cucumber-protractor-template
2 replies
ssrinivasKG
@ssrinivasKG
new to serenity-js here
was wondering if the action class based approach exists in Serenity-JS or is Screenplay the only supported approach?
Jan Molak
@jan-molak
Hi @ssrinivasKG, welcome! Could you give an example of what you have in mind?
ssrinivasKG
@ssrinivasKG
Hey @jan-molak, thanks for the welcome! :) im looking at the serenity-bdd ScenarioSteps equivalent i suppose in Serenity-Js
8 replies
Jan Molak
@jan-molak
Merry Christmas everyone!🎄
1 reply
Anthony Browness
@demos74dx
test?
@jan-molak hi
Jan Molak
@jan-molak
Welcome, @demos74dx!
Kyrie Irving
@mnajibb_twitter
Hi @jan-molak , im new to serenityJs, currently want to do some research on how to integrate SerenityJS with appium (emulator, real device and device farm) and integrate also with CI/CD, do you have any suggestion where can i start my journey first? thank you very much!!!
3 replies
ssrinivasKG
@ssrinivasKG
anyone here attempted to do a Serenity-JS Allure reporting setup?
3 replies
Nywlem
@Nywlem
Need help to capture css value inherited by parent element of the target element.
1 reply
ssrinivasKG
@ssrinivasKG
@jan-molak Im trying to obtain the response body from an API request using the TakeNote.of functionality to story the LasResponse.body() however it seems like when i retrieve what i have stored using Note.of () im unable to access the request body itself even though when i log the Note.of im seeing the JSON response. Is there an easy way to get at the response body and store it as a a AXIOS Response object or even plain JSON without going through the LastResposne.body()?
15 replies
ssrinivasKG
@ssrinivasKG
Another question for you @jan-molak: is the Note.of() method available across different steps? For Ex: Given -> TakeNote.Of(...) Then -> Note.of(...) this currently is giving me an error saying that the answer to the note was never recorded
2 replies
Jan Molak
@jan-molak
Hey guys, Serenity/JS finally has its own Twitter account for any project-related updates and release notifications - https://twitter.com/SerenityJS
Jan Molak
@jan-molak

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!

1 reply
Jan Molak
@jan-molak
Hey folks, we have a new template project demonstrating using Serenity/JS with Cucumber in the context of REST API testing - https://github.com/serenity-js/serenity-js-cucumber-template
Enjoy :-)
mjgalapon
@mjgalapon
how do you extract the actual value from the Note.of("topic")?
10 replies
eyesopen
@eyesopen
Hi, i see that "See" was deprecated, but there is no mention what is the next best thing. Is there a place where such changes are documented? changelog does not seem to cover it nor i can find it directly in the backlog
5 replies
eyesopen
@eyesopen
in a cucumber project if i would like to use 2 different kind of actors, how could i call them to stage? like for API tests i would like to use APIAtors and for UI tests - UIActors. Following basic tutorials i engage UIActors in Before step, but now i need to add APIActors somewhere..
7 replies
viper3400
@viper3400

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

6 replies
Jan Molak
@jan-molak
I think 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())
Jan Molak
@jan-molak
Hey folks, new project template for your API testing pleasure :blush: - https://github.com/serenity-js/serenity-js-mocha-template
5 replies
Thelonius Tester
@TheloniusT_twitter
Hi @jan-molak ! Thanks a lot for this project, it really shines!
I've been writing some test cases with Serenity and Protractor and it is quite normal that I need to wait for elements to be visible before interacting with them.
My plan was to create an interaction which does "safe click" (wait for element to be clickable and then clicks it) but then I read about SRP at the end of https://serenity-js.org/handbook/design/interactions.html. Does it make sense to create a task for that? My idea was that tasks are more suitable for problem domain.
15 replies
Nywlem
@Nywlem
Hello Jan, is it possible to generate the test report in xml format? Our requirement is to enable gating on our PR's when there are failures in the test reports.
2 replies
Thelonius Tester
@TheloniusT_twitter

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?

23 replies
Jan Molak
@jan-molak

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 ;-)

https://github.com/sponsors/serenity-js

Jan Molak
@jan-molak
Wow, thanks for becoming our GitHub Sponsor, @viper3400! Much appreciated!
1 reply
eyesopen
@eyesopen
hi, is it possible that versions of packages will have different version or if one will increment the rest will get a rise too?
image.png
5 replies
sheerintaj
@sheerintaj
Hi Jan.. I have issues with report generation in serenity-js-cucumber-protractor-template project which you have shared in git. Index file has no updated test execution results.json file ia not generated.i have executed npx serenity-bdd run
sheerintaj
@sheerintaj
Please guide me Jan.
5 replies
Jan Molak
@jan-molak
Hey folks, @sheerintaj noticed that serenity-js-cucumber-protractor-template project might generate an empty report. This was caused by an issue with package-lock.json file that got corrupted when Dependabot updated Serenity/JS dependencies one at a time, rather than all of them together. I've now migrated all the template projects to use RenovateApp instead of Dependabot, which seems to offer better control over what dependencies should be updated together.
eyesopen
@eyesopen
hi, i am trying to work with data from LastResponse.body(), but i keep getting undefined. I did Log.the(LastResponse.body()) and that works, but if i try to access any property from the object it is not defined. What am i doing wrong?
Log.the(LastResponse.body().myProp) results undefined
35 replies
Kyrie Irving
@mnajibb_twitter

hi @jan-molak , i am currently develop mobile automation using webdriverio and integrate it with serenityJS screenplay pattern,

when running the tests, so far so good (test run as expected on appium, and pass on terminal using
wdio ./config/wdio.android.conf.js/ command), i also described it on serenityJS actors and create wrapper functions around it,

but im having trouble when generating the reports, it shows zero scenario test on serenity bdd reports, can you guide me on this one?

i have a feeling that due to wdio not generate anything after my automation test fisnished(or due to serenityJS core itself).. but im not sure why,

any suggestions, hints or help will be very much appreciated, thanks in advance!

12 replies
eyesopen
@eyesopen

Hello again :) i am trying to verify that object property has value. There is probably existing expectation allowing to verify that, but i failed to find it and went with my own expectation. My issue is that it prints too much to the report:

Expectation.thatActualShould('exist').soThat((actualValue) => actualValue && actualValue.length < 0)

✓ user ensures that property id does exist undefined (0ms)

is there a way to rid the output of the expected value?

1 reply
siva90144
@siva90144
@jan-molak does serenity JS supports rest API automation? if yes can you please give sample project or start up guide? is there any difference/advantage when compared to serenity java ?
11 replies
viper3400
@viper3400

Hi @jan-molak

Imagine the following pseudo list:

<div class="list">
    <div class="item>
        <div class="header">A<div>
        <div class="info">X</div>
    </div>
    <div class="item>
        <div class="header">A<div>
        <div class="info">Y</div>
    </div>
    <div class="item>
        <div class="header">B<div>

        <div class="info">X</div>
    </div>
    <div class="item>
        <div class="header">B<div>
        <div class="info">Y</div>
    </div>
</div>

I would like to access an "item" but it has to match both the text values of "header" and "info".

I'd a similar question concerning this "child to parent access" here: https://gitter.im/serenity-js/Lobby?at=6013ea301ed88c58d808ad05
But somehow I was not able to manage it that way.

What I tried so far (pseudo code):

Items = () => Target.all('items').located(by.css('.items'));
ItemHeader = () => Target.the('header').located(by.css('.header'));
ItemInfo = () => Target.the('info').located(by.css('.info'));

ListItem = (header: string, info: string) =>
        Pick.from<ElementFinder, ElementArrayFinder>(Items())
            .where(Text.of(ItemHeader(), includes(header))
            .where(Text.of(ItemInfo(), includes(info))           
            .first()
            .describedAs(
                `list entry that inlcudes '${header}' as main info and '${info}' as extra bottom info`
        );

I then tried:

ItemHeader = (header: string) =>
        Target.the(`main info text`).located(by.cssContainingText('.header', header));

ItemInfo = (info: string) =>
        Target.the(`main info text`).located(by.cssContainingText('.info', info));


ListItem = (header: string, info: string) =>
        Pick.from<ElementFinder, ElementArrayFinder>(Items())
            .where(ItemHeader(header), isVisible())
            .where(ItemHeader(info), isVisible())

            .first()
             .describedAs(
                `list entry that inlcudes '${header}' as main info and '${info}' as extra bottom info`
        );

This was also not successful. Only thing, that worked out was:

ListItem = (header: string, info: string) =>
        Pick.from<ElementFinder, ElementArrayFinder>(Items())
            .where(ItemHeader(header), isVisible())
            //.where(ItemHeader(info), isVisible())

            .first()
             .describedAs(
                `list entry that inlcudes '${header}' as main info and '${info}' as extra bottom info`
        );

So, how could I "join" both of the values needed to locate my item?
I'm stuck in here. What would be the Serenity/JS solution for this problem?

Thanks in advance.

13 replies
Jan Molak
@jan-molak
Hey folks! I've just raised a PR for protractor-cucumber-framework to replace its internals with Serenity/JS - protractor-cucumber-framework/protractor-cucumber-framework#198 Please feel free to upvote it if you think it's a good idea :-)
Also, Serenity/JS 2.24.0 introduces a bunch of fixes and new features around Cucumber and Protractor integration - https://serenity-js.org/changelog#2-24-0-2021-02-26-
eyesopen
@eyesopen
Hi, my project includes UI and API tests. Serenity is setup to capture screenshots on failures. But if it is API tests that fail there is nothing to capture and the photographer timesout. Is there a way to disable photographer for API tests?
eyesopen
@eyesopen
is it possible to use actor without overriding actorInTheSpotlight() result? Some of the steps i want to perform(validation) needs to be done by system user rather than the end user. But end user is known only in Given step
6 replies
viper3400
@viper3400

Hi @jan-molak , I've got another question: Have you (or someone else in here) ever tried to implement multiple language support to run the same spec with different user languages?
My way:

  • I assign the desired language for the test run to a browser param in proctractor conf.
  • Then I have a language class for each language (just containing the translation strings).
  • Each class implements an interface with the defined string properties.
  • I kind of inject this interface into constructor of each Target / Task using the param to determine the language class to use
    • (Therefore each target / task will be classes in my case as well)

This works fine, but seems to have a lot of overhead. On the other side I need a simple way to enhance the translation list (without having the overhead in there).
What would be the Serenity/JS way to achieve this?

52 replies
tfarrar
@tfarrar
Hi @jan-molak I am trying to validate circuitName
  {
      "status": "SUCCESS",
      "circuitData": {
          "requestTimeStamp": "2021-03-03",
          "responseTimeStamp": "2021-03-03",
          "circuitLst": [
              {
                  "circuit": [
                      {
                          "circuitId": "11111",
                          "circuitName": "AAAAAA"


                      }
                  ]
              }
          ]
      }
  } 

    Ensure.that(
        LastResponse.body<any>().map(actor => body  => body.circuitData.circuitLst[0].circuit.circuitName),
        contain('AAAAAA')
    )


  TypeError: Cannot read property 'circuitName' of undefined
6 replies