0

How can i use the data driven or dynamic username and password when i enter the actor name in the cucumber it should use the respective password maybe from a json file or something depending on the actor.

So when i enter this in the feature file

//example.feature

      Feature: Add item and place the order for that item
      In order to wear something new
      As an online shopping customer
      I want to be able to add an item to my shopping bag and then place the order

      Scenario: Add an item to shopping bag to place the order using Paypal
        Given that "Bruno" is logged in to his "admin" account
         When he searches and adds an item from "men" section to his shopping bag
         Then he can place the order

// example.steps.ts

import { Actor } from "serenity-js/lib/screenplay";
import { BrowseTheWeb } from "serenity-js/lib/screenplay-protractor";
import { protractor } from "protractor";
import { Start, AddItemsToShoppingBag } from "../website-model/src/index";
import { Authenticate } from '../website-model/src/ability/authenticate';

protractor.browser.ignoreSynchronization = true;

export = function selectItemSteps() {
  let actor = Actor.named('Bruno').whoCan(BrowseTheWeb.using(protractor.browser));

  this.Given(/^that "([^"]*)" is logged in to his "([^"]*)" account$/, function (name: string, pageUrl: string) {
    return actor.attemptsTo(
      Start.LaunchUrl(pageUrl, name),
    );
  });

  this.When(/^he searches and adds an item from "([^"]*)" section to his shopping bag$/, function (gender:string) {
    return actor.attemptsTo(
      AddItemsToShoppingBag.called(gender)
  );
  });

  this.Then(/^he can place the order$/, function () {
    return actor.attemptsTo(
      // PlaceOrder.hjgkhaksdjh()
    );
    // expect(james.toSee(thankYouPageElementsMap(lbl_thank_you).Displayed)).eventually.equal('Thank You');
  });
}

// login-user.ts

    import { Task, step, PerformsTasks } from "serenity-js/lib/screenplay";
import { Click, Enter } from "serenity-js/lib/screenplay-protractor";
import { homePageElementsMap } from "../interactions/html-elements/pages-elements-maps/home-page-elements-maps";
import { loginPageElementsMap } from "../interactions/html-elements/pages-elements-maps/login-page-elements-map";

export class LoginUser implements Task {

  static called(name: string): LoginUser {
    return new LoginUser(name);
}
  @step('{0} Login Page - Login Bruno')
  performAs(actor: PerformsTasks): PromiseLike<void> {
    return actor.attemptsTo(
      Click.on(homePageElementsMap.lnk_login),
      Enter.theValue('test@test.com').into(loginPageElementsMap.txt_login_email),
      Enter.theValue('password111').into(loginPageElementsMap.txt_login_pwd),
      Click.on(loginPageElementsMap.btn_login)
    );
  }

  constructor(private name: string) {
  }
}
Marit
  • 2,399
  • 18
  • 27
J Don
  • 65
  • 1
  • 2
  • 6

2 Answers2

0

Implement the step

Given that "Bruno" is logged in to his "admin" account

to randomly select a user. You could randomly select them from a file or from whatever the typescript equivalent of an Enum or Collection is.

Note: currently you are assigning "Bruno" outside of your step definition. I'd consider this bad practice as the implementation of your test is not tied to your steps (i.e. stuff happens outside them) which might lead to incorrect feature files / unexpected behavior. For example: If you change the step to

Given that "Bob" is logged in to his "customer" account

this will not work automatically, as you've still hardcoded actor to be Bruno.

You will still have to share state between the steps (i.e. all steps in a scenario need to know which actor is logged into which account)

Marit
  • 2,399
  • 18
  • 27
0

I take the following approach to this using some odd syntax.

Users are quite unusual compared to most things in an application because they know something the application doesn't (their password). So to login you can't use fixtures or factories to get an existing user from the database.

What I do in my test code is create a class specifically for Users. I call this TUser. In my test world I identify a user only by their first name and then I generate everything else including their password. So if a have a user Bruno my code will

  • call TUser.new(first_name: Bruno) to give me my user and store that in a variable, lets say @bruno for this example
  • use that user to create a database record e.g. create_user(user: @bruno)
  • visit the login in page and fill in the details by asking @bruno for them, e.g.`fill_in(:password, with: @bruno.password)

and the cuke that does this would read something like

Given there is a user Bruno When Bruno signs in Then Bruno should ...

** All above is ruby **

You can see a more detailed version of this in one of my sample projects. Having Txxx classes to create Test versions of particular entities is quite powerful once you get past their initial strangeness.

diabolist
  • 3,990
  • 1
  • 11
  • 15