Serenity-js: Dynamic element locators

Created on 22 Aug 2020  路  4Comments  路  Source: serenity-js/serenity-js

Greetings, great documentation and project. I am new and I am missing something.
I follow https://github.com/serenity-js/serenity-js/issues/564
BUT I want to use my Note as a string and I cannot figure out how. To extend your example with the Vouchers.code, say I wanted to use that code in a By.linkText(

actor.attemptsTo(
     // (1)
     TakeNote.of(Text.of(Vouchers.code)),    
     // ... add the product to a basket, go to checkout, etc.

     // (2)
     Ensure.that(Target.the('voucher code detail link').located(By.linkText(Note.of(Text.of(Vouchers.code)))))), .........
 );

Is this possible?

enhancement

All 4 comments

Hello, I am still struggling with this issue. I need data as a string carried from interaction to interaction. No matter what I have tried I cannot seem to get at the value of the promise to utilize as a string. The Log Interaction prints the value... but I can't seem to write an interaction similar to Log to utilize the value. Thank you 馃槉

Hi @y3rsh and thanks for your kind words!

It's a bit tricky because Text is an asynchronous construct, a Question that an Actor needs to answer(), and Protractor's by.linkText locator requires a static string. I think Serenity/JS might require a couple of tweaks to handle your scenario out of the box.

There's hope, however!

Until there's a better way, I'd approach this problem with a custom question along the following lines:

import { Question } from '@serenity-js/core';
import { BrowseTheWeb } from '@serenity-js/protractor';
import { by } from 'protractor';

export const TargetByLinkText = (description: string, text: Question<string>) =>
  Question.about(`the ${ description }`, actor =>
    actor.answer(text).then(value =>
      BrowseTheWeb.as(actor).locate(by.linkText(value)),
    ),
  );

Which you'd then use with Note:

actor.attemptsTo(
     // (1)
     TakeNote.of(Text.of(Vouchers.code)),    
     // ... add the product to a basket, go to checkout, etc.

     // (2)
     Ensure.that(
        Text.of(TargetByLinkText('voucher code detail link', Note.of(Text.of(Vouchers.code)))),
        equals('expected')
      ),
 );

Does this help?

Best,
Jan

This helps a ton! The big key I was missing was calling actor.answer(.
I actually created an interaction that calls a task with the string as a parameter.
Another day I will post my example here for others to see.

  • [x] @y3rsh add an example!

Thank you.

Here is my example. I needed the note string in a few interactions. So I made a Task that intakes a string parameter.

export const resolveNoteAndUseInInteractionOrTask(note: Answerable<string>) =>
    Interaction.where(`#actor resolves a string note and uses it.`, actor => {
        return actor.answer(note).then(result => {
            return taskOrInteractionUtilizingTheNote(result).performAs(actorInTheSpotlight());
        });
    });
Was this page helpful?
0 / 5 - 0 ratings