How I can get access to API in the global command file? - javascript

I want to create a global command in the nightwatch.js framework when I do that in page object_file without global command function
navigateWithNav() {
return navigateWithNavToolbar.call(this, "#home-nav")
},
Everything works correctly. But when I trying change function in the object _file, on global command I will get undefined for this.api, how I can resolve it?
// page_oject file
navigateWithNav() {
return this.navigateWithNavToolbar("#home-nav")
},
// global command file
const { client } = require("nightwatch-cucumber")
const { MID_TIMEOUT } = global.config.timeouts
exports.command = async function navigateWithNavToolbar(selector) {
return this.api.url(async (url) => {
// if we are someplace which doesnt have the nav toolbar, then
// goto the homepage
if (!url.value.includes(client.launch_url)){
await client.url(client.launch_url)
}
await this.api.waitForElementPresent(selector, MID_TIMEOUT, false)
await this.api.click(selector)
})
}

I don't know about the syntax that the page_oject file code is in, but you want to do something like this to bind this:
navigateWithNav = () => this.navigateWithNavToolbar("#home-nav")

Related

Can I read and execute dynamic script file using webpack?

I wondering if it possible to load script dynamic by webpack.
I create a nodejs application with webpack 5 configuration and typescript. (ts-loader).
And I want the application will be able to run module-script file that I'll give by reading the config file I created.
Something like that:
app.ts:
const config = JSON.parse(fs.readFileSync('./app.config.json', 'utf-8'));
import(config.fn).then(m => { console.log({ m }); m.foo(); })
app.config.json:
{ fn: 'path/to/fn.js' }
path/to/fn.js:
exports = function foo() { console.log('in foo'); }
The problem is when I type the filename hard-coded in import it's works, but when i pass using variable it not work.
I wondering if webpack can do it? because I getting error:
uncaught (in promise) Error: Cannot find module './foo.js'
The code:
console.clear();
const foo = './foo.js';
// not works :(
import(foo).then((m) => {
console.log({ m });
});
// not works :(
// require(foo).then((m) => {
// console.log({ m });
// });
//works:
// import('./foo').then((m) => {
// console.log({ m });
// });
stackblitz

Accessing non-existent property of module.exports inside circular dependency NodeJS

Im having some issues when using module.exports inside NodeJS, and I've followed multiple guides, and im almost certain Im doing it right.
I have to scripts, main.js and event.js. Im trying to share a function from main.js to event.js, but its not working. Here is the code:
Main.js
function Scan(){
if(fs.readdirSync('./events/').length === 0){
console.log(colors.yellow('Events Folder Empty, Skipping Scan'))
} else {
var events = fs.readdirSync('./events/').filter(file => file.endsWith('.json'))
for(const file of events){
let rawdata = fs.readFileSync('./events/' + file);
let cJSON = JSON.parse(rawdata);
}
events.sort()
tevent = events[0]
StartAlerter()
}
}
module.exports = { Scan };
Event.js
const main = require('../main')
main.Scan;
This returns the error:
(node:19292) Warning: Accessing non-existent property 'Scan' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
What am I doing wrong?
I discovered that the arrangement had no effect in the error.
I simply changed the way I exported the function from the Main.js
from:
module.exports = { Scan };
to:
exports.Scan = Scan
And in Event.js, I was able to access the file like this
const main = require("./Main.js");
let result = main.Scan();
This solved my problem, I hope it helps another developer 😎
Problem solved, heres what I did differently:
module.exports = { Scan };
Is declared before the Scan function is defined, like so:
module.exports = { Scan };
function Scan(){
//Code
}
Then in event.js, I wrote
const main = require('../main')
As it is now a module, and can be used with the require() function.
Then to execute the funciton in event.js, I write
main.Scan()
To execute it.
better try :
module.exports = Scan;
I am gonna answer it using a simple example, like in this case below:
File A has 3 functions to process database activity: function
addDB, updateDB, and delData;
File B has 2 functions to process User activity on smartphone:
function addHistory, and editHistory;
Function updateDB in file A is calling function editHis in file B, and function editHistory is calling function updateDB in file A. This is what we called circular-dependency. And we need to prevent it by only giving output of state from editHistory and the rest will be processed inside file A.
//ORIGINAL FUNCTIONS which caused CIRCULAR DEPENDENCY
function updateDB() {
//process update function here
//call function in fileB
const history = require("fileB.js");
await history.editHistory(data).then((output) => {
if(output["message"] === "success"){
response = {
state: 1,
message: "success",
};
}
});
return response;
}
//THIS is the WRONG ONE
function editHistory() {
//process function to edit History here
//call function in fileA
const file = require("fileA.js");
await file.updateDB(data).then((output) => { //You should not call it here
if(output["message"] === "success") {
output = {
state: 1,
message: "success",
};
}
});
return output;
}
//==================================================//
//THE FIX
function updateDB() {
//process function here
const history = require("fileB.js");
await history.editHistory(data).then((output) => {
if(output["message"] === "success"){
await updateDB(data).then((output) => {
response = {
state: 1,
message: "success",
};
});
} else {
log("Error");
}
});
return response;
}
function editHistory() {
//process function to edit History here
// No more calling to function inside the file A
output = {
state: 1,
message: "success",
};
return output;
}

dynamically gerDownloadURL from images on firebase storage for display

I have a whole bunch of images that have been uploaded on firebase storage and I want to dynamically retrieve the images and display inside my app screen. This is what I tried so far without success:
I tried out the listFilesAndDirectories function found in the RN firebase storage usage API reference which gives me this error:
Possible Unhandled Promise Rejection (id: 1):
Error: [storage/object-not-found] No object exists at the desired reference.
NativeFirebaseError: [storage/object-not-found] No object exists at the desired reference.
function listFilesAndDirectories(reference, pageToken) {
return reference.list({pageToken}).then(result => {
// Loop over each item
result.items.forEach(ref => {
console.log(ref.fullPath);
});
if (result.nextPageToken) {
return listFilesAndDirectories(reference, result.nextPageToken);
}
return Promise.resolve();
});
}
const storageReference = storage()
.ref('gs://appname445.appspot.com/images');
listFilesAndDirectories(storageReference).then(() => {
storageReference.getDownloadURL();
console.log('Finished listing');
});
the above function prints the log statement "Finished listing' but doesn't display image
I also wrote this function which didn't work, it outputs a maxDownloadRetryError after 3 minutes
function fetchImage() {
reference.getDownloadURL().then(
function(url) {
console.log(url);
},
function(error) {
console.log(error);
},
);
}
fetchImage();
The error message is telling you there is no object at the location of the reference you're using. It's not possible to use getDownloadURL() with a path that isn't an actul file object. You can't use it on prefixes (folders).
If you're trying to get a download URL for each object that you listed with listFilesAndDirectories, you would have to call getDownloadURL() on each and every file object that it finds (not just once for the entire prefix).
It would be more like this:
function listFilesAndDirectories(reference, pageToken) {
return reference.list({pageToken}).then(result => {
result.items.forEach(ref => {
// call getDownloadURL on every object reference
ref.getDownloadURL().then(url => {
console.log(`${fullPath}: ${url}`)
})
});
if (result.nextPageToken) {
return listFilesAndDirectories(reference, result.nextPageToken);
}
return Promise.resolve();
});
}

Waiting for window / global variable to be defined in a Jest test

// index.html
// this script defines window.externalLibrary variable to use throughout app,
// it just takes a second or few to load as "window.externalLibrary" is always undefined on startup
<script src="https://www.something.com/externalLibrary.js"></script>
// package.json
jest": {
"setupFiles": [
"./src/jest/globals.js"
]
// globals.js
global.externalLibrary = window.externalLibrary;
// externalLibraryTest.js
describe('externalLibrary.js Tests', () => {
it('Please work', () => {
console.log(window.externalLibrary); //undefined
console.log(global.externalLibrary); //undefined too
});
How can I get this to work?
Usually in my app I use a function on load before using the variable:
export const initializeExternalLibrary = () => {
return new Promise((resolve) => {
if (window.singularApp) resolve(window.singularApp);
Object.defineProperty(window, 'singularApp', {
set (value) {
console.log('External Library Initialized.');
resolve(value);
}
});
});
};
but I tried using that function inside the Jest test and that didn't work as well. Does anyone have any ideas? I'm a bit desperate, thank you

Use chance plugin in cypress

Is it possible to use chance plugin with cypress.io?
https://chancejs.com
I installed plugin via npm to node_modules\chance and edited /plugins/index.js file, but still get error from cypress - Can't start, The plugins file is missing or invalid.
If using this plugin is impossible - what do you recommend to write tests basing on registration new users? I planned to use chance to generate "random: emails and passwords.
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
module.exports = on => {
on("task", {
chance: require("chance"),
});
};
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
Just install chancejs with npm:
npm install chance
Then just use it in your test for example:
/// <reference types="cypress" />
import Chance from 'Chance';
const chance = new Chance();
describe('Testing chance', function (){
const company =chance.company();
it('type company in duckduckgo.com', function () {
cy.visit('https://duckduckgo.com/')
cy.get('#search_form_input_homepage')
.should('be.visible')
.type(company)
})
})
cypress/support/index.js:
Override the default task command so that you can supply multiple arguments as you'd normally.
Cypress.Commands.overwrite('task', (origFn, name, ...args) => {
return origFn(name, args);
});
// if you're gonna use `chance` plugin a lot, you can also add a custom command
Cypress.Commands.add('chance', (...args) => {
return cy.task('chance', ...args);
});
cypress/plugins/index.js:
Wrap the tasks in function that will spread the arguments, and also handle a case when the task doesn't return anything and return null instead, so that cypress doesn't complain.
const chance = require('chance').Chance();
// lodash should be installed alongside with cypress.
// If it doesn't resolve, you'll need to install it manually
const _ = require('lodash');
on('task', _.mapValues(
{
chance ( method, ...args ) {
return chance[method](...args);
}
},
func => args => Promise.resolve( func(...args) )
// ensure we return null instead of undefined to satisfy cy.task
.then( val => val === undefined ? null : val )
));
In your spec file:
describe('test', () => {
it('test', () => {
cy.document().then( doc => {
doc.body.innerHTML = `<input class="email">`;
});
cy.task('chance', 'email', {domain: 'example.com'}).then( email => {
cy.get('.email').type(email);
});
// or use the custom `chance` command we added
cy.chance('email', {domain: 'test.com'}).then( email => {
cy.get('.email').type(email);
});
});
});

Categories

Resources