webdriverio / expect-webdriverio

WebdriverIO Assertion Library
https://webdriver.io
MIT License
75 stars 52 forks source link

Extending expect methods with custom code #1365

Closed gpaciga closed 11 months ago

gpaciga commented 11 months ago

In the WDIO projects I work on, I find a lot of helper methods being created around WDIO's built-in expects so that we can do extra logging. One simple example, instead of:

expect(element).toBeDisplayed()

we have a custom method that first waits for the element to be displayed, then check whether that is true or false, and then call our logger with the result. Very roughly,

async expectDisplayed(name, element) {
  const description = `${name} is displayed`;
  try {
    await element.waitForDisplayed();
    await reporter.pass(description);
  } catch (e) {
    await reporter.fail(description);
  }
}

Crucially for us, this allows us to log (in multiple places) what is being checked even when everything passes, using human-readable descriptions, rather than the default of staying silent unless there is an error. The reporter.fail() method here also logs, takes a screenshot, and throws a new error so the framework knows to mark the test a failure. Sometimes the log message will be different in case of a failure (e.g. to include element.selector).

We've essentially had to re-implement most of the expect API, but inevitably people will have to do something new and fall back to WDIO's native way of doing things, which leads to inconsistent logging and therefore harder to understand results. It also makes onboarding a pain for anybody who is used to WDIO from other projects.

I would love to instead use the normal expect(element).isDisplayed() and automatically call our reporter.pass() or reporter.fail() logic depending on the result, for all calls to expect. To get the right semantics in our logging, it would probably require passing custom keys in the options object passed to the assertions, similar to the existing .isDisplayed({message}) (message only ever describes a failure, rather than a neutral description of what the expectation was). Maybe a hook that accepts the result, something to identify the assertion, the element, and the options?

We have experimented with jasmine's expectationResultHandler, but this doesn't get called for WDIO's assertions.

christian-bromann commented 11 months ago

Thanks for reporting @gpaciga

I will look into this as part of my effort getting more reporting into the assertion lib (see #33). My current idea is to provide the ability to set a beforeAssertion and afterAssertion hook in your wdio.conf.js or as part of a service plugin. Do you think this would work for you?

gpaciga commented 11 months ago

Yes I think it could. I'd define the login we want to use somewhere globally and just install them in the config or plugin. As long as there's enough information passed to the hooks, including the ability to pass custom context information like the human-readable descriptions in my example, I can see it working.