I have a cucumber-js and playwright project.
I want to access worldParameters key and value which is defined in cucumber.js file as follows:
worldParameters: {
baseUrl: 'https://www.google.com'
}
How can I access baseUrl and use it in my steps.js file?
As per the documentation here, the config file should have a format as below.
module.exports = {
default: {
worldParameters: {
appUrl: 'http://localhost:3000/',
},
}
}
Then as per tests here, you should be able to access the parameters by using this.parameters.appUrl in your code.
Define a file named 'cucumber.js' in your root directory and define your code like below:
let worldOptions = {
browserName: browser,
environment: env,
partition: partition,
project: project,
timestamp: global.timestamp,
reportDir: global.reportDir,
headless: headless,
slowMotion: slowMotion,
partition: partition,
target: target,
browserVersion: browserVersion,
os: os,
osVersion: osVersion,
device: device
};
console.log('cucumber js world options: ' + JSON.stringify(worldOptions));
let common = [
'--require ./support/', // Load hooks
'./**/tests/features/', // Specify our feature files
'--require-module ts-node/register', // Load TypeScript module
'--require ./**/tests/steps/**/', // Load step definitions
'-f #cucumber/pretty-formatter',
// '--format json:reports/' + project + '/'+global.timestamp +'/cucumber_report.json',
'--format json:' + global.reportDir + 'cucumber_report.json',
'--parallel ' + (parallel !== undefined ? parallel : 1) + ' --world-parameters ' + JSON.stringify(worldOptions),
'--publish-quiet'
].join(' ');
Now, cucumber 'this' object holds your world params data and read them usin 'this.World.browserName'
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 months ago.
Improve this question
I was wondering if any of the following is possible to implement using vite build tool.
Consider that I have files in directory matching the pattern: /content/file-[id].md
/content/file-1.md
/content/file-2.md
Every time I serve the SPA app with vite command or building an app with vite build I would like to
grab all the files /content/file-[id].md and transform them into /content_parsed/file-[id].html
/content_parsed/file-1.html
/content_parsed/file-2.html
grab all files /content_parsed/file-[id].html and generated a manifest file /files.manifest containing all paths of files.
/files.manifest
This has to be done automatically in watch mode, when the app is served (vite command) and on-demand when app is built (vite build).
I am pretty sure this is possible to be done with a manual script that I could run with node ./prepareFiles.js && vite, but in this case I am loosing the reactivity when serving the app (i.e. the watch-mode).. so a direct integration into vite would be a step-up in terms of usability and testability (I think).
Given the above use-case - can vite do this? Do I need to write a custom plugin for that? or do you recommend creating a separate watch-files/watch-directory script for that?
I have been able to partially accomplish what I wanted. The only issue right now is the hot reload functionality.
if you import the manifest as
import doc from 'docs.json'
then the page will be auto-reloaded if the module is updated.
On the other had, if you want to dynamically load the data with fetch API:
fetch('docs.json')
.then(r => r.json())
.then(json => {
//...
})
Then the only way to refresh page contents is by manual refresh.. If anyone has a suggestion how to trigger reload from within vite plugin context please let me know.. I will update the post once I figure it out.
Also I should mention that I have decided not to pre-generate the html pages so this functionality is missing from the plugin but could easily be extended with marked, markdown-it remarked etc..
Plugin: generateFilesManifest.ts
import {PluginOption} from "vite";
import fs from "fs";
import path from 'path'
const matter = require('front-matter');
const chokidar = require('chokidar');
import {FSWatcher} from "chokidar";
export type GenerateFilesManifestConfigType = {
watchDirectory: string,
output: string
}
export type MatterOutputType<T> = {
attributes: T,
body: string,
bodyBegin: number,
frontmatter: string,
path: string,
filename: string,
filenameNoExt: string,
}
export default function generateFilesManifest(userConfig: GenerateFilesManifestConfigType): PluginOption {
let config: GenerateFilesManifestConfigType = userConfig
let rootDir: string
let publicDir: string
let command: string
function generateManifest() {
const watchDirFullPath = path.join(rootDir, config.watchDirectory)
const files = fs.readdirSync(watchDirFullPath);
// regenerate manifest
const manifest: any[] = []
files.forEach(fileName => {
const fileFullPath = path.join(watchDirFullPath, fileName)
// get front matter data
const fileContents = fs.readFileSync(fileFullPath).toString()
//const frontMatter = matter.read(fileFullPath)
const frontMatter = matter(fileContents)
//console.log(frontMatter);
// get file path relative to public directory
//const basename = path.basename(__dirname)
const fileRelativePath = path.relative(publicDir, fileFullPath);
const fileInfo = JSON.parse(JSON.stringify(frontMatter)) as MatterOutputType<any>;
fileInfo.path = fileRelativePath
fileInfo.filename = fileName
fileInfo.filenameNoExt = fileName.substring(0, fileName.lastIndexOf('.'));
fileInfo.frontmatter = ''
manifest.push(fileInfo);
});
const outputString = JSON.stringify(manifest, null, 2);
fs.writeFileSync(config.output, outputString, {encoding: 'utf8', flag: 'w'})
console.log('Auto-generated file updated')
}
let watcher: FSWatcher | undefined = undefined;
return {
name: 'generate-files-manifest',
configResolved(resolvedConfig) {
publicDir = resolvedConfig.publicDir
rootDir = resolvedConfig.root
command = resolvedConfig.command
},
buildStart(options: NormalizedInputOptions) {
generateManifest();
if (command === 'serve') {
const watchDirFullPath = path.join(rootDir, config.watchDirectory)
watcher = chokidar.watch(watchDirFullPath,
{
ignoreInitial: true
}
);
watcher
.on('add', function (path) {
//console.log('File', path, 'has been added');
generateManifest();
})
.on('change', function (path) {
//console.log('File', path, 'has been changed');
generateManifest();
})
.on('unlink', function (path) {
//console.log('File', path, 'has been removed');
generateManifest();
})
.on('error', function (error) {
console.error('Error happened', error);
})
}
},
buildEnd(err?: Error) {
console.log('build end')
watcher?.close();
}
}
}
in vite.config.ts, use as
export default defineConfig({
plugins: [
vue(),
generateFilesManifest({
watchDirectory: '/public/docs',
output: './public/docs.json'
})
]
})
you might want to cover such as edge-cases as watch directory not present etc...
front-matter is the library that parses markdown files. Alternative is gray-matter
EDIT: thanks to #flydev response I was able to dig some more examples on page reload functionality. Here's the experimental functionality that you could add:
function generateManifest() {
// ...
ws?.send({type: 'full-reload', path: '*'})
}
let ws: WebSocketServer | undefined = undefined;
return {
name: 'generate-files-manifest',
//...
configureServer(server: ViteDevServer) {
ws = server.ws
}
// ...
}
Currently the whole page is reloaded regardless of the path.. Not sure if there is a way to make it smart enough to just reload pages that loaded the manifest file.. I guess it's currently limited by my own ability to write a better code :)
We have protractor-cucumber framework as e2e test. Till now we use the conf file with statically mentioning the environment details inside the conf json. I would like to pass user defined arguments with the protractor_conf file something like below.
protractor protractor_conf.js -DbrowserName=chrome -DexecPlatform=(native/sauce)
and would like to fetch this argument inside the conf.js and substitute under the capabilities section. I could not get proper details on net, so any help/suggestions would be appreciated.
You can add Parameters in your conf.js file then pass the arugs from the command line.
Here is an example.
// The params object will be passed directly to the Protractor instance,
// and can be accessed from your test as browser.params. It is an arbitrary
// object and can contain anything you may need in your test.
// This can be changed via the command line as:
// --params.environment.Browser "Firefox"
params: {
environment: {
browser: 'Chrome',
execPlatform: 'sauce',
password: 'default'
}
}
Now from we can pass the arugs from command line
protractor conf.js --parameters.environment.browser= Firefox --parameters.environment.execPlatform=sauce --parameters.environment.password=password123
Next, you can also refer these parameters in your spec file.
describe('describe some test', function() {
it('describe some step', function() {
$('.password').sendKeys(browser.params.login.password);
});
});
There are multiple advantages to having a parameter setup.
If we know we are going to be using the same values in multiple spec files (i.e login email and password), parameters are great for removing unnecessary repetition.
Being able to change parameter values at runtime makes it easier to run the same tests with different data.
Increases security – Having passwords hardcoded in your spec files is not a great approach. Parameters give you the ability to keep them out and instead provide them at runtime.
You can use process api to parse the arguments in cmd line.
// protractor conf.js
var readParamsFromCli = function() {
var paramsPair = process.argv.slice(3).filter(function(it){
return it.startsWith('-D');
});
var params = {};
paramsPair.forEach(function(pair){
var parts = pair.split('=');
var name = parts[0].trim().replace('-D', '');
var value = parts[1] && parts[1].trim() || true;
params[name] = value;
});
return params;
};
var params = readParamsFromCli();
var capbilities = {
browserName: params.browserName || 'chrome',
platform: params.execPlatform
};
exports.config = {
...
capbilities: capbilities
};
Then you can run case as following:
protractor protractor_conf.js -DbrowserName=chrome -DexecPlatform=native
You could split the configuration up into multiple config files. For example protractor-chrome.conf.js:
const baseConf = require('./protractor.conf').config;
exports.config = Object.assign({
capabilities: {
browserName: 'chrome'
}
}, baseConf);
This will be similar to 2nd example but uses the config file directly.
const args = require('minimist')(process.argv.slice(2));
exports.config = {
//your config stuff
baseUrl: args.Url ? args.URL : <your default>,
capabilities: {
'browserName': 'chrome',
chromeOptions: {
args: [args.Options]
},
}
}
Then in your package.json script like this:
"e2e": "protractor protractor.conf.js --Url=http://test.com" --Options=--headless
Hi I have the following simple nightwatch demo script which is looping when ran with multiple browser environment, but which works fine if I run the test with single browser.
Following arguments loops the test:
var argv = {
test: 'nightwatchgoogletest.js',
config: 'nightwatch.json',
reporter: 'junit',
env : 'default,chrome'
};
Following works fine:
var argv = {
test: 'nightwatchgoogletest.js',
config: 'nightwatch.json',
reporter: 'junit',
env : 'chrome' (or default or any single browser)
};
Following is my code, please let me know what am I doing wrong here.
nightwatchgoogletest.js :
module.exports = {
'Demo test Google' : function (client) {
client
.url('http://google.no')
.pause(1000);
// expect element to be present in 1000ms
client.expect.element('body').to.be.present.before(1000);
// expect element <#lst-ib> to have css property 'display'
client.expect.element('#lst-ib').to.have.css('display');
// expect element to have attribute 'class' which contains text 'vasq'
client.expect.element('body').to.have.attribute('class').which.contains('vasq');
// expect element <#lst-ib> to be an input tag
client.expect.element('#lst-ib').to.be.an('input');
// expect element <#lst-ib> to be visible
client.expect.element('#lst-ib').to.be.visible;
client.end();
}
};
And have written the following node script to call above test:
var Nightwatch = require('nightwatch');
function proceess_test() {
try {
var argv = {
test: 'nightwatchgoogletest.js',
config: 'nightwatch.json',
reporter: 'junit',
env : 'default,chrome'
};
console.log("\n>> Initiating Tests for ...",process.env.__NIGHTWATCH_ENV_KEY);
var settings = {};
var done = function() {console.log("done")};
Nightwatch.runner(argv, done, settings);
done();
} catch (error) {
console.log('Exception: ' + error.message);
}
}
proceess_test();
With the following nightwatch configuration:
http://www.jsoneditoronline.org/?id=7e8e1616d595417ceeafaccc6358b33d
But when I run the test, it going in an infinite testing loop as follows:
Background
I've been using grunt.js with a hogan.js task to build the static HTML for our internal docs. I'm learning JavaScript as I go, but I've gotten the task to work well enough for layouts and pages, but it would really help our workflow to have the hogan task render mustache partials to HTML, as in the example in this gist: https://gist.github.com/4132781
Current Setup and what I want to accomplish
All of our mustache partials are in a folder called "partials". Ideally when the grunt build is run, the hogan task will grab any partials from the partials folder and insert them into the HTML wherever they are referenced (also, shown in gist).
What I DON'T want
I don't want to have to define each partial in the task or task configuration. This won't work, we have ~200 partials and growing, so we need to have the task scan a folder and grab partials based on either file name or something. I also don't want to use a different language or build tool. We've used Jade, some markdown-based docs builders, a number of others. If we can just get partials to render as described we'll be in great shape!
Is it possible to accomplish this? Thanks in advance for any feedback
I was looking at your code in the gist and some of the options don't match with the filenames you're referencing.
Here is my stab at updating the code you provided to allow rendering partials:
grunt.js
The src is the list of pages you're building that might contain partials
In this case, components.mustache would be located at 'docs/components/templates/pages/components.mustache'
Updating the layout option to layout.mustache which is used for all the pages (including components.mustache)
Adding a paths object to options which has a path to the partials folder. All these partials will be read and compiled and stored in options.partials for later use in the grunt task.
module.exports = function(grunt) {
'use strict';
// Project configuration
grunt.initConfig({
pkg: '<json:package.json>',
meta: {
banner:
'/**\n' +
'* <%= pkg.name %>.js v<%= pkg.version %> by #fat & #mdo\n' +
'* Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
'* http://www.apache.org/licenses/LICENSE-2.0.txt\n' +
'*/'
},
// Build HTML docs from .mustache files
hogan: {
production: {
src: 'docs/components/templates/pages/*.mustache',
dest: 'docs/components/FILE.html',
options: {
title: 'Sellside',
url: 'docs',
setAccount: 'NA',
setSiteId: 'NA',
layout: 'docs/components/templates/layout.mustache',
dev: true,
docs: true,
app: false,
website: false,
paths: {
partials: 'docs/components/templates/partials/*.mustache'
}
}
}
}
});
// Load npm tasks.
grunt.loadNpmTasks('grunt-contrib');
// Load local tasks.
grunt.loadTasks('tasks');
grunt.registerTask('default', 'hogan');
};
hogan.js
Updating this task to read in all the partials and compile them.
The helper is being updated to add the 'body' partial (which is the compiled page) to the options.partials list.
The options.partials is then passed into the hogan.render method so all the partials are available to all the pages.
/*
* Build HTML from mustache files
* https://github.com/sellside/ui/grunt.js
*
* Copyright (c) 2012 Sellside
* Authored by Jon Schlinkert
*/
module.exports = function(grunt) {
// Grunt utilities.
var task = grunt.task,
file = grunt.file,
utils = grunt.util,
log = grunt.log,
verbose = grunt.verbose,
fail = grunt.fail,
option = grunt.option,
config = grunt.config,
template = grunt.template,
_ = utils._
// external dependencies
var fs = require('fs'),
hogan = require('hogan');
// ==========================================================================
// TASKS
// ==========================================================================
grunt.registerMultiTask('hogan', 'Compile mustache files to HTML with hogan.js', function() {
var data = this.data,
src = grunt.file.expandFiles(this.file.src),
dest = grunt.template.process(data.dest),
// Options are set in gruntfile
defaults = {
production: false,
docs: false,
title: 'Sellside',
setAccount: 'NA',
setSiteId: 'NA',
layout: 'docs/templates/layout.mustache',
paths: {},
partials: {}
},
options = _.extend(defaults, this.data.options || {})
!src && grunt.warn('Missing src property.')
if(!src) return false
!dest && grunt.warn('Missing dest property')
if(!dest) return false
var done = this.async()
var srcFiles = file.expandFiles(src)
if(options.paths.partials) {
var partials = grunt.file.expandFiles(options.paths.partials);
log.writeln('Compiling Partials...');
partials.forEach(function(filepath) {
var filename = _.first(filepath.match(/[^\\\/:*?"<>|\r\n]+$/i)).replace(/\.mustache$/, '');
log.writeln(filename.magenta);
var partial = fs.readFileSync(filepath, 'utf8');
options.partials[filename] = hogan.compile(partial);
});
log.writeln();
}
try {
options.layout = fs.readFileSync(options.layout, 'utf8')
options.layout = hogan.compile(options.layout, {
sectionTags: [{
o: '_i',
c: 'i'
}]
})
} catch(err) {
grunt.warn(err) && done(false)
return
}
srcFiles.forEach(function(filepath) {
var filename = _.first(filepath.match(/[^\\\/:*?"<>|\r\n]+$/i)).replace(/\.mustache$/, '')
grunt.helper('hogan', filepath, filename, options, function(err, result) {
err && grunt.warn(err) && done(false)
if(err) return
file.write(dest.replace('FILE', filename), result)
})
})
done()
})
// ==========================================================================
// HELPERS
// ==========================================================================
grunt.registerHelper('hogan', function(src, filename, options, callback) {
log.writeln('Compiling ' + filename.magenta);
var page = fs.readFileSync(src, 'utf8'),
html = null,
layout = options.layout,
context = {};
context[filename] = 'active';
context._i = true;
context.production = options.production;
context.docs = options.docs;
context.setAccount = options.setAccount;
context.setSiteId = options.setSiteId;
var title = _.template("<%= page == 'Index' ? site : page + ' · ' + site %>")
context.title = title({
page: _(filename).humanize().replace('css', 'CSS'),
site: options.title
})
try {
page = hogan.compile(page, {
sectionTags: [{
o: '_i',
c: 'i'
}]
})
options.partials.body = page;
page = layout.render(context, options.partials)
callback(null, page)
} catch(err) {
callback(err)
return
}
})
};
One thing to note, if you're going to pass data into the partials, you'll need to add that to the context object in the file layout.render call.
Hope this all make sense and helps you out.
I've been trying to use requirejs and js-test-driver along side, and I can't seen to get it working.
I have a minimal configuration like this at the root :
server: http://localhost:9876
load:
- src/main/resources/web/resources/vendor/requirejs/require.js
test:
- src/test/js/*.js
A "src/main/js/greeter.js" file defines a silly module :
define(function(require) {
myapp = {};
myapp.Greeter = function() {
};
myapp.Greeter.prototype.greet = function(name) {
return "Hello " + name + "!";
};
return myapp;
});
And I'm trying to let require load the greeter module in a "src/test/js/greeterTest.js" :
GreeterTest = TestCase("GreeterTest");
require.configure({ ???? });
require([ "src/main/js/greeter" ], function(myapp) {
GreeterTest.prototype.testGreet = function() {
var greeter = new myapp.Greeter();
assertEquals("Hello World!", greeter.greet("World"));
};
});
Whenever I run this, I get an error because myapp is not defined when creating the Greeter.
So is there a way I can configure require in this case ? I tried :
setting the baseUrl property to something like file:///.... to give the location of the file
using the gateway configuration to proxy the requests that requirejs might do (although I have no server running to serve the js files, so again I had to use file:///)
Is there something else I should try ?
Thanks
Turns out it is possible, but poorly documented :
js-test-driver has a 'serve' settings that lets the test server responds static files
once served, the files are available at localhost:42442/test/xxxx (The 'test' prefix is never mentionned, except in a comment low in the doc page).
So this works :
server: http://localhost:9876
load:
- src/main/resources/web/resources/vendor/requirejs/require.js
test:
- src/test/js/*.js
serve:
- src/main/js/*.js
And requirejs has to be configured like this :
require({
baseUrl : "/test/src/main/js"
}, [ "greeter" ], function(myapp) {
GreeterTest = TestCase("GreeterTest");
GreeterTest.prototype.testGreet = function() {
var greeter = new myapp.Greeter();
assertEquals("Hello World!", greeter.greet("World"));
};
});
Notice :
the / before the tests
the fact that you have to reuse the "src/main/js" part ; I guess that is linked to the fact that my jsTestDriver config is located at the same level as the "src" folder, and
it might needs some tweaking if placed otherwise.