0

First-off, thanks for the chai-smoothie!

I've been trying to polish some of the test code and use chai-smoothie more, but I have ran into some trouble:

This is what it looked like before:

return expect(Promise.all([
    userMenuPage.userMenuItemIcon.isDisplayed(),
    userMenuPage.userMenuItemText().isDisplayed()
])).to.eventually.be.eql([true, true])

and this is how I expected it to work in chai smoothie

expect(userMenuPage.userMenuItemIcon).to.eventually.be.displayed
expect(userMenuPage.userMenuItemText()).to.eventually.be.displayed

when running the new code, I receive the following error:

   Step Definition: steps/userMenuSteps.js:23
   Message:
     TypeError: assertion._obj.locator is not a function
         at <repo>/tests/node_modules/chai-smoothie/lib/src/chai-smoothie.ts:42:65
         at <repo>/tests/node_modules/protractor/built/element.js:798:32
         at ManagedPromise.invokeCallback_ (<repo>/tests/node_modules/selenium-webdriver/lib/promise.js:1379:14)
         at TaskQueue.execute_ (<repo>/tests/node_modules/selenium-webdriver/lib/promise.js:2913:14)
         at TaskQueue.executeNext_ (<repo>/tests/node_modules/selenium-webdriver/lib/promise.js:2896:21)
         at asyncRun (<repo>/tests/node_modules/selenium-webdriver/lib/promise.js:2775:27)
         at <repo>/tests/node_modules/selenium-webdriver/lib/promise.js:639:7
         at process._tickCallback (internal/process/next_tick.js:103:7)

Page model definition looks like this:

userMenuItemText: () => $('#desktop-menu #desktop-menu-classic span').getText(),
userMenuItemIcon: $('#desktop-menu #desktop-menu-classic .fa-fjunk'),

The issue is with the second row "userMenuPage.userMenuItemText().isDisplayed()". If I just use "userMenuPage.userMenuItemIcon.isDisplayed()", then I get no problem, and if I just use "userMenuPage.userMenuItemText().isDisplayed()", then I get the failure.

Do you have any recommendationts on how to overcome this and still use chai smoothie?

1 Answers1

0

The problem is caused by the assertion to.eventually.be.displayed applied to the text of the element, rather than the element itself.

Update: as of version 0.2.1, chai-smoothie can work with either.

Hope this helps!

Jan


Nevertheless, it might be cleaner to assert on the element to verify its visibility, and on its text to verify the contents:

So instead of:

const userMenuPage = {
    userMenuItemText: () => $('#desktop-menu #desktop-menu-classic span').getText(),
    userMenuItemIcon: $('#desktop-menu #desktop-menu-classic .fa-fjunk')
}

maybe try:

const userMenuPage = {
    userMenuItem: $('#desktop-menu #desktop-menu-classic span'),
    userMenuItemIcon: $('#desktop-menu #desktop-menu-classic .fa-fjunk')
}

and then:

expect(userMenuPage.userMenuItem).to.eventually.be.displayed
expect(userMenuPage.userMenuItem.getText()).to.eventually.equal('expected text')

With Serenity/JS you could also define the page object as follows:

class UserMenuPage {
    static Item      = Target.the('Menu item').located(by.css('#desktop-menu #desktop-menu-classic span');
    static Item_Text = Text.of(UserMenuPage.Item);

    static Item_Icon = Target.the('Menu icon').located(by.css('#desktop-menu #desktop-menu-classic .fa-fjunk');
}

which allows you to define "questions" such as UserMenuPage.Item_Text in the same place as targets and avoid having to call .getText() in the scenario.

Jan Molak
  • 4,426
  • 2
  • 36
  • 32