How do we use expect in WebdriverIO as a standalone script? - webdriver-io

WebdriverIO has a sample of using it in a script:
https://webdriver.io/docs/gettingstarted#run-in-a-script
const { remote } = require('webdriverio');
;(async () => {
const browser = await remote({
capabilities: {
browserName: 'chrome'
}
})
await browser.url('https://webdriver.io')
const apiLink = await browser.$('=API')
await apiLink.click()
await browser.saveScreenshot('./screenshot.png')
await browser.deleteSession()
})()
However, there is no mentioning of how we can use expect, such as expect(elementFoo).toHaveText("Hello World") How can we have expect (and have one of mocha, jasmine, or cucumber like when we set up a webdriverio project using
npx wdio ./path/to/new/project
or is it already possible to use expect without using one of those three modules?)
Also, if we used npx wdio ./path/to/new/project to create a whole project, the expect(elementFoo).toHaveText("Hello World") knows how to wait a few seconds to finally say that it doesn't contain the text, which I am not sure if pure mocha, jasmine, or cucumber has that feature too.

Related

Selenium and Jasmine: BeforeAll fails silently while building Firefox driver

I have written some tests for my app in selenium. I run them locally and on our GitLab-CI. locally they work, but on the CI they fail suddenly (without me having changed something relevant afaik). What makes me scratch my head is, the fact, that the beforeAll not seems to be ran to the end.
Consider this:
let driver;
const options = new Options();
if (testConfig.headless) {
options.addArguments('-headless');
}
describe('my app', () => {
beforeAll(async done => {
console.log('beforeAll');
try {
driver = await new Builder()
.forBrowser('firefox')
.setFirefoxOptions(options)
.build();
} catch (e) {
console.log('error', e);
}
console.log(!driver ? 'driver is not' : driver is');
done();
});
});
beforeEach(async done => {
await driver.get(/* my apps path */);
done();
});
Result on de CI: Every test fails in beforeEach because driver is undefined. But the beforeAll only reports 'beforeAll'. the log in the end does not says nothing. So the beforeAll function seem to fail, but silently and the script does continue anyway. Any Ideas how I can fix or even debug this?
My dependencies
"devDependencies": {
"geckodriver": "^1.20.0",
"jasmine": "^3.6.3",
"selenium-webdriver": "^4.0.0-alpha.7",
The reason was, in contradiction to the above example, the browser wasn't started in headless mode. My fault. But still, a very crappy behavior not to say anything. I leave this here, if anyone is facing the same.

Unit testing for REST API using node Js

I want to write unit testing for my REST API calls(Using mocha and chai).
Can anyone provide me better guide or any previously written code ,so that I can perform easily.
There are multiple guides through internet to start with mocha and chai. As, for example, the official documentation:
Mocha documentation
Chai documentation
Using npm you can install both:
Mocha: npm install --save-dev mocha
Chai: npm install chai
Also, for HTTP you need chai-http: npm install chai-http
With this you can start to code your tests.
First of all, into your test file you need import packages
var chai = require('chai'), chaiHttp = require('chai-http');
chai.use(chaiHttp);
And also use the assertion you want, for example:
var expect = chai.expect;.
Tests use this schema:
describe('Test', () => {
it("test1", () => {
})
it("test2", () => {
})
})
Where describe is to declare a 'suite' of tests. And inside every suite you can place multiple tests, even another suite.
If you execute this code using mocha yourFile.js you will get:
Test
√ test1
√ test2
Now you can start to add routes to test. For example somthing like this:
it("test1", () => {
chai.request('yourURL')
.get('/yourEndpoint')
.query({value1: 'value1', value2: 'value2'})
.end(function (err, res) {
expect(err).to.be.null;
expect(res).to.have.status(200);
});
})
And if you want to use your own express app, you can use
var app = require('../your/app')
...
it("test1", () => {
chai.request(app)
...
}
...
And also exists multiple more options describe into Chai documentation.

Jest + Selenium: how do I do an operation before and after all tests inside a describe block is run?

I am trying to create a simple automated test to detect if the added element contains the text it is supposed to have. The test is run using node.js with jest command. I am using Selenium to automate the UI process and Jest to validate the UI's content.
I want to do the following.
Create variables that are accessible in all tests in the describe block before running any of the test
Close the Selenium-driven browser after all tests in the describe block is run
So far, I have this code.
const { Builder, By, until } = require('selenium-webdriver')
const url = 'http://127.0.0.1:3000'
describe('addUser', async() => {
afterAll(async() => {
await driver.quit()
}, 15000)
test('valid name and age should add a new element', async() => {
const driver = await new Builder().forBrowser('firefox').build()
await driver.get(url)
const nameField = await driver.wait(until.elementLocated(By.id('name')), 10000)
const ageField = await driver.wait(until.elementLocated(By.id('age')), 10000)
const btnAddUser = await driver.wait(until.elementLocated(By.id('btnAddUser')), 10000)
await nameField.click()
await nameField.sendKeys('Adam')
await ageField.click()
await ageField.sendKeys('39')
await btnAddUser.click()
const userItem = await driver.wait(until.elementLocated(By.css('.user-item')), 10000)
const userItemText = await userItem.getText()
expect(userItemText).toBe('Adam (39 years old)')
}, 10000)
})
The problems I am facing are the following.
I have to declare the driver, ask the driver to open a new page, and finding all the necessary elements every time I run a test. If possible, I would like to do these initialization steps inside a beforeAll function (by Jest) and store the variables somehow. Then, I can use driver, nameField, ageField, etc. in every test without having to declare them again. How would I do this while maintaining a clean code?
I will close the Selenium-driven browser after all tests inside the addUser describe block are run. So, I added driver.quit() inside afterAll (Jest) to close the browser. Unfortunately, this doesn't work; the browser doesn't close itself. How can I close the Selenium-operated browser after each describe block?
The test is working great, but how can I solve the two problems above?
driver variable is declared in test scope and is unavailable in afterAll. Even if it were declared in describe scope, a teardown would be performed only for the last driver because there can be multiple tests but afterAll is called after the last one.
Variables that need a teardown can be either redefined for each test:
let driver;
beforeEach(async () => {
driver = ...
});
afterEach(async () => {
await driver.quit()
});
Or reused for all tests:
let driver;
beforeAll(async () => {
driver = ...
});
afterAll(async () => {
await driver.quit()
});

How do I run tests on multiple browsers in lambdatest?

I have a lambdatest and testcafe setup, lambdatest account has a single parallel run.
As far as I understand, testcafe doesn't support queuing of tests.
So my question is how do I manage to run tests on different browser/OS combination on lambdatest(one after the other without queuing).
Thanks in advance.
You can create several runners for each browser and run them in series. You can find an example in the following thread on GitHub:
https://github.com/DevExpress/testcafe/issues/2495#issuecomment-421090352
As Dmitry stated, you can create several runners for each browser and run them in series.
Here is an example code to run parallel testing over LambdaTest Selenium Grid through custom testcafe runner.
const browsers = [
['lambdatest:Chrome#74.0:Windows 10"', 'lambdatest:Chrome#75.0:Windows 10'],
['lambdatest:Chrome#76.0:Windows 8', 'lambdatest:Chrome#77.0:Windows 8'],
];
const runTest = async browser => {
console.log('starting tests');
await createTestCafe('localhost', 1337, 1338)
.then(tc => {
testcafe = tc;
const runner = testcafe.createRunner();
return runner
.src(['web-tests/*.ts'])
.browsers(browser)
.run();
})
.then(async failedCount => {
console.log('Tests failed: ' + failedCount);
await testcafe.close();
return;
});
}
const runAllBrowsers = async () => {
for (const browser of browsers) {
await runTest(browser);
}
}
For more information, refer to GitHub repository of LambdaTest & Testcafe. Cheers!

Jasmine test makes no pass/fail report under webdriver.io

Running the following jasmine test under webdriver.io like this: node path/to/test/script.js, the test executes (web browser is pulled up, target page visited), and thanks to the last line, the jasmine 'it' functions (below) do execute (without the last line, they don't, although the 'describe' function still runs).
But jasmine doesn't provide any kind of report result for the 'it' tests and the 'expect' assertions; there's nothing on the console from jasmine. There's no 'pass/fail' result, and so forth.
How to get jasmine to make a report, and esp. one that is readable by Jenkins?
The problem test script:
var webdriverjs = require('foo-bar/node_modules/webdriverio');
var jasmine = require('foo-bar/node_modules/jasmine-node');
var options = {
port: 4445,
desiredCapabilities: {
browserName: process.argv[2] || 'phantomjs'
}
};
describe('my webdriverjs tests', function () {
var client;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 9999999;
beforeEach(function() {
client = webdriverjs.remote(options);
client.init();
});
it('shows the correct title', function (done) {
client
.url('http://localhost:4444').getTitle(function(err, title) {
expect(title).toBe('foo bar');
}).call( done );
});
afterEach(function(done) {
client.end(done);
});
});
jasmine.getEnv().execute();
Note: Cross-posted here: https://groups.google.com/forum/#!topic/webdriverio/-EOrQ003B9I
I ran into some of the same challenges when I was looking into this. The big issue is that this test needs to be executed as a jasmine test, not a webdriver test.
decribe('my webdriverio tests with jasmine', function(){
var client;
beforeEach(function(){
client = require('path/to/webdriverio').remote({
desiredCapabilities: {browserName:'safari'}
}).init.url('https://www.stackoverflow');
}, 5000);
afterEach(function(done){
client.end(done);
}, 5000);
it('runs a very simple test',function(done){
client.getTitle(function(err,result){
expect(result).toBe('Stack Overflow');
}).call(done);
}, 5000);
});
Now to run this test, you would just run a typical jasmine-node command from your terminal.
It comes down to the naming convention you are using. First, you need to remove the last line: jasmine.getEnv().execute(); then run the jasmine-node command with the --matchall flag:
jasmine-node --matchall path/to/test/script.js
If you named your file script_spec.js, then you could run it without the --matchall flag.
This is also assuming you have jasmine-node installed globally. If you want to use the local node_modules dependency, then you need to run this command:
./node_modules/jasmine-node/bin/jasmine-node --matchall path/to/test/script.js
When you are using jasmine-node module you should run your spec with
node_modules/jasmine-node/bin/jasmine-node $TEST_DIRECTORY
And your test should end with *spec.js, *spec.coffee or *spec.litcoffee as docs said.
And jasmine.getEnv().execute(); and var jasmine = require('foo-bar/node_modules/jasmine-node'); should not be in your script.