webdriverio / expect-webdriverio Goto Github PK
View Code? Open in Web Editor NEWWebdriverIO Assertion Library
Home Page: https://webdriver.io
License: MIT License
WebdriverIO Assertion Library
Home Page: https://webdriver.io
License: MIT License
Merge toBeRequestedWithResponse
with toBeRequestedWith
toBeRequestedWith({
request: { sort: 'asc' }
response: [{ title: 'a' }, { title: 'b' }] // toBeRequestedWithResponse
})
Tests with .not negation don't work correctly, the end result is the testrunner always receiving undefined
and then failing the test. This seems to happen with all methods. The result is the same in both sync and async modes.
Test case:
describe('webdriver.io page footer', () => {
it('should have the right class', () => {
browser.url('https://webdriver.io');
const footer = $('#footer');
footer.waitForExist();
// ok, passes
expect(footer).toHaveClass('nav-footer');
// doesn't pass
expect(footer).not.toHaveClass('asdf');
// from the documentation, doesn't pass
expect(footer).not.toHaveProperty('height', 42);
});
});
Output:
[chrome 85.0.4183.83 mac os x #0-0] 1 failing (10.9s)
[chrome 85.0.4183.83 mac os x #0-0]
[chrome 85.0.4183.83 mac os x #0-0] 1) webdriver.io page footer should have the right class
[chrome 85.0.4183.83 mac os x #0-0] Expect $(`#footer`) not to have class
Expected [not]: "asdf"
Received : undefined
Hi
It seems like the option ignoreCase
is not working for the toHaveValue()
assertion method.
Given this assertion:
expect(browser.$('#searchField')).toHaveValue('iPhone', {ignoreCase: true, asString: true});
I'm getting this error when running the test:
[chrome mac os x #0-0] Error: Expect $(`#searchField`) to have property value
[chrome mac os x #0-0]
[chrome mac os x #0-0] Expected: "iPhone"
[chrome mac os x #0-0] Received: "iphone"
Is that a bug or do the 'stringOptions' just don't work for toHaveValue
?
Best regards,
Annika
By the way:
Great project! I'm using 'chai-webdriverio' right now and just started to look into this - it looks very promising :)! I like the syntax and the fact that you can pass in WebdriverIO elements and not only selectors like in 'chai-webdriverio'.
Good day.
I have no idea where things are failing, but I'm unable to use expect assertions.
My packages:
"@types/chromedriver": "^81.0.0",
"@types/jest": "23.3.13",
"@types/node": "^10.17.21",
"chromedriver": "^81.0.0",
"expect-webdriverio": "^1.1.0",
"jest": "22.4.3",
"ts-jest": "^22.4.6",
"webdriverio": "5.22.4"
I'm using jest and typescript. In my tsconfig:
"compilerOptions": {
"module": "commonjs",
"types": [
"node",
"jest",
"webdriverio",
"expect-webdriverio"
],
}
And in my jestconfig:
testEnvironment: 'node',
setupTestFrameworkScriptFile: 'expect-webdriverio',
transform: {
"^.+\\.tsx?$": "ts-jest",
},
My test code contains:
const el = await browser.$('input');
await el.click();
expect(el).toBeFocused();
And this fails!
Error:
Unexpected return from a matcher function.
Matcher functions should return an object in the following format:
{message?: string | function, pass: boolean}
'{}' was returned
83 | await el.click();
> 84 | expect(el).toBeFocused();
at _validateResult (node_modules/expect/build/index.js:196:11)
at Object.throwingMatcher [as toBeFocused] (node_modules/expect/build/index.js:158:5)
at src/my/test/file.ts
What's happening here and how do I fix it?
Is there a way to do number comparison ?
ex.
expect(page.getCount()).to.be.gt(2000)
I would like to replace chai to use expect-webdriverio just need to map those as well
WebdriverIO version: 7.10.1
Mode: WDIO Testrunner
If WDIO Testrunner, running sync/async: async
Node.js version: v15.12.0
NPM version: v7.6.3
Browser name and version: Chrome 92
Platform name and version: e.g. MacOs Big Sur
Additional wdio packages used (if applicable): "@wdio/jasmine-framework": "^7.11.0"
exports.config = {
baseUrl: 'https://todomvc.com/',
capabilities: [{
browserName: 'chrome',
'goog:chromeOptions': {
args: ['--headless']
}
}],
headless: true,
framework: 'jasmine',
specs: ['*.test.js'],
services: ['chromedriver'],
jasmineOpts: {
defaultTimeoutInterval: 90000,
}
};
The matchers aren't working with jasmine framework. If I change to the mocha, then it'll work as expected.
describe('TodoMVC', () => {
it('verify title', async () => {
await browser.url('#');
await expect(browser).toHaveTitle('TodoMVC');
});
});
The test above should be passed.
Error in "TodoMVC verify title"
Error: Expected Browser({ sessionId: 'c76db59575408052600827adc6476a2f', capabilities: Object({ acceptInsecureCerts: false, browserName: 'chrome', browserVersion: '93.0.4577.63', chrome: Object({ chromedriverVersion: '92.0.4515.107 (87a818b10553a07434ea9e2b6dccf3cbe7895134-refs/branch-heads/4515@{#1634})', userDataDir: '/var/folders/fv/1gs2zg7n6hq1m3zy_pxkh54m0000gp/T/.com.google.Chrome.AycbGv' }), goog:chromeOptions: Object({ debuggerAddress: 'localhost:61336' }), networkConnectionEnabled: false, pageLoadStrategy: 'normal', platformName: 'mac os x', proxy: Object({ }), setWindowRect: true, strictFileInteractability: false, timeouts: Object({ implicit: 0, pageLoad: 300000, script: 30000 }), unhandledPromptBehavior: 'dismiss and notify', webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:virtualAuthenticators: true }), addCommand: Function, overwriteCommand: Function, addLocatorStrategy: Function, config: Object({ specs: [ './webdriverio/e2e/*.test.js' ], suites: Object({ ... to have title 'React'.
at
0-0] 2021-09-06T19:13:11.845Z INFO webdriver: Initiate new session using the WebDriver protocol
[0-0] 2021-09-06T19:13:11.908Z INFO webdriver: [POST] http://localhost:9515/session
[0-0] 2021-09-06T19:13:11.908Z INFO webdriver: DATA {
[0-0] capabilities: {
[0-0] alwaysMatch: { browserName: 'chrome', 'goog:chromeOptions': [Object] },
[0-0] firstMatch: [ {} ]
[0-0] },
[0-0] desiredCapabilities: { browserName: 'chrome', 'goog:chromeOptions': { args: [Array] } }
[0-0] }
2021-09-06T19:13:12.274Z WARN chromedriver: [1630955592.274][WARNING]: This version of ChromeDriver has not been tested with Chrome version 93.
[0-0] 2021-09-06T19:13:12.699Z INFO webdriver: COMMAND navigateTo("https://todomvc.com/")
[0-0] 2021-09-06T19:13:12.699Z INFO webdriver: [POST] http://localhost:9515/session/c76db59575408052600827adc6476a2f/url
[0-0] 2021-09-06T19:13:12.699Z INFO webdriver: DATA { url: 'https://todomvc.com/' }
[0-0] 2021-09-06T19:13:14.155Z INFO webdriver: COMMAND getTitle()
[0-0] 2021-09-06T19:13:14.155Z INFO webdriver: [GET] http://localhost:9515/session/c76db59575408052600827adc6476a2f/title
[0-0] Error in "TodoMVC verify title"
Error: Expected Browser({ sessionId: 'c76db59575408052600827adc6476a2f', capabilities: Object({ acceptInsecureCerts: false, browserName: 'chrome', browserVersion: '93.0.4577.63', chrome: Object({ chromedriverVersion: '92.0.4515.107 (87a818b10553a07434ea9e2b6dccf3cbe7895134-refs/branch-heads/4515@{#1634})', userDataDir: '/var/folders/fv/1gs2zg7n6hq1m3zy_pxkh54m0000gp/T/.com.google.Chrome.AycbGv' }), goog:chromeOptions: Object({ debuggerAddress: 'localhost:61336' }), networkConnectionEnabled: false, pageLoadStrategy: 'normal', platformName: 'mac os x', proxy: Object({ }), setWindowRect: true, strictFileInteractability: false, timeouts: Object({ implicit: 0, pageLoad: 300000, script: 30000 }), unhandledPromptBehavior: 'dismiss and notify', webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:virtualAuthenticators: true }), addCommand: Function, overwriteCommand: Function, addLocatorStrategy: Function, config: Object({ specs: [ './webdriverio/e2e/*.test.js' ], suites: Object({ ... to have title 'React'.
at <Jasmine>
at UserContext.<anonymous> (/Users/ylaichenkov/Desktop/practice/protractor-endgame/webdriverio/e2e/simple.test.js:14:27)
at processTicksAndRejections (node:internal/process/task_queues:94:5)
[0-0] 2021-09-06T19:13:14.158Z INFO webdriver: COMMAND deleteSession()
[0-0] 2021-09-06T19:13:14.159Z INFO webdriver: [DELETE] http://localhost:9515/session/c76db59575408052600827adc6476a2f
[0-0] 2021-09-06T19:13:14.160Z INFO webdriver: RESULT TodoMVC
[0-0] FAILED in chrome - /webdriverio/e2e/simple.test.js
2021-09-06T19:13:14.332Z INFO @wdio/cli:launcher: Run onComplete hook
Spec Files: 0 passed, 1 failed, 1 total (100% completed) in 00:00:03
2021-09-06T19:13:14.334Z INFO @wdio/local-runner: Shutting down spawned worker
2021-09-06T19:13:14.585Z INFO @wdio/local-runner: Waiting for 0 to shut down gracefully
2021-09-06T19:13:14.585Z INFO @wdio/local-runner: shutting down
I think this module is must-have for writing nice web tests with WebdriverIO.
I stumbled upon this module when I read the release notes for WebdriverIO 6, and otherwise wouldn't have known about it.
Is there a specific reason why this was made as a separate module, instead of being bundled directly in WebdriverIO? Are you planning on bundling it with WebdriverIO in the future?
I believe that bundling this module directly into WebdriverIO would be one of the improvements that would help making with making it easier to write non-flaky tests with WebdriverIO, out-of-the-box.
Slightly related, my isssue on WebdriverIO
Environment (please complete the following information):
Config of WebdriverIO
By Default
Describe the bug
Looks like there is a bug in typings in expects
toHaveText(text: string | string[], options?: ExpectWebdriverIO.StringOptions): R
Shouldn't it be like this
toHaveText(text: string | string[], options?: ExpectWebdriverIO.StringOptions): Promise<R>
To Reproduce
Steps to reproduce the behavior:
describe('sample spec', () => {
it('should be logo', async () => {
browser.url('https://webdriver.io/')
expect(await $('p.hero__subtitle')).toHaveText('bla bla') //expect is definetely wrong, but the test passes
});
});
Expected behavior
Test above should failed.
NOTE: I know that there is a workaround
await expect($('p.hero__subtitle')).toHaveText('bla bla') //it should fail and it fails
but I still think that there is a bug in typings
Let's bring up the unit test coverage to like 90% and higher.
Since we already have toHaveTextContaining
it would be nice to also have such a matcher for urls. Given that we have toHaveText
and toHaveTextContaining
we should follow this pattern for toHaveTitle
and toHaveUrl
as aliases to e.g. toHaveTitle("foobar", { containing: true })
.
not
matchers got broken since #133
The fix #170 breaks toBeRequestedTimes
and toBeCalled
matchers. At least tests are failing.
Marked failed tests as skipped 982fd5c for now. Let's fix them!
Matchers require global browser
, but imagine I have 2 or more browsers, how to get around it?
browser
var is obviously global... need to have a way to supply custom browser...
Description
When an expectation fails, error message does not provide accurate element selector info when using shadow$
command.
Expected Behaviour
When an expectation fails, it provides full element selector info when using shadow$
command.
$('form').$('input')
Actual Behaviour
When an expectation fails, error message has the following structure when using shadow$
command:
Expect $(
).$(
).$(
).$(
) to have property value
Additional Info
Testing framework: Mocha
Tech stack: LitElement
Dependencies
"@wdio/cli": "^5.18.6"
"@wdio/mocha-framework": "^5.18.6"
"expect": "^25.1.0"
"expect-webdriverio": "^0.2.0"
expect-webdriverio
version: 1.2.3
WebdriverIO version: 6.4.1
Test Framework: mocha (jest/jasmine/mocha/cucumber/etc)
async/sync: async (is @wdio/sync
used? - No)
expect matchers return type is not a Promise
Jasmine users should not be affected as far as expectAsync is used in async mode.
I've upgraded webdriverio
& all used @wdio/*
package dependencies to v6 on a projects which also uses chai
for expect(...)
matchers. Now, when I run tests, I see the following in STDOUT for each spec file that is executed:
[0-0] Warning! Unsupported expect lib is used.
| Only Jasmine >= 3.3.0 and Jest's expect are supported.
| expect-webdriverio is assigned to global.expectWdio
I was first confused to see this, as I don't have expect-webdriverio
defined as a dependency in package.json
. But then I noticed it is enabled by default now if you use @wdio/mocha-framework
(webdriverio/webdriverio#5335).
So, is there any way to suppress the warning?
Could you add support for multiple possible strings in toHaveText / toHaveTextContaining APIs? see example below:
expect(...).toHaveText(['string1', 'string2'])
Description:
When a tests fail, it doesn't exit automatically
Expected Behaviour:
When tests fail, it'll continue running and exit properly
Actual Behaviour:
When tests fail, it gets stuck to the point where it describes the discrepancy between the expected and actual results
Additional Info:
I'm using mocha as my framework
toBeRequestedWithResponse
should support { containing: true }
and/or a function comparator
toBeRequestedWithResponse({ foo: 'bar' }, { containing: true })
toBeRequestedWithResponse((data: string | Array<...> | Record<string, unknown>) => data === '{"filter":"year"}')
Add TSLint for additional checks.
Allow users to use this assertion library with multiremote. Using the isMultiremote
flag of the browser
object should help to determine the current mode and allows to then iterate over the multiremote instances to do separate assertions.
expect-webdriverio
version: 1.3.0
WebdriverIO version: 6.4.1
Test Framework: mocha (jest/jasmine/mocha/cucumber/etc)
async/sync: sync (is @wdio/sync
used? - Yes)
expect(section).not.toHaveClass('page2')
Property 'toHaveClass' does not exist on type 'Matchers<Element>'
Looks like a regression since #122
Let's make sure the matcher was called with supported parameters, fail fast otherwise.
There should be no need in console.error
usage.
I have a couple of matchers that I've already created for the Chai version of webdriver.io expects that I'd like to move over to the Jest-style matchers as I port to this framework. The problem is that some of them might not make sense to be part of this core library and over time a monolithic package probably isn't the best idea anyways.
Would it be possible to expose a some of the existing custom methods and / or a new method to enable some extensibility? Specifically, I'd be looking to at least get the core src/utils
methods (e.g. executeCommandBe
and its dependencies).
The first method I'd like to swap in looks like this:
// check the style (supports type validation of keys in Typescript)
expect(label).toHaveStyle({
"font-family": "Faktum",
"font-size": "26px",
color: "#000" // handles "black", "#000000", "rgb(0, 0, 0)", and "rgba(0, 0, 0, 1)"
});
Let's implement a new matcher that works this:
const searchMock = browser.mock('**/search?*', { method: 'POST' })
$('search').click()
// POST http://localhost:8080/tst/invoices/search?size=20&page=0&sort=createdDateTime,desc'
// body { foo: 'bar', released: true }
expect(searchMock).toBeRequestedWith({
method: 'POST',
url: (url) => url.includes('invoices') && url.includes('localhost'),
request: { released: true },
query: { size: 20 },
headers: (headers) => headers.Authorization.startsWith('Bearer '),
}, { containing: true })
// types.d.ts
toBeRequestedWith({
method: string
url: string | (url: string) => boolean
request: string | Record<string: unknown> | Array<Record<string: unknown>> | (payload: unknown) => boolean
query: string | Record<string: string>| (query: Record<string: string>) => boolean
headers: Record<string: string> | (headers: Record<string: string>) => boolean
}): R
We still allow for toBeVisible
and other v5 commands which should be deprecated.
Hi all!
I am checking out webdriverio 6 and I got an error using toHaveChildren
Expect $$(`div.card`) to have children
Expected: 9
Received: serializes to the same string
However when using toBeElementsArrayOfSize
instead it works fine, according to the docs it is Same as toHaveChildren.
expect(StoreHomePage.productCards).toBeElementsArrayOfSize({ eq: 9 });
works fine
expect(StoreHomePage.productCards).toHaveChildren({ eq: 9 });
fails
StoreHomePage.productCards
is $$('div.card')
Context:
"@wdio/cli": "^6.1.5"
node --version
v12.16.1
[//]: # NOTE: This repository only maintains packages that are listed in the Readme. Please make sure that your issue is directly caused by one of these packages and if not file an issue in the correct 3rd party package repository.
Environment (please complete the following information):
Config of WebdriverIO
I don't think any of this matters in this case.
Describe the bug
expect.toHaveChildren, according to the docs, is the same as expect.toBeElementsArrayOfSize; however, after hours of trying to figure out why toHaveChildren gave us 4, we realized that toBeElementsArrayOfSize was giving the value we expected.
Since the WebdriverIO Expect docs state that toHaveChildren and toBeElementsArrayOfSize are the same, we just happen to try it out and the alternative method worked.
It seems toHaveChildren may have a bug in it since it doesn't behave the same way and returns a value that doesn't make sense.
To Reproduce
we expected 33 but instead it showed 4 in the logs.
console.debug('size of $$(#settingsClassesList > li).length = ' + $$('#settingsClassesList > li').length); // printed 32
expect($$('#settingsClassesList > li')).toHaveChildren({ gte: 31 }); // threw AssertionError with Expected 31 Received 4
Expected behavior
Expected 31 not 4, but with the alternative command, it worked.
Log
[0-0] size of $$(#settingsClassesList > li).length = 32
[0-0] Error in "Class Creation & Deletion Should create class and delete the class"
Expect $$(`#settingsClassesList > li`) to have children
Expected: ">= 31"
Received: 4
expect(sessionCountListBeforeCleanUp).toBeElementsArrayOfSize({ gte: 3 })
The above line, when checking that the array is greater or equal than 3, fails if it gets a number greater than 3. In this example, our sessionCountListBeforeCleanUp
variable is of size 4.
The below output seems to contradict itself, since a value of 4 is indeed greater than or equal to 4.
Expect $$(`//div[@class="span6 class-timings-list"]/ul/li[@class="hasHoverStyles"]`) to be elements array of size
Expected: ">= 3"
Received: 4
[chrome 83.0.4103.61 linux #0-0] Error: Expect $$(`//div[@class="span6 class-timings-list"]/ul/li[@class="hasHoverStyles"]`) to be elements array of size
[chrome 83.0.4103.61 linux #0-0]
[chrome 83.0.4103.61 linux #0-0] Expected: ">= 3"
[chrome 83.0.4103.61 linux #0-0] Received: 4
[chrome 83.0.4103.61 linux #0-0] at Context.<anonymous>
While we would love to have a strict equals version of this, the gte behavior does not seem correct.
Platform: Mac OS
WebdriverIO: v7.0.7
In order to better understand what has been asserted it would be super helpful if the library could report every assertion so that the consumer (WebdriverIO) can use this to enrich its reporting capabilities.
Using wdio 5.18.4 and allure-reporter 5.16.6. In case of a failed assertion the allure reporter can not parse the failure message to XML which causes the process to hang indefinitely.
This is the failure message that can not be handled by allure-js-commons 1.3.2.
�[32m- Ditt spel på Bomben �[7m(är betal|kostade)�[27m�[39m
�[31m+ Ditt spel på Bomben �[7mkostade 16kr�[27m�[39m
�[31m+ �[7mDu hittar ditt spel under Mina spel.�[27m�[39m
�[31m+ �[7mDu vet väl att du kan stötta din favoritförening varje gång du spelar.�[27m�[39m
�[31m+ �[7mVälj föreningar här.�[27m�[39m
I guess the failure-message ends up formatted in the test object which then is used in all reporters.
While this works for console output, the hidden ESC character makes the xml parsing fail. The colorcoding will also look bad in any other reports.
I'm sorry I don't have any suggestions on how to solve this, but my personal view is that the colorcoding does not add much to the understanding of the failure. Having the expected and actual criterias would give enough information.
const mock = browser.mock('**')
// some calls happened ...
// let's say mock.calls.length is more than 1
expect(mock).not.toBeRequested()
it doesn't make sense to wait for mock.calls
length to decrease.
Actual Result
waiting mock.calls
length to decrease which makes no sense
Expected Result
should not wait
Add types for mock matchers
expect
is only required for expect-webdriverio
to work with Mocha / CucumberJS test frameworks out of the box in webdriverio
.expect
is not a required dependency for expect-webdriverio
used in the Jasmine framework.Ideally, expect-webdriverio
should install expect
depending on if Jasmine/Jest installation however it's not currently possible.
When using appium for testing ios safari
appiumVersion: '1.17.1',
browserName: 'Safari',
deviceName: 'iPhone XS Simulator',
deviceOrientation: 'portrait',
platformName: 'iOS',
platformVersion: '13.0',
The following check fails
expect($('#search')).toHaveValue('');
with error
Method has not yet been implemented"
and from appium log
Calling AppiumDriver.getProperty() with args: ["value","5011","9ee8f32f-9e8e-46c4-b488-e2c6dda4cf96"]
2020-12-29 21:34:01:303 - [debug] [XCUITest] Executing command 'getProperty'
However the same test passes when
expect($('#search')).toHaveAttribute('value', '');
It seems to be related to the issue brought up here
webdriverio/webdriverio#3606
This would be awesome, so that we don't need to apply multiple transformations and calculations, and having no good error feedback when the expect fails.
The response headers object is about to be added to request
with webdriverio/webdriverio#5821
Let's replace headers
filter with requestHeaders
and responseHeaders
.
Add unit tests to reach 99% coverage. Any help is appreciated!
Inside of toHaveAttribute the condition is:
async function condition(el: WebdriverIO.Element, attribute: string, value: string, options: ExpectWebdriverIO.StringOptions): Promise<any> {
const attr = await el.getAttribute(attribute)
if (typeof attr !== 'string') {
return { result: false, value: attr }
}
if (typeof value !== 'string') {
return { result: true, value: attr }
}
return compareText(attr, value, options)
}
Which means that a test like this would pass
test('success with non-string attribute value as expected', async () => {
el.getAttribute = jest.fn().mockImplementation((attribute: string) => {
return "Correct Value"
})
const result = await toHaveAttribute(el, "attribute_name", 123, { ignoreCase: true });
expect(result.pass).toBe(true)
})
Is this the expected behaviour because surely this implies that passing in any non-string value as the expected would result in a success which seems like confusing behaviour to me?
While updating the Cucumber boilerplate I recognise that the expect-webdriverio lib doesn't allow for customer error messages like
expect(nrOfElements).toHaveLength(
0,
`Element with selector "${selector}" should not exist on the page`
);
The definition of the expect dependency (node_modules/expect/build/types.d.ts
) is as follows:
/**
* Used to check that an object has a `.length` property
* and it is set to a certain numeric value.
*/
toHaveLength(expected: number): R;
In jasmine framework this throws two assertions :
it('Sorts the inventory in asc order of price and adds element to cart', async () => {
expect(1).toBe(2)
});
This can be validated by :
Adding below to config file:
jasmineOpts: {
// Jasmine default timeout
defaultTimeoutInterval: 60000,
//
// The Jasmine framework allows interception of each assertion in order to log the state of the application
// or website depending on the result. For example, it is pretty handy to take a screenshot every time
// an assertion fails.
expectationResultHandler: function (passed, assertion) {
console.log("Pass: ",passed,"Assertion: ", assertion)
// do something
}
},
This gives below outputs:
[0-0] Pass: false Assertion: {
[0-0] matcherName: 'toBe',
[0-0] passed: false,
[0-0] message: 'Expected 1 to be 2.',
[0-0] error: undefined,
[0-0] errorForStack: undefined,
[0-0] actual: 1,
[0-0] expected: 2
[0-0] }
[0-0] Pass: false Assertion: {
[0-0] matcherName: '',
[0-0] passed: false,
[0-0] expected: '',
[0-0] actual: '',
[0-0] error: {
[0-0] matcherName: 'toBe',
[0-0] message: 'Expected 1 to be 2.',
[0-0] stack: 'Error: Expected 1 to be 2.\n' +
[0-0] ' at <Jasmine>\n' +
[0-0] ' at Spec.addExpectationResult (D:\\prject\\node_modules\\@wdio\\jasmine-framework\\build\\index.js:296:32)\n' +
[0-0] ' at <Jasmine>\n' +
[0-0] ' at UserContext.<anonymous> (D:\\prject\\test\\specs\\cartFeature.js:12:25)\n' +
[0-0] ' at UserContext.executeAsync (D:\\prject\\node_modules\\@wdio\\utils\\build\\shim.js:136:25)',
[0-0] passed: false,
[0-0] expected: 2,
[0-0] actual: 1
[0-0] }
[0-0] }
And the allure report looks like:
Do anyone knows how to avoid this ?
Reproducible example:
webdriverio-Jasmine - Copy.zip
Just run:
npm install
npx wdio
./openAllureRport.bat
observe console log and allure report as mentioned above
toHaveProperty
exists in both this library and the core ExpectJS package:
https://webdriver.io/docs/api/expect.html#tohaveproperty
https://jestjs.io/docs/en/expect#tohavepropertykeypath-value
This means you can't use the core ExpectJS assertion, because the WDIO one in this package overwrites it.
Not really sure on a good solution. Maybe add a check in the custom matcher to see if it's an Object, and if so, use the Expect version. I'm not crazy about have two functions of the same name serve different purposes though... Maybe change the name of this matcher to toHaveHtmlProperty
or toHaveElementProperty
?
Example
expect(label).toHaveStyle({
"font-family": "Faktum",
"font-size": "26px",
color: "#000" // handles "black", "#000000", "rgb(0, 0, 0)", and "rgba(0, 0, 0, 1)"
});
according to #105
Please also add:
I just ran into the following error message:
Expect $(`.todo`) to have text
Expected: "ToDo #3"
Received: " ToDo #3 "
I suggest to allow options for toHaveText
and toHaveTextContaining
to strip text from the result. These options should be default true
as I believe there are more scenarios where you want to strip it rather than keep it.
I was thinking about adding some test cases for the waitUntil function. A couple of conditions here failed, for example:
"waitUntil › positive condition › should fail if isNot is true".
In this case:
In my mind it makes sense that you are waiting for the condition to be failing in this test case. So therefore you should expect the result to fail.
I have written in my head the starter unit tests that I would expect the function to obey (pre adding in wait times) and I wondered if anyone had any thoughts on if this is what they also expect?
describe('waitUntil', () => {
let condition: any
const positiveCondition = () => { return {result: true, message: "test" }}
const negativeCondition = () => { return {result: false, message: "test" }}
describe('positive condition', () => {
beforeEach(() => {
condition = async () => {
return positiveCondition().result
}
})
test('should fail if isNot is true', async () => {
const pass = await waitUntil(condition, true, {})
expect(pass).toBe(false)
})
test('should pass if isNot is false', async () => {
const pass = await waitUntil(condition, false, {})
expect(pass).toBe(true)
})
test('should fail if isNot is true and wait is 0', async () => {
const pass = await waitUntil(condition, true, {wait: 0})
expect(pass).toBe(false)
})
test('should pass if isNot is false and wait is 0', async () => {
const pass = await waitUntil(condition, false, {wait: 0})
expect(pass).toBe(true)
})
})
describe('negative condition', () => {
beforeEach(() => {
condition = async () => {
return negativeCondition().result
}
})
test('should pass if isNot is true', async () => {
const pass = await waitUntil(condition, true, {})
expect(pass).toBe(true)
})
test('should fail if isNot is false', async () => {
const pass = await waitUntil(condition, false, {})
expect(pass).toBe(false)
})
test('should pass if isNot is true and wait is 0', async () => {
const pass = await waitUntil(condition, true, {wait: 0})
expect(pass).toBe(true)
})
test('should fail if isNot is false and wait is 0', async () => {
const pass = await waitUntil(condition, false, {wait: 0})
expect(pass).toBe(false)
})
})
})
Environment
expect-webdriverio
version: 1.3.1
WebdriverIO version: 6.4.4
Test Framework: mocha (jest/jasmine/mocha/cucumber/etc)
async/sync: sync (is @wdio/sync
used? - Yes)
Steps to reproduce
const searchMock = browser.mock('FOOBAR') // 0 requests
expect(searchMock).toBeRequested() // should fail
Actual Result
Expect mock to be called
Expected: 0
Received: serializes to the same string
Expected Result
similar to how toHaveChildren
matcher works
Expect $(`input`) to have children
Expected: ">= 1"
Received: 0
When I run tsc
5 errors are found
$ tsc
node_modules/@types/jasmine/ts3.1/index.d.ts:112:18 - error TS2451: Cannot redeclare block-scoped variable 'expect'.
112 declare function expect<T extends jasmine.Func>(spy: T | jasmine.Spy<T>): jasmine.FunctionMatchers<T>;
~~~~~~
node_modules/expect-webdriverio/types/jest-global.d.ts:3:15
3 declare const expect: jest.Expect
~~~~~~
'expect' was also declared here.
node_modules/@types/jasmine/ts3.1/index.d.ts:119:18 - error TS2451: Cannot redeclare block-scoped variable 'expect'.
119 declare function expect<T>(actual: ArrayLike<T>): jasmine.ArrayLikeMatchers<T>;
~~~~~~
node_modules/expect-webdriverio/types/jest-global.d.ts:3:15
3 declare const expect: jest.Expect
~~~~~~
'expect' was also declared here.
node_modules/@types/jasmine/ts3.1/index.d.ts:126:18 - error TS2451: Cannot redeclare block-scoped variable 'expect'.
126 declare function expect<T>(actual: T): jasmine.Matchers<T>;
~~~~~~
node_modules/expect-webdriverio/types/jest-global.d.ts:3:15
3 declare const expect: jest.Expect
~~~~~~
'expect' was also declared here.
node_modules/@types/jasmine/ts3.1/index.d.ts:131:18 - error TS2451: Cannot redeclare block-scoped variable 'expect'.
131 declare function expect(): jasmine.NothingMatcher;
~~~~~~
node_modules/expect-webdriverio/types/jest-global.d.ts:3:15
3 declare const expect: jest.Expect
~~~~~~
'expect' was also declared here.
node_modules/expect-webdriverio/types/jest-global.d.ts:3:15 - error TS2451: Cannot redeclare block-scoped variable 'expect'.
3 declare const expect: jest.Expect
~~~~~~
node_modules/@types/jasmine/ts3.1/index.d.ts:112:18
112 declare function expect<T extends jasmine.Func>(spy: T | jasmine.Spy<T>): jasmine.FunctionMatchers<T>;
~~~~~~
'expect' was also declared here.
node_modules/@types/jasmine/ts3.1/index.d.ts:119:18
119 declare function expect<T>(actual: ArrayLike<T>): jasmine.ArrayLikeMatchers<T>;
~~~~~~
and here.
node_modules/@types/jasmine/ts3.1/index.d.ts:126:18
126 declare function expect<T>(actual: T): jasmine.Matchers<T>;
~~~~~~
and here.
node_modules/@types/jasmine/ts3.1/index.d.ts:131:18
131 declare function expect(): jasmine.NothingMatcher;
~~~~~~
and here.
Found 5 errors.
Dependencies
$ npm ls --depth=0
├── @types/[email protected]
├── @typescript-eslint/[email protected]
├── @wdio/[email protected]
├── @wdio/[email protected]
├── @wdio/[email protected]
├── @wdio/[email protected]
├── @wdio/[email protected]
├── @wdio/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"outDir": "./dist/",
"baseUrl": ".",
"allowJs": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"paths": {
"@tests/*": ["./tests/*"],
"@be-pages/*":["./src/pages/*"],
"@be-selectors/*":["./src/selectors/*"]
},
"types": ["node", "@wdio/sync", "@wdio/jasmine-framework", "expect-webdriverio"]
},
"include": ["./src/**/*.ts", "./tests/**/*.ts", "./config/**/*.ts"],
"exclude": ["node_modules"]
}
toHaveText
and toHaveTextContaining
do not get the element text correctly
it('go to google', async () => {
await browser.url('http://www.google.com');
const elem = await $('#SIvCob');
expect(await elem.getText()).toContain('Google offered in');
expect(elem).toHaveTextContaining('Google offered in');
})
The assertions should be equivalent, but actually, the second resolves to false.
[0-0] {
passed: true,
assertion: {
matcherName: 'toContain',
passed: true,
message: '',
error: undefined,
errorForStack: undefined,
actual: 'Google offered in: Français',
expected: 'Google offered in'
}
}
[0-0] {
passed: undefined,
assertion: {
matcherName: 'toHaveTextContaining',
passed: undefined,
message: "Expected Element({ sessionId: '276a5be58236ede817a24f4e00b3ef3c', elementId: '283acefc-74ce-4fea-9699-ffb41e49b0ba', element-6066-11e4-a52e-4f735466cecf: '283acefc-74ce-4fea-9699-ffb41e49b0ba', selector: '#SIvCob', parent: Browser({ sessionId: '276a5be58236ede817a24f4e00b3ef3c', capabilities: Object({ acceptInsecureCerts: true, browserName: 'chrome', browserVersion: '90.0.4430.85', chrome: Object({ chromedriverVersion: '90.0.4430.24 (4c6d850f087da467d926e8eddb76550aed655991-refs/branch-heads/4430@{#429})', userDataDir: '/var/folders/x8/c58l8cz10x7gkpf7wy1hxcv00000gn/T/.com.google.Chrome.CscXpN' }), goog:chromeOptions: Object({ debuggerAddress: 'localhost:52180' }), networkConnectionEnabled: false, pageLoadStrategy: 'normal', platformName: 'mac os x', proxy: Object({ }), setWindowRect: true, strictFileInteractability: false, timeouts: Object({ implicit: 0, pageLoad: 300000, script: 30000 }), unhandledPromptBehavior: 'dismiss and notify', webauthn:extension:largeBlob: true, webauthn:virtualA ... to have text containing 'Google offered in'.",
error: undefined,
errorForStack: undefined,
actual: Element {
sessionId: '276a5be58236ede817a24f4e00b3ef3c',
elementId: '283acefc-74ce-4fea-9699-ffb41e49b0ba',
'element-6066-11e4-a52e-4f735466cecf': '283acefc-74ce-4fea-9699-ffb41e49b0ba',
selector: '#SIvCob',
parent: [Browser],
emit: [Function: bound ],
isReactElement: false,
addCommand: [Function (anonymous)],
overwriteCommand: [Function (anonymous)]
},
expected: 'Google offered in'
}
}
[0-0] {
passed: false,
assertion: {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: {
matcherName: 'toHaveTextContaining',
message: "Expected Element({ sessionId: '276a5be58236ede817a24f4e00b3ef3c', elementId: '283acefc-74ce-4fea-9699-ffb41e49b0ba', element-6066-11e4-a52e-4f735466cecf: '283acefc-74ce-4fea-9699-ffb41e49b0ba', selector: '#SIvCob', parent: Browser({ sessionId: '276a5be58236ede817a24f4e00b3ef3c', capabilities: Object({ acceptInsecureCerts: true, browserName: 'chrome', browserVersion: '90.0.4430.85', chrome: Object({ chromedriverVersion: '90.0.4430.24 (4c6d850f087da467d926e8eddb76550aed655991-refs/branch-heads/4430@{#429})', userDataDir: '/var/folders/x8/c58l8cz10x7gkpf7wy1hxcv00000gn/T/.com.google.Chrome.CscXpN' }), goog:chromeOptions: Object({ debuggerAddress: 'localhost:52180' }), networkConnectionEnabled: false, pageLoadStrategy: 'normal', platformName: 'mac os x', proxy: Object({ }), setWindowRect: true, strictFileInteractability: false, timeouts: Object({ implicit: 0, pageLoad: 300000, script: 30000 }), unhandledPromptBehavior: 'dismiss and notify', webauthn:extension:largeBlob: true, webauthn:virtualA ... to have text containing 'Google offered in'.",
stack: "Error: Expected Element({ sessionId: '276a5be58236ede817a24f4e00b3ef3c', elementId: '283acefc-74ce-4fea-9699-ffb41e49b0ba', element-6066-11e4-a52e-4f735466cecf: '283acefc-74ce-4fea-9699-ffb41e49b0ba', selector: '#SIvCob', parent: Browser({ sessionId: '276a5be58236ede817a24f4e00b3ef3c', capabilities: Object({ acceptInsecureCerts: true, browserName: 'chrome', browserVersion: '90.0.4430.85', chrome: Object({ chromedriverVersion: '90.0.4430.24 (4c6d850f087da467d926e8eddb76550aed655991-refs/branch-heads/4430@{#429})', userDataDir: '/var/folders/x8/c58l8cz10x7gkpf7wy1hxcv00000gn/T/.com.google.Chrome.CscXpN' }), goog:chromeOptions: Object({ debuggerAddress: 'localhost:52180' }), networkConnectionEnabled: false, pageLoadStrategy: 'normal', platformName: 'mac os x', proxy: Object({ }), setWindowRect: true, strictFileInteractability: false, timeouts: Object({ implicit: 0, pageLoad: 300000, script: 30000 }), unhandledPromptBehavior: 'dismiss and notify', webauthn:extension:largeBlob: true, webauthn:virtualA ... to have text containing 'Google offered in'.\n" +
' at <Jasmine>\n' +
' at Spec.addExpectationResult (/Users/thiagolima/Documents/neo/member-portal/node_modules/@wdio/jasmine-framework/build/index.js:296:32)\n' +
' at <Jasmine>\n' +
' at UserContext.<anonymous> (/Users/thiagolima/Documents/neo/member-portal/test/wdio/tests/login.test.ts:32:18)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:93:5)',
passed: undefined,
expected: 'Google offered in',
actual: [Element]
}
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.