How to call a function inside webdriverio test configuration file - node.js

The url shows a WebdriverIO test runner configuration
https://webdriver.io/docs/configurationfile.html
It has got many hooks. Consider the hook onComplete I want to write a function, may be a function to create a file. In another file and call that function inside the onComplete hook. Could you please help me to achieve this.

Yes, you pretty much described the flow.
Define your function in a file and export it:
module.exports = (() => {
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* > Def: Polls the DOM until the given 'desiredState' is found.
* #param {string} desiredState ['loading', 'interactive', 'complete']
* #returns {Promise} WebdriverIO Promise
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
browser.addCommand('waitForReadyState', (desiredState) => {
let foundState;
browser.waitUntil(() => {
foundState = browser.execute('return document.readyState;');
console.log(`\n> Waiting for page to load ... | Current state: '${foundState}'`);
return foundState === desiredState;
}, browser.options.waitforTimeout, `Timeout before expected state! Found: '${foundState}' | Expected: '${desiredState}'`);
});
})();
Then, import it in the desired hook (e.g: for a custom_command, the before hook):
before: function (capabilities, specs) {
require('./test/custom_commands/waitForReadyState');
}
You can easily reproduce the model to implement logging & file manipulation functions that you need to run in the onComplete hook.

its maybe late but here is how you can do it :
/** file to keep your function should be in es5 or you have to add babel to covert it to es6 before WebdriverIO start **/
test.js
module.exports = function foo(){
console.log('here');
}
in config file //before export.config:
const foo = require('path-to-test.js');
use foo() in onComplete() hook

Related

gRPC: 14 UNAVAILABLE: failed to connect to all addresses

grpc fails to connect even when I set my jest test() async function to a 100000ms cap before it times out.
// terminal, after running jest --watch
● creates new record
14 UNAVAILABLE: failed to connect to all addresses
at Object.<anonymous>.exports.createStatusError (node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (node_modules/grpc/src/client_interceptors.js:1209:28)
at InterceptingListener.Object.<anonymous>.InterceptingListener._callNext (node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.Object.<anonymous>.InterceptingListener.onReceiveStatus (node_modules/grpc/src/client_interceptors.js:618:8)
at callback (node_modules/grpc/src/client_interceptors.js:847:24)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 skipped, 2 total
Snapshots: 0 total
Time: 106.03s, estimated 116s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
owner#G700:~/PhpstormProjects/shopify/bu
FAIL functions/src/classes/__tests__/FirestoreConnection.test.ts (108.991s)
✕ creates new record (100029ms)
○ skipped
● creates new record
: Timeout - Async callback was not invoked within the 100000ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 100000ms timeout specified by jest.setTimeout.Error:
51 |
52 |
> 53 | test("creates new record", async () => {
| ^
54 | const addedDocument = await db
55 | .createNew(RecordTypes.globalRule, {
56 | storeId : "dummyStoreId"
at new Spec (node_modules/jest-jasmine2/build/jasmine/Spec.js:116:22)
at Object.<anonymous> (functions/src/classes/__tests__/FirestoreConnection.test.ts:53:1)
● creates new record
14 UNAVAILABLE: failed to connect to all addresses
at Object.<anonymous>.exports.createStatusError (node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (node_modules/grpc/src/client_interceptors.js:1209:28)
at InterceptingListener.Object.<anonymous>.InterceptingListener._callNext (node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.Object.<anonymous>.InterceptingListener.onReceiveStatus (node_modules/grpc/src/client_interceptors.js:618:8)
at callback (node_modules/grpc/src/client_interceptors.js:847:24)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 skipped, 2 total
Snapshots: 0 total
Time: 111.16s
Ran all test suites related to changed files.
// FirebaseConnection.ts, inside the class
protected async addDocument(collectionName: string, documentData: object): Promise<firestore.DocumentSnapshot|null> {
try {
const newlyAddedDocument = await this.database
.collection(collectionName)
.add(documentData);
return await newlyAddedDocument.get();
}
catch (e) {
console.log(e, `=====error=====`);
return null;
}
}
// --------------- Public Methods
public async createNew(type: RecordTypes, documentData: object): Promise<firestore.DocumentSnapshot|null> {
this.verifySchemaIsCorrect(type, documentData);
const collectionName = this.getCollectionName(type);
return await this.addDocument(collectionName, documentData);
}
// FirebaseConnection.test.ts
import * as firebaseTesting from "#firebase/testing";
import {RecordTypes} from "../../../../shared";
import FirestoreConnection from "../FirestoreConnection";
/* * * * * * * * * * * * * * * * * * * * *
Setup
* * * * * * * * * * * * * * * * * * * * */
const createTestDatabase = (credentials): any => {
return firebaseTesting
.initializeTestApp({
projectId: 'testProject',
auth: credentials
})
.firestore();
};
const nullAllApps = firebaseTesting
.apps().map(app => app.delete());
const db = new FirestoreConnection('testShopDomain', createTestDatabase(null));
/* * * * * * * * * * * * * * * * * * * * *
Tests
* * * * * * * * * * * * * * * * * * * * */
test("creates new record", async () => {
const addedDocument = await db
.createNew(RecordTypes.globalRule, {
storeId : "dummyStoreId"
, globalPercent : 40
});
expect(addedDocument).toEqual({
storeId : "dummyStoreId"
, globalPercent : 40
, badProp : 0
});
}, 100000);
Is anyone able to tell why this is happening? Looking at the documentation this appears to be a lower level library: https://grpc.github.io/grpc/node/
Update
After it was suggested that the server/emulator was not found by gRPC, I ran firebase serve --only functions,firestore. Terminal showed emulators running on different ports for both services. Rerunning jest --watch now produces a slightly different error:
2 UNKNOWN:
at Object.<anonymous>.exports.createStatusError (node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (node_modules/grpc/src/client_interceptors.js:1209:28)
at InterceptingListener.Object.<anonymous>.InterceptingListener._callNext (node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.Object.<anonymous>.InterceptingListener.onReceiveStatus (node_modules/grpc/src/client_interceptors.js:618:8)
at callback (node_modules/grpc/src/client_interceptors.js:847:24)
That gRPC error means that no server is running at the address you are trying to connect to, or a connection to that server cannot be established for some reason. If you are trying to connect to a local Firestore emulator, you should verify that it is running and that you can connect to it outside of a test.
Firebase functions was hiding the underlying error. This was solved in 2 steps:
enabling logging in the the admin SDK with firestore.setLogFunction()
projectId testProject was invalid. Changing the projectId to testproject with all lowercase letters cleared this error.
unset your proxy
unset https_proxy;unset http_proxy

Is this a good way to use module.exports?

I'm curious if the following way is a good approach to use the module.exports functionality.
And if so, what is the best way to add commentary to the code so JSDoc3 can handle it correctly.
I'm currently exporting functions as follows:
Let say we have a module1.js with the following code:
/**
* Module1 module
* #module Module1
*/
module.exports = {
// no jsdoc commentary on purpose
function1: function(param1) {
function1(param1);
},
/**
* Function2
*
* Function that will do something
* #returns {boolean} return value
*/
function2: function() {
return function2();
},
}
/**
* Function1
*
* Function that will do something
* #param param1 {string} First parameter
*/
function function1(param1){
console.log(param1);
// do something
}
/**
* Function2
*
* Function that will do something
* #returns {boolean} return value
*/
function function2() {
// do something
return true;
}
and in module2.js
/**
* Module2 module
* #module Module2
*/
// Requirements
module1 = require('./module1.js');
/**
* myFunction
*
* Function that will do something
*/
function myFunction() {
const param1 = "Parameter1";
module1.function1(param1); // call function1 from module 1
}
// just an example of function2 in module2.js
const myBoolean = module1.function2();
// more stuf
The problem with this approach is that function1 will now only be described in the jsdoc file as 'inner'(local) function, and function2will now be duplicated in the generated jsdoc file one as 'static' (the exported) and one as 'inner' (local) function.
Why this approach:
The reason for this approach is: I want no functionality in exported functions. I want other developers to easily see what functions are exported. So the real functionality is put in the local function below the exports.
The question:
Is this a correct way to use the module exports?
And is this a correct way to commentary the code? (for JSDoc3)
ps: im pretty new with NodeJS

using Underscore in SuiteScript 2

I am writing a script in SS2 and I ran into doc that stated that I should do the below. I have done this and the paths are right but it doesn't seem to see underscore as it comes back as undefined, when trying to use it. Any help with this would be great, thanks
define( [ 'N/email'
, 'N/runtime'
, 'N/search'
, '/SuiteScripts/af_scripts/underscore.js#1.8.3/underscore'
],
function( email, runtime, search, _) {
function onRequest( context ) {
var request = context.request;
var us = _;
}
return {
onRequest: onRequest
};
} );
In my case, I used lodash to add HTML file contents to my suitelet
When you define your modules you can insert the lodash library at the end just like
define(['N/file', 'N/record', 'N/search', 'N/ui/serverWidget','./lodash.js'],
but at function you should not insert anything just like
function(file, record, search, serverWidget) {
Here is a sample of code to load a file and get his contents using lodash
/**
* #NApiVersion 2.x
* #NScriptType Suitelet
* #NModuleScope SameAccount
*/
define(['N/file', 'N/record', 'N/search', 'N/ui/serverWidget','./lodash.js'],
/**
* #param {file} file
* #param {record} record
* #param {search} search
* #param {serverWidget} serverWidget
*/
function(file, record, search, serverWidget) {
/**
* Definition of the Suitelet script trigger point.
*
* #param {Object} context
* #param {ServerRequest} context.request - Encapsulation of the incoming request
* #param {ServerResponse} context.response - Encapsulation of the Suitelet response
* #Since 2015.2
*/
function onRequest(context) {
var templateFile = file.load({
id: 'filePath'
});
//for example.
var compiled = _.template(templateFile.getContents());
}
return {
onRequest: onRequest
};
});
Note:
I inserted the file to the same location as my suitelet in the file cabinet that why I used this relative path (./lodash.js), use the full path if the suitelet is not at the same file.
I have not see how to do it that way. But the way I found that works is like this:
/**
* #NApiVersion 2.x
* #NScriptType usereventscript
*/
require.config({
paths:{
"coolthing":"/SuiteScripts/myFavoriteJsLibrary"
}
});
define(['coolthing'],function (coolthing){
return {
beforeLoad:function beforeLoad(ctx){
coolthing.times(2,function(){
log.debug('log','log');
});
}
};
});
I put underscore-min.js in the same folder as my Suitescripts.
Then I created a config file named 'underscoreConfig.json' in the same folder with the following contents:
{
"paths":{
"underscore": "./underscore-min"
}
}
Then I add the following to my scripts:
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
* #NModuleScope SameAccount
* #NAmdConfig ./underscoreConfig.json
*/
define(['underscore', 'N/record', 'N/search'],
/**
* #param {underscore} underscore
* #param {record} record
* #param {search} search
*/
function(_, record, search) {
Now I am able to call Underscore functions in my scripts.
E.g.
var segmentObj = _.findWhere(segmentFields, {id: segmentId});

JSDoc when exporting a function constructor in node.js

I'm just starting to add some JSDoc comments to a code base I've been working on, for the most part this seems to work, but there's one area that's causing me some difficulties.
If I describe a function constructor in a file, and then export it on the module.exports, when I later require() that module, I get no documentation on the type and the inferred type is set as |exports. Clicking on the doesn't take me anywhere. I currently have:
/**
* Creates an instance of the StatusCodeErrorItem
* #param {string} message The message for this error
* #param {object} params The parameters that caused this error to occur
* #alias lib/common/StatusCodeErrorItem.StatusCodeErrorItem
* #returns {StatusCodeErrorItem}
* #constructor
*/
function StatusCodeErrorItem(message, params) {
this.message = message;
this.params = params;
}
/**
* Holds information about an error
* #module lib/common/StatusCodeErrorItem
*/
module.exports = StatusCodeErrorItem;
and in the file that uses it:
var StatusCodeErrorItem = require('./StatusCodeErrorItem');
I'd thought at this point that'd I'd be able to press f1 to bring up the inline documentation, and see the definition of StatusCodeErrorItem as described in that file. But instead I only see: inferred type StatusCodeErrorItem|exports
Webstorm 9
Node.js 0.10.36 (I know both are old)
Any thoughts on what I'm doing wrong? Is what I'm after even possible? Are my versions simply too old?
Cheers
Webstorm 2016.1.1 solves the issue. The below JSDoc gets correctly assigned to types pulled in by require. I'll now be pestering people to get me a new license.
'use strict';
/**
* Creates an instance of the StatusCodeErrorItem
* #memberof common
* #constructor
* #classdesc A class for holding information about an error. The params object allows the tracking of the function
* parameters that caused the error, but should not be used to store large objects.
* #description Creates an instance of the StatusCodeErrorItem with the given message and optional params object
* #param {string} message The message for this error
* #param {object} [params] The parameters that caused this error to occur
* #returns {StatusCodeErrorItem}
* #see {#link module:lib/common/StatusCodeError.StatusCodeError|StatusCodeError}
*/
function StatusCodeErrorItem(message, params) {
this.message = message;
this.params = params;
}
/**
* Surfaces a class that holds information about an error
* #module lib/common/StatusCodeErrorItem
*/
module.exports = StatusCodeErrorItem;

Node.js : how to pass parameter's value from terminal to JS script

Given a jsdom based svgcreator.node.js script file :
var jsdom = require('jsdom');
jsdom.env(
"<html><body></body></html>", // CREATE DOM HOOK
[ 'http://d3js.org/d3.v3.min.js', // JS DEPENDENCIES online ...
'js/d3.v3.min.js' ], // ... & offline
// D3JS CODE * * * * * * * * * * * * * * * * * * * * * * * *
function (err, window) {
var svg = window.d3.select("body")
.append("svg")
.attr("width", 100)
.attr("height", 100);
svg.append("rect")
.attr("id", "rect1")
.attr("x", 10)
.attr("y", 10)
.attr("width", 80)
.attr("height", 80)
.style("fill", "green");
// END svg design
//PRINTING OUT SELECTION
console.log(window.d3.select("body").html());
}
// END (D3JS) * * * * * * * * * * * * * * * * * * * * * * * *
);
Given I use NodeJS terminal command to run it and generate a output.svg file :
node svgcreator.node.js > output.svg # nodeJS + script command
How to pass a parameter's value from the terminal to NodeJS ?
Dependencies for tests:
svgcreator.node.js github repository: git clone 'git#github.com:hugolpz/svgcreator.node.js.git'
jsdom required, use : sudo npm install -g jsdom (global).
Solution used (#Matt_Harrison): we rely on process.env.myVar
svgcreator.node.js JS code :
var jsdom = require('jsdom');
jsdom.env(
"<html><body></body></html>", // CREATE DOM HOOK:
[ 'http://d3js.org/d3.v3.min.js', // JS DEPENDENCIES online ...
'js/d3.v3.min.js' ], // ... & offline
// D3JS CODE * * * * * * * * * * * * * * * * * * * * * * * *
function (err, window) {
var color = process.env.COLOR; // <<################# IMPORTANT !!
var svg = window.d3.select("body")
.append("svg")
.attr("width", 100)
.attr("height", 100);
svg.append("rect")
.attr("id", "rect1")
.attr("x", 10)
.attr("y", 10)
.attr("width", 80)
.attr("height", 80)
.style("fill", color); // <<################# IMPORTANT !!
// END svg design
//PRINTING OUT SELECTION
console.log(window.d3.select("body").html());
}
// END (D3JS) * * * * * * * * * * * * * * * * * * * * * * * *
);
Terminal NodeJS command :
COLOR=#66AAFF node svgcreator.node.js > out.svg # <<############# IMPORTANT !! setting the value.
+1 #Matt_Harrison answer and the question appreciated !
In your terminal, you can use environment variables:
$ COLOR=#FFFFFF node jsdom.node.js
In your JS, do:
var color = process.env.COLOR;
Or you could add extra arguments to the command:
$ node jsdom.node.js '#FFFFFF'
and in your JS :
var color = process.argv[2];
If you want to use a library; I would advise looking into the Minimist library, or Commander for a more fully-featured solution.

Resources