We have a lot of cypress tests in our Angular Project. But we want to use k6 as our new main load testing tool. But also we want to keep our already written cypress tests.
Is it possible to execute cypress tests within k6? e.g run k6 with 1000 VUs but instead of k6 test script, use cypress test scrpts.
There's an article here: Using Cypress to automate k6 scripts recording
Lots of steps, but to update for Cypress v10 the syntax for the before:browser:launch hook:
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('before:browser:launch', (browser, launchOptions) => {
if (browser.isHeaded) {
try {
launchOptions.extensions.push(...);
} catch (error) {
console.log("extension not available"); //when in headless mode
}
return launchOptions;
}
})
},
// other config
}
Answer above was a solid suggestion. I used that article indicated there, only slight modifications (i mentioned it on the medium post).
for cypress 10+, under cypress.config.js
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('before:browser:launch', (browser = {}, launchOptions) => {
console.log(launchOptions.args) // print all current args
//Mac and Linux path
//const k6path = "k6Files/k6-Browser-Recorder"
//Windows path
const k6path = "C:\\Users\\..."
if (browser.isHeaded) {
try {
launchOptions.extensions.push(k6path);
} catch (error) {
console.log("extension not available"); //when in headless mode
}
return launchOptions
}
})
},
},
});
if your using env config files like cypress.dev-config.js then above goes in that e2e section
Rest of instruction on the post should work just fine.
Related
In cypress, the xlsx file I am downloading always starts with lets say "ABC" and then some dynamic IDs like ABC86520837.xlsx. How can I verify and add assertion that if the file is downloaded successfully and also contains that dynamic name?
You'll need to create a task to search within file directory of your machine and then return a list of matching downloads to assert. You'll also need globby to make it easier.
In your plugins/index.js
async findFiles (mask) {
if (!mask) {
throw new Error('Missing a file mask to search')
}
console.log('searching for files %s', mask)
const list = await globby(mask)
if (!list.length) {
console.log('found no files')
return null
}
console.log('found %d files, first one %s', list.length, list[0])
return list[0]
},
In your spec file:
const downloadsFolder = Cypress.config('downloadsFolder')
const mask = `${downloadsFolder}/ABC*.xlsx`
cy.task('findFiles', mask).then((foundImage) => {
expect(foundImage).to.be.a('string')
cy.log(`found image ${foundImage}`)
})
Cypress example
Assuming you are running a recent version of Cypress,
Add a task to read the downloads folder in /cypress.config.js
const { defineConfig } = require('cypress')
const fs = require('fs')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('task', {
filesInDownload (folderName) {
return fs.readdirSync(folderName)
},
})
}
}
})
In the test
const downloadsFolder = Cypress.config('downloadsFolder')
cy.task('filesInDownload', downloadsFolder).then(files => {
const abcFile = files.find(file => file.startsWith('ABC'))
expect(abcFile).to.not.be.undefined
})
I recommend you set the downloadsFolder configuration, as this will remove files between test runs.
The erros occurs when i add
const replace = require("replace-in-file"); in file to my code
const replace = require("replace-in-file");
const options = {
files: "./config/dashboardData.json",
configFile: true,
from: /}\n{/g,
to: ",\n",
};
I have installed babel and configured the preset still I got the issue
The package replace-in-file handles files on the OS, so it needs to be called from Node.
You would need to set up a Cypress task.
In Cypress ver 10+, do this in cypress.config.js
// cypress.config.js
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('task', {
replaceTask(options) {
const replace = require("replace-in-file");
try {
const results = replace.sync(options);
return results
}
catch (error) {
return error
}
},
})
},
// other e2e configuration here
},
});
// test.spec.cy.js
it('calls replace-in-file', () => {
const options = {
files: "./config/dashboardData.json",
configFile: true,
from: /}\n{/g,
to: ",\n",
};
cy.task('replaceTask', options).then(resultsOrError => {
console.log(resultsOrError)
})
});
I'm using API Routes on a Next.JS app with Apollo-Server, to create a GraphQL API wrapper around a REST endpoint. But I'm running into an issue if the project has a bathPath.
I've been following this example, and a video tutorial on youtube.
I've replicated my issue by using the repo from that tutorial. Upon running that code $ yarn dev, and navigating to http://localhost:3000/api/graphql the GraphQl playground shows up, and works as expected.
However if I add a basepath to the project then the graphQl playground still shows up fine at http://localhost:300/basepath/api/graphql but it gives me the error of "Server cannot be reached" and shows a 404 error in the network tab on the dev tools.
To add the base path I created a next.config.js and added
module.exports = {
basePath: '/basepath'
}
In pages/api/graphql.ts I updated the path from /api/graphql to /basepath/api/graphql
import { ApolloServer } from "apollo-server-micro";
import { schema } from "src/schema";
const server = new ApolloServer({ schema });
const handler = server.createHandler({ path: "/somewhere/api/graphql" });
export const config = {
api: {
bodyParser: false,
},
};
export default handler;
In src/apollo.ts I updated the HttpLink uri from /api/graphql to /basepath/api/graphql
import {
ApolloClient,
InMemoryCache,
NormalizedCacheObject,
} from "#apollo/client";
import { useMemo } from "react";
let apolloClient: ApolloClient<NormalizedCacheObject>;
function createIsomorphicLink() {
if (typeof window === "undefined") {
// server
const { SchemaLink } = require("#apollo/client/link/schema");
const { schema } = require("./schema");
return new SchemaLink({ schema });
} else {
// client
const { HttpLink } = require("#apollo/client/link/http");
return new HttpLink({ uri: "/bathpath/api/graphql" });
}
}
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: createIsomorphicLink(),
cache: new InMemoryCache(),
});
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient();
if (initialState) {
_apolloClient.cache.restore(initialState);
}
if (typeof window === "undefined") return _apolloClient;
apolloClient = apolloClient ?? _apolloClient;
return apolloClient;
}
export function useApollo(initialState) {
const store = useMemo(() => initializeApollo(initialState), [initialState]);
return store;
}
Any ideas why adding a basepath would break this setup? and what I'd need to do to fix it?
This is my first time posting on stack overflow, so I hope my description is good enough, please do ask if I've missed anything and thanks for your help in advance!
I'm trying to write to console the network log after a test failure as part of my protractor suite. The code works fine when in an afterEach() block but fails to execute the promise when inside of a custom jasmine reporter. As far as I can tell the promise never executes, but there are no known/shown errors.
protractor config (simplified):
exports.config = {
specs: ['./e2e/**/*.spec.ts'],
capabilities: {
browserName: 'chrome',
chromeOptions: {
perfLoggingPrefs: {
enableNetwork: true,
enablePage: false,
}
},
loggingPrefs: {
performance: 'ALL',
browser: 'ALL'
},
},
onPrepare() {
jasmine.getEnv().addReporter({
specDone: result => {
new ErrorReporter(browser).logNetworkError(result);
}
});
},
};
ErrorReporter:
class ErrorReporter {
constructor(browser) {
this.browser = browser;
}
logNetworkError(result) {
if(result.status === 'failed') {
// execution makes it in here
this.browser.manage().logs().get('performance').then(function(browserLogs) {
// execution DOES NOT make it here
browserLogs.forEach(function(log) {
const message = JSON.parse(log.message).message;
if(message.method === 'Network.responseReceived') {
const status = message.params.response.status;
const url = message.params.response.url;
if(status !== 200 && status !== 304) {
console.log(`----E2E NETWORK ERROR----`);
console.log(`STATUS: [${status}]`);
console.log(`URL: [${url}]`);
console.log(`RESPONSE: [${log.message}]`);
}
}
});
});
}
}
}
module.exports = ErrorReporter;
The code inside the logNetworkError() method works completely fine when executed in an afterEach() block but never writes out any logs when executed as a custom reporter. I would expect that this would work as a jasmine reporter as well.
If it's not possible to execute this as a jasmine reporter is there some way to access the executed test's results in the afterEach() block? I do not want to log on successful test execution.
I figured out the solution. There was 2 main problems. The first was that I needed to use async and await inside of the function that was creating the log:
async logNetworkError(result) {
if(result.status === 'failed') {
const logs = await this.browser.manage().logs().get('performance');
logs.forEach((log) => {
const message = JSON.parse(log.message).message;
if(message.method === 'Network.responseReceived') {
const status = message.params.response.status;
const url = message.params.response.url;
if(status !== 200 && status !== 304) {
console.log(`-----E2E NETWORK ERROR-----`);
console.log(`TEST NAME: ${result.fullName}`);
console.log(`STATUS: [${status}]`);
console.log(`URL: [${url}]`);
console.log(`RESPONSE: [${log.message}]`);
}
}
});
}
}
the second part of the problem was that another reporter which was saving screenshots did not have async and await which was stopping other reporters from completing. Adding async/await to both reporters solved this issue.
I am trying to get Nightwatch's inbuilt parallel test_workers working with browserstack-local for local url testing.
When running tests without browserstack local, Nightwatch test_workers seem to work just fine. The same is true for running local tests without test_workers enabled.
I have tried the examples found here https://github.com/browserstack/nightwatch-browserstack but none of these uses browserstack-local in combination with Nightwatch test_workers.
When running locally with test_workers I get the following output.
Connecting local
Connected. Now testing...
Process terminated with code 0.
Has anyone else encountered similar issues?
EDIT: I have since resolved this issue and have posted an answer below
I have dumped the relevant configuration files below.
My local.conf.js
nightwatch_config = {
globals_path: 'globals.js',
output_folder: false,
src_folders: ['tests'],
selenium: {
'start_process': false,
'host': 'hub-cloud.browserstack.com',
'port': 80
},
test_workers: {
"enabled": true,
"workers":2
},
test_settings: {
default: {
desiredCapabilities: {
'browserstack.user': process.env.BROWSERSTACK_USER,
'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY,
'browserstack.local': true,
'browserstack.debug': false,
}
}
}
};
// Code to copy seleniumhost/port into test settings
for (let i in nightwatch_config.test_settings) {
if (nightwatch_config.test_settings.hasOwnProperty(i)) {
let config = nightwatch_config.test_settings[i];
config['selenium_host'] = nightwatch_config.selenium.host;
config['selenium_port'] = nightwatch_config.selenium.port;
}
}
module.exports = nightwatch_config;
local.runner.js
#!/usr/bin/env node
var Nightwatch = require('nightwatch');
var browserstack = require('browserstack-local');
var bs_local;
process.env.BROWSERSTACK_ID = new Date().getTime();
try {
process.mainModule.filename = "./node_modules/.bin/nightwatch";
// Code to start browserstack local before start of test
console.log("Connecting local");
Nightwatch.bs_local = bs_local = new browserstack.Local();
bs_local.start({ 'key': process.env.BROWSERSTACK_ACCESS_KEY }, function (error) {
if (error) throw error;
console.log('Connected. Now testing...');
Nightwatch.cli(function (argv) {
Nightwatch.CliRunner(argv)
.setup(null, function () {
// Code to stop browserstack local after end of parallel test
bs_local.stop(function () { });
})
.runTests(function () {
// Code to stop browserstack local after end of single test
bs_local.stop(function () { });
});
});
});
} catch (ex) {
console.log('There was an error while starting the test runner:\n\n');
process.stderr.write(ex.stack + '\n');
process.exit(2);
}
and my package.json script
node ./local.runner.js -c ./local.conf.js
The issue here was due to the module filename being incorrectly defined in the local.runner.js
process.mainModule.filename = "./node_modules/.bin/nightwatch";
should be pointed directly at the Nightwatch file in its directory.
process.mainModule.filename = "./node_modules/nightwatch/bin/nightwatch";
The difference in these files and the exact reason for this solution working are beyond me.
The answer was derived from the "suite" runner in https://github.com/browserstack/nightwatch-browserstack
It seems you are not specifying browsers. Modify your configuration file to be inline with the following configuration file:
var browserstack = require('browserstack-local');
nightwatch_config = {
src_folders : [ "local" ],
selenium : {
"start_process" : false,
"host" : "hub-cloud.browserstack.com",
"port" : 80
},
test_workers: {
"enabled": true,
"workers":2
},
common_capabilities: {
'browserstack.user': process.env.BROWSERSTACK_USERNAME || 'BROWSERSTACK_USERNAME',
'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY || 'BROWSERSTACK_ACCESS_KEY',
'browserstack.debug': true,
'browserstack.local': true
},
test_settings: {
default: {},
chrome: {
desiredCapabilities: {
browser: "chrome"
}
},
firefox: {
desiredCapabilities: {
browser: "firefox"
}
},
safari: {
desiredCapabilities: {
browser: "safari"
}
}
}
};
// Code to support common capabilites
for(var i in nightwatch_config.test_settings){
var config = nightwatch_config.test_settings[i];
config['selenium_host'] = nightwatch_config.selenium.host;
config['selenium_port'] = nightwatch_config.selenium.port;
config['desiredCapabilities'] = config['desiredCapabilities'] || {};
for(var j in nightwatch_config.common_capabilities){
config['desiredCapabilities'][j] = config['desiredCapabilities'][j] || nightwatch_config.common_capabilities[j];
}
}
module.exports = nightwatch_config;