Testcafe test is running twice - testing

I have a testcafe project where i run tests. I've divided in multiple fixtures but there's one file that is always running twice and i can't figure it out what's wrong, my other files do not have this problem.
this is my fixture file.
fixture`${environment} ENV`.page`${adminUrl}`
.before(async () => {
connection = await initDB();
const tempSimulationsRun = await prepareTempRunRecords();
const tempId = await createTempDomainUser(tempAdminUser, Number(userDomainRoles.KALEIDOSIM_ADMINS));
await insertTempRunRecords(tempSimulationsRun);
})
.after(async () => {
// remove temp org
await removeOrganizationByName(TEMP_ORG_NAME);
});
test(`KiDomain Simulation Runs feature`, async () => {
const tempUser: UserCreationData = {
email: test02.email,
country: "acouuntry",
firstName: "KI Domain",
lastName: "KALEIDO",
password: test02.password,
phoneNumber: "+59173698120",
};
const userId1 = await createTempDomainUser(tempUser, Number(userDomainRoles.GOLD_ADMINS));
userDomainIdList.push(userId1);
const credentials: UserCredentials = {
email: tempUser.email,
password: tempUser.password,
};
await SimulationRunFeature(credentials);
});
this is my console log output
2022-10-08 15:10:51.523 INFO [CustomLog.info] Registering a new user in DB
creating fake run records
run records created
2022-10-08 15:11:22.422 INFO [CustomLog.info] Registering a new user in DB
creating fake run records
run records created
and this is my package.json command
"portal_target_kitestcloud1": "FRONT_END_ENV=kitestcloud1 NODE_ENV=kitestcloud1 testcafe 'chrome:headless' src/fixtures/portal/portal.ts --skip-js-errors --concurrency 6 --reporter html:reports/testcafe-portal.html -s takeOnFails=true -q attemptLimit=3,successThreshold=1",
any help is appreciated,
thanks in advance.

Related

Using ssh in cy.exe() always get timeout error

I use ssh command in cypress exec command. ssh command works properly but I get timeout error from exec() function always.
My code is :
cy.exec('ssh username#111.111.1.1 "\file.exe"')
Actually this code works properly and I can see that file.exe works on remote desktop but I get error on exec().
I think I have to put some options inside the ssh command like -q -w . I tried some of them but it did not work.
Could you please help me?
Maybe exec is too limited in the way you can interact with the command being called, you need a programmable API rather than just configuration options.
You can try using a task instead, there is a library node-ssh that will interface with a Cypress task.
I'm not familiar with ssh protocols, so you will have to fill in those details, but here is a basic example for Cypress task and the node-ssh library
cypress/plugins/index.js
module.exports = (on, config) => {
on('task', {
ssh(params) {
const {username, host, remoteCommand} = params // destructure the argument
const {NodeSSH} = require('node-ssh')
const ssh = new NodeSSH()
ssh.connect({
host: host,
username: username,
privateKey: '/home/steel/.ssh/id_rsa' // maybe parameterize this also
})
.then(function() {
ssh.execCommand(remoteCommand, { cwd:'/var/www' })
.then(function(result) {
console.log('STDOUT: ' + result.stdout)
console.log('STDERR: ' + result.stderr)
})
})
return null
},
})
}
Returning result
The above ssh code is just from the example page of node-ssh. If you want to return the result value, I think this will do it.
module.exports = (on, config) => {
on('task', {
ssh(params) {
const {username, host, remoteCommand} = params // destructure the argument
// returning promise, which is awaited by Cypress
return new Promise((resolve, reject) => {
const {NodeSSH} = require('node-ssh')
const ssh = new NodeSSH()
ssh.connect({
host: host,
username: username,
privateKey: '/home/steel/.ssh/id_rsa'
})
.then(function() {
ssh.execCommand(remoteCommand, { cwd:'/var/www' })
.then(function(result) {
resolve(result) // resolve to command result
})
})
})
},
})
}
In the test
cy.task('ssh', {username: 'username', host: '111.111.1.1', command: '\file.exe'})
.then(result => {
...
})
Only a single parameter is allowed for a task, so pass in an object and destructure it inside the task as shown above.

Testcafe not working for Nuxt/Vue Amplify/Cognito calls. RangeError: Maximum call stack size exceeded

I have been trying out Testcafe for our Nuxt application E2E tests as I understood it has good selectors with VueJS and its working great except for the parts where a call is made to cognito via amplify for user login/signup. It might be a testcafe and amplify issue rather than the frontend framework issue as the Login/Signup works absolutely fine. Also tried replacing the Cognito calls with normal REST api calls and it works fine too. Also tried it with Cypress and they work fine but Testcafe has better coverage in terms of cross browser testing so maybe a better option. Do you know if how I can fix this error or its better to look into different frameworks? Will try to share share my code in the best way possible as I cannot share my repo as its for my company. And will be happy to answer with more code or clarifications if required. Thanks and find the code below:
My submit function:
async submit() {
this.$v.$touch();
if (this.$v.$invalid) return;
this.disabled = true;
try {
await this.registerUser({
username: this.email,
password: this.newPassword,
attributes: {
given_name: this.firstname,
family_name: this.lastname,
email: this.email,
'custom:isPerson': 'true',
'custom:dataPrivacy': 'true'
}
});
this.$router.push(this.appendLocalization('/user/confirmuser'));
this.disabled = false;
} catch (error) {
this.$log.error('Could not register user', error);
this.disabled = false;
}
The amplify function:
import Auth from '#aws-amplify/auth';
import Amplify from '#aws-amplify/core';
Amplify.configure({
Auth: {
userPoolId: process.env.userPoolId,
userPoolWebClientId: process.env.userPoolWebClientId,
region: process.env.region
}
});
export const state = () => {
return {
session: {},
user: {}
};
};
export const mutations = {
setUser: (state, user) => {
state.user = { ...user };
state.session = state.user.signInUserSession;
}
};
registerUser: ({ commit }, credentials) =>
new Promise((resolve, reject) => {
Auth.signUp({
username: credentials.username,
password: credentials.password,
attributes: credentials.attributes
})
.then((user) => {
commit('setUser', user);
resolve(user);
})
.catch(reject);
}),
My Testcafe code:
import { Selector, ClientFunction } from 'testcafe';
fixture`Signup Page`.page`http://localhost:3000/de/user/signup`;
const email = Selector('input').withAttribute('name', 'email');
const password = Selector('input').withAttribute('name', 'password');
const checkbox = Selector('input').withAttribute('type', 'checkbox');
const button = Selector('button').withAttribute('name', 'submit');
const getLocation = ClientFunction(() => document.location.href);
test('Test successful signup', async (t) => {
const validemail =
'WebFunctionalTest' + new Date().getTime() + '#something.com';
const validpassword = 'password';
await t
.typeText(email, validemail)
.typeText(password, validpassword)
await t.click(button).debug();
await t.expect(getLocation()).contains('userconfirm');
});
Signup Error:
RangeError: Maximum call stack size exceeded
at c (hammerhead.js:16)
at i (hammerhead.js:16)
at value (hammerhead.js:6)
at _traverse (commons.app.js:12575)
at _traverse (commons.app.js:12575)
at _traverse (commons.app.js:12575)
at _traverse (commons.app.js:12575)
at _traverse (commons.app.js:12575)
at _traverse (commons.app.js:12575)
at _traverse (commons.app.js:12575)
P.S: I can see that Testcafe is making the cognito call and is getting a proper response in network tab but somehow not handling it in the code. I thought Testcafe should behave like a normal user testing like click the button and wait for the whole sequence to finish i.e successful page transition but somehow it's not.
I have spent quite sometime trying to figure this out but couldnt so posting it elaborately here, any help will be very appreciated. Thanks in advance.

Is it possible to run same testcafe fixture with different preconditions

Could somebody help with finding the most adequate way to run the same fixture with different preconditions using testcafe (fixture beforeEach)?
Given I have following fixture:
fixture('[Test] My Page')
.meta({ env: 'aat', mobile: 'true', author: 'me' })
.beforeEach(async t => {
await t.navigateTo(myPage.url)
await waitForReact(10000)
})
test('Page should load all data successfully', async t => {
const { Query: queries } = await t.ctx.graphQLTools.mockManagementClient.getCalls()
for (const q of Object.keys(queries)) {
for (const { args, context } of Object.keys(queries[q])) {
await t.expect(queries[q][args]).typeOf('undefined')
await t.expect(queries[q][context]).typeOf('undefined')
}
}
})
In the code example above I need to run this test for several times:
I'm an anonymous user
I'm the admin user
I'm a default user
I've tried the following code, but it looks cumbersome and will create complexity when I have more than 1 test in the fixture that needs to be checked(taken from https://testcafe-discuss.devexpress.com/t/multiple-execution-of-one-test-with-different-data/219):
const a = ['anonymous', 'logged In']
for (const user of a) {
test.meta({ wip: 'true' })(`Page should load all data successfully for ${user} user`, async t => {
if (R.equals('logged In', user)) {
await helpers.setCookie({ key: 'access_token', value: '123123123' })
await helpers.reloadPage()
}
const { Query: queries } = await t.ctx.graphQLTools.mockManagementClient.getCalls()
await t.expect(helpers.isEqlToEmptyQuery(queries.basket)).eql(true)
await t.expect(helpers.isEqlToEmptyQuery(queries.categories)).eql(true)
if (R.equals('logged In', user)) {
await t.expect(helpers.isEqlToEmptyQuery(queries.customer)).eql(true)
}
})
}
Is there a way I can run the whole fixture for 2-3 times with different beforeEach fixture hooks?
One simple solution could be to add three npm scripts in package.json:
"test": "testcafe chrome <all testcafe options>"
"test-anonymous": "npm test -- --user=anonymous"
"test-admin": "npm test -- --user=admin"
"test-default": "npm test -- --user=default"
Then read this custom command-line option in the beforeEach as I explained in Testcafe - Test command line argument outside test case

Control vue navigation from Testcafe

For testing Vue2 I use testcafe.
Command to run tests
testcafe firefox test/e2e/specs/ --app \"npm run dev\"
--app-init-delay 20000 -S -s test/e2e/screenshots
Test file
import { ClientFunction, Selector } from 'testcafe';
const devServer = require('../../../webpack/devServer');
fixture(`Getting Started`)
// Load the URL your development server runs on.
.page(`http://localhost:${devServer.port}/#/login`);
test('test login', async t => {
const userSelector = await new Selector('.login-squere input[type="text"]');
const passSelector = await new Selector('.login-squere input[type="password"]');
const logiIn = await new Selector('.login-squere button');
await t.typeText(userSelector, 'manager')
.typeText(passSelector, 'manager')
.click(logiIn);
});
I expect after .click(logiIn) site to route to /#/projects, but nothing happens
I added to test
await t.typeText(userSelector, 'manager')
.typeText(passSelector, 'manager')
.click(logiIn)
.navigateTo(`http://localhost:${devServer.port}/#/projects`);
And again no result. If I set .page to /#/projects it wil be rerouted to login.
So I can test only login page, because I cant make testcafe route Vue to next view.
This problem appears only if after login click we have ajax. TestCafe doesnt have request handler, so it is better to try something else for e2e
Try this one:
test('login', async t => {
await login(t);
});
and separate your code into a new function:
const login = async t => {
const userSelector = await new Selector('.login-squere input[type="text"]');
const passSelector = await new Selector('.login-squere input[type="password"]');
const logiIn = await new Selector('.login-squere button');
await t.typeText(userSelector, 'manager')
.typeText(passSelector, 'manager')
.click(logiIn);
};

How to test an Electron app with selenium webdriver

I have read the documentation and I have followed the tutorial step by step and I only have managed to run the app.
Documentation: http://electron.atom.io/docs/tutorial/using-selenium-and-webdriver/
The connection with chromedriver I cannot make it work, when I launch the test and try click a simple button I get this:
Error: ChromeDriver did not start within 5000ms at Error (native)
at node_modules/spectron/lib/chrome-driver.js:58:25 at
Request._callback (node_modules/spectron/lib/chrome-driver.js:116:45)
at Request.self.callback
(node_modules/spectron/node_modules/request/request.js:200:22) at
Request.
(node_modules/spectron/node_modules/request/request.js:1067:10) at
IncomingMessage.
(node_modules/spectron/node_modules/request/request.js:988:12) at
endReadableNT (_stream_readable.js:913:12) at _combinedTickCallback
(internal/process/next_tick.js:74:11) at process._tickCallback
(internal/process/next_tick.js:98:9)
My code:
"use strict";
require("co-mocha");
var Application = require('spectron').Application;
var assert = require('assert');
const webdriver = require('selenium-webdriver');
const driver = new webdriver.Builder()
.usingServer('http://127.0.0.1:9515')
.withCapabilities({
chromeOptions: {
binary: "./appPath/app"
}
})
.forBrowser('electron')
.build();
describe('Application launch', function () {
this.timeout(100000);
var app;
beforeEach(function () {
app = new Application({
path: "./appPath/app"
});
return app.start();
});
afterEach(function () {
if (app && app.isRunning()) {
return app.stop();
}
});
it('click a button', function* () {
yield driver.sleep(5000);
yield driver.findElement(webdriver.By.css(".classSelector")).click();
});
});
Thanks and sorry for my English.
I recommend you to use Spectron. which is a less painful way of testing your electron app. in my opinion perfect combination is using it with Ava test framework, which allows the concurrently test.
async & await is also another big win. which allows you to have so clean test cases.
and also if you have a test which needs to happen serial, you can use test.serial
test.serial('login as new user', async t => {
let app = t.context.app
app = await loginNewUser(app)
await util.screenshotCreateOrCompare(app, t, 'new-user-mission-view-empty')
})
test.serial('Can Navigate to Preference Page', async t => {
let app = t.context.app
await app.client.click('[data-test="preference-button"]')
await util.screenshotCreateOrCompare(app, t, 'new-user-preference-page-empty')
})
and just for reference; my helper test cases.
test.before(async t => {
app = util.createApp()
app = await util.waitForLoad(app, t)
})
test.beforeEach(async t => {
t.context.app = app
})
test.afterEach(async t => {
console.log('test complete')
})
// CleanUp
test.after.always(async t => {
// This runs after each test and other test hooks, even if they
failed
await app.client.localStorage('DELETE', 'user')
console.log('delete all files')
const clean = await exec('rm -rf /tmp/DesktopTest')
await clean.stdout.on('data', data => {
console.log(util.format('clean', data))
})
await app.client.close()
await app.stop()
})
util function,
// Returns a promise that resolves to a Spectron Application once the app has loaded.
// Takes a Ava test. Makes some basic assertions to verify that the app loaded correctly.
function createApp (t) {
return new Application({
path: path.join(__dirname, '..', 'node_modules', '.bin',
'electron' + (process.platform === 'win32' ? '.cmd' : '')),
// args: ['-r', path.join(__dirname, 'mocks.js'), path.join(__dirname, '..')],
env: {NODE_ENV: 'test'},
waitTimeout: 10e3
})
}
First off, Spectron (which is a wrapper for WebdriverIO) and WebdriverJS (which is part of Selenium-Webdriver) are two different frameworks, you only need to use one of them for your tests.
If you are using WebdriverJS, then you need to run ./node_modules/.bin/chromedriver in this step: http://electron.atom.io/docs/tutorial/using-selenium-and-webdriver/#start-chromedriver
I could get ChromeDriver working by adding a proxy exception in my terminal.
export {no_proxy,NO_PROXY}="127.0.0.1"