Cypress task with xlsx leads to f.slice when using - cypress

I am getting this error when trying to access a cypress task masking the "xlsx": "^0.18.5"
for reading excel files.
From Node.js Internals:
TypeError: f.slice is not a function
at firstbyte (/local0/biologics/gitcheckouts/new-ui-e2e/node_modules/xlsx/xlsx.js:23626:38)
at readSync (/local0/biologics/gitcheckouts/new-ui-e2e/node_modules/xlsx/xlsx.js:23706:14)...
My task looks like this cypress.config.ts
on('task', {
readXlsx: readXlsx.read,
});
If I add brackets after the read:-> readXlsx: readXlsx.read() it already fails when starting cypress with the same error message:
Does anybody know what to do? (Cypress version 12.5.0)
Add on:
import * as fs from 'fs';
private validateExcelFile(countedItems: number, correction: number) {
cy.get('#LASTDOWNLOADEDFILE').then((name) => {
const fileName = name as unknown as string;
cy.log(`Validating excel file: ${fileName}`);
const buffer = fs.readFileSync(fileName);
cy.task('readXlsx', { buffer }).then((rows) => {
const rdw = (rows as string).length;
expect(rdw).to.be.equal(countedItems - correction);
});
});
}

I cannot tell what code, if any, precedes the task. The message seems to indicate a buffer issue, here is my working code you can compare to your own.
Otherwise, suspect the file itself.
import { readFileSync } from "fs";
import { read } from "xlsx/xlsx.mjs";
function read(name) {
const buffer = readFileSync(name);
const workbook = read(buffer);
return workbook
}
...
on('task', {
readXlsx: (name) => read(name)
...

Related

Visual testing with Nightwatch-vrt: Test passed, element is captures, but no picture is seen

I installed nightwatch-vrt locally in my project. Npm showed me multiple vulnerities which I ignored.
I created a nightwatch.vrt.conf.js with the following content:
const path = require('path');
const baseConfig = require('./nightwatch.conf.js');
const config = {
...baseConfig,
custom_commands_path: ['node_modules/nightwatch-vrt/commands'],
custom_assertions_path: ['node_modules/nightwatch-vrt/assertions']
};
function generateScreenshotFilePath(nightwatchClient, basePath, fileName) {
const moduleName = nightwatchClient.currentTest.module,
testName = nightwatchClient.currentTest.name;
return path.join(process.cwd(), basePath, moduleName, testName, fileName);
};
config.test_settings.default.globals = {
"visual_regression_settings": {
"generate_screenshot_path": generateScreenshotFilePath,
"latest_screenshots_path": "vrt/latest",
"latest_suffix": "",
"baseline_screenshots_path": "vrt/baseline",
"baseline_suffix": "",
"diff_screenshots_path": "vrt/diff",
"diff_suffix": "",
"threshold": 0.5,
"prompt": false,
"always_save_diff_screenshot": true
}
}
module.exports = config;
My test (simple, just to see if it works) looks like:
module.exports = {
tags: ['x'],
'visual testing':function(browser) {
browser
.url('https://www.kraeuter-und-duftpflanzen.de')
.maximizeWindow()
.assert.visible('.header-main')
.pause(1000)
.assert.screenshotIdenticalToBaseline('.header-main')
//.saveScreenshot('./tests_output/image.png')
.end();
}
}
Now the test passes, no assertions failed, a folder is created and the file is correctly named placed there, but I can only see an field with checkerboard pattern (like the transparent background in vector graphics) in the size of the captured element.
Before the test report messages like this are shown:
[32644:26476:0414/082519.134:ERROR:device_event_log_impl.cc(214)] [08:25:19.134]
USB: usb_device_handle_win.cc:1049 Failed to read descriptor from node connection:
Ein an das System angeschlossenes Gerõt funktioniert nicht. (0x1F)
If I let Nightwatch take a screenshot itself, it is displayed correctly.
Does anyone know, where's the mistake?
it seems that this package is broken and not updated for a very very long time. I advise you to update to this one https://www.npmjs.com/package/#bbc/nightwatch-vrt

Cypress: The 'task' event has not been registered in the plugins file. You must register it before using cy.task()

I am writing the end-to-end tests using Cypress for my web application. In my tests, I am trying to create a task, https://docs.cypress.io/api/commands/task. But it is throwing an error. Here is what I did.
I declared a task in the plugins/index.js file as follow.
module.exports = (on) => {
on("task", {
setTestId(id) {
testId = id;
return null;
},
getTestId() {
return testId;
}
});
};
Then I use the task in the test as follow.
cy.task('setTestId', 7654321);
When I run the tests, I am getting the following error.
The 'task' event has not been registered in the plugins file. You must register it before using cy.task()
As you can see, I tried this solution as well, Cypress task fails and complains that task event has not been registered in the plugins file. It did not work either. What is wrong with my code and how can I fix it?
You're missing some formatting (":" and "=>" and such). Try this:
module.exports = (on) => {
on("task", {
setTestId: (id) => {
testId = id;
return null;
},
getTestId: () => {
return testId;
}
});
};
Set the testId as you did:
cy.task('setTestId', 7654321);
And when you want to retrieve the testId, use:
cy.task('getTestId').then((testId) => {
cy.log(testId)
});

Cypress and Excel Test Data

Has anyone used excel to store test data while runing cypress tests? I am trying to make this work, but since I cant access the file system with browserify I cant read excel test data file. Anyone got this working? DO you have any links/code on how to get it working?
Thanks.
I realised that normal excel processing packages wont work with cypress and typescript, since u r using browserfiy. browserify will prevent you from performing file read/write operations.
as a workaround, i only read the excel file prior to browserifying it (in the plugins/index.js), and convert it into a json file and save it in the fixtures folder.
then in the support/index.js in a beforeAll hook i read the json file as a fixture and save it to an aliased variable. Now I can parse data from the aliased variable and use it where required in cypress context throughout the test. this is what worked for me.
Here is an instruction how to use excel as source for cypress tests https://medium.com/#you54f/dynamically-generate-data-in-cypress-from-csv-xlsx-7805961eff55
First you need to convert your xlsx file to json with Xlsx
import { writeFileSync } from "fs";
import * as XLSX from "xlsx";
try {
const workBook = XLSX.readFile("./testData/testData.xlsx");
const jsonData = XLSX.utils.sheet_to_json(workBook.Sheets.testData);
writeFileSync(
"./cypress/fixtures/testData.json",
JSON.stringify(jsonData, null, 4),
"utf-8"
);
} catch (e) {
throw Error(e);
}
Then import json file and loop over each row and use the data in the way you want. In this example it tries to log in to a system.
import { login } from "../support/pageObjects/login.page";
const testData = require("../fixtures/testData.json");
describe("Dynamically Generated Tests", () => {
testData.forEach((testDataRow: any) => {
const data = {
username: testDataRow.username,
password: testDataRow.password
};
context(`Generating a test for ${data.username}`, () => {
it("should fail to login for the specified details", () => {
login.visit();
login.username.type(data.username);
login.password.type(`${data.password}{enter}`);
login.errorMsg.contains("Your username is invalid!");
login.logOutButton.should("not.exist");
});
});
});
});

How to debug an import binding name that is not found

I have a NativeScript application that I'm trying to add iBeacon support to using the iBeacon plugin. The application builds successfully and is synced to my phone (I'm using SideKick). When the app runs, it has a fatal javascript exception. The javascript error is reported at:
file:///app/tns_modules/tns-core-modules/ui/builder/builder.js:244:56: JS ERROR Error: Building UI from XML. #file:///app/app-root.xml:18:9
That line is where the page that attempts to access the iBeacon code is defined:
<Frame defaultPage="views/search/search-page"></Frame>
and the specific error is:
Importing binding name 'BeaconLocationOptions' is not found.
I'm assuming this occurs as part of the following import statement:
import {NativescriptIbeacon, BeaconCallback, BeaconLocationOptions, BeaconLocationOptionsIOSAuthType, BeaconLocationOptionsAndroidAuthType, BeaconRegion, Beacon } from 'nativescript-ibeacon';
The above import statement is what is documented as part of the iBeacon documentation.
There is a nativescript-ibeacon directory under node_modules in my project. The specific ios file seems to be there:
/Users/edscott/NativeScript/beacon-test/node_modules/nativescript-ibeacon/nativescript-ibeacon.ios.js
I'm not sure if it is a problem in my code or a problem with configuration - maybe something missing that stops the ibeacon files from being deployed properly to the device.
My code is in javascript, but I have installed the typescript plugin. It looks like this iBeacon plugin assumes the app is written in typescript.
I'm looking for help in determining what to try next.
FYI...I've tried pulling the source files out of the node_modules and incorporating them directly into my project. After resolving many issues with this approach, I eventually hit the same wall - a problem importing the code when running on the device.
Below is the code that is using the iBeacon plugin:
const observableModule = require("tns-core-modules/data/observable");
import {NativescriptIbeacon, BeaconCallback, BeaconLocationOptions, BeaconLocationOptionsIOSAuthType, BeaconLocationOptionsAndroidAuthType, BeaconRegion, Beacon } from 'nativescript-ibeacon';
function SearchViewModel() {
let callback = {
onBeaconManagerReady() {
// start ranging and/or monitoring only when the beacon manager is ready
this.nativescriptIbeacon.startRanging(this.region);
this.nativescriptIbeacon.startMonitoring(this.region);
},
didRangeBeaconsInRegion: function(region, beacons) {
console.log("didRangeBeaconsInRegion");
},
didFailRangingBeaconsInRegion: function(region, errorCode, errorDescription) {
console.log("didFailRangingBeaconsInRegion");
}
};
let options = {
iOSAuthorisationType: BeaconLocationOptionsIOSAuthType.Always,
androidAuthorisationType: BeaconLocationOptionsAndroidAuthType.Coarse,
androidAuthorisationDescription: "Location permission needed"
};
let nativescriptIbeacon = new NativescriptIbeacon(callback, options);
let region = new BeaconRegion("HelloID", "2f234454-cf6d-4a0f-adf2-f4911ba9ffa6");
const viewModel = observableModule.fromObject({
"beaconData": "not set yet",
"onTapStart": function() {
this.set("beaconData", "started");
console.log("tapped start");
if (!nativescriptIbeacon.isAuthorised()) {
console.log("NOT Authorised");
nativescriptIbeacon.requestAuthorization()
.then(() => {
console.log("Authorised by the user");
nativescriptIbeacon.bind();
}, (e) => {
console.log("Authorisation denied by the user");
})
} else {
console.log("Already authorised");
nativescriptIbeacon.bind();
}
},
"onTapStop": function() {
this.set("beaconData", "stopped");
console.log("tapped stop");
nativescriptIbeacon.stopRanging(region);
nativescriptIbeacon.stopMonitoring(region);
nativescriptIbeacon.unbind();
}
});
return viewModel;
}
module.exports = SearchViewModel;
I have created a playground for you here.
If you look into example, I am importing NativescriptIbeacon from the main folder and rest from the common folder.
P.S. This plugin has dependency on nativescript-permission
import { NativescriptIbeacon } from '../nativescript-ibeacon';
import {
BeaconRegion, Beacon, BeaconCallback,
BeaconLocationOptions, BeaconLocationOptionsIOSAuthType, BeaconLocationOptionsAndroidAuthType
} from "../nativescript-ibeacon/nativescript-ibeacon.common";
This answer solved my problem along with another modification. After splitting the import up I still had the same error. Then I read the following page about modules:
https://docs.nativescript.org/core-concepts/android-runtime/getting-started/modules
Based on this statement:
If the module identifier passed to require(moduleName) does not begin
with '/', '../', or './', then NativeScript will lookup the module
within the tns_modules folder
I assumed that maybe only require does the proper lookup into tns_modules.
I refactored the import to use require instead, and that worked. My changes are below. There may be a more efficient way to do this, but it worked for me.
const nsb = require("nativescript-ibeacon/nativescript-ibeacon.js");
const nsbc = require("nativescript-ibeacon/nativescript-ibeacon.common.js");
const NativescriptIbeacon = nsb.NativescriptIbeacon;
const BeaconCallback = nsbc.BeaconCallback;
const BeaconLocationOptions = nsbc.BeaconLocationOptions;
const BeaconLocationOptionsIOSAuthType = nsbc.BeaconLocationOptionsIOSAuthType;
const BeaconLocationOptionsAndroidAuthType = nsbc.BeaconLocationOptionsAndroidAuthType
const BeaconRegion = nsbc.BeaconRegion;
const Beacon = nsbc.Beacon;

Says Jasmine spy is not being called, but I can see that its being called

I can't figure out why Jasmine is claiming that the function I'm spying on isn't being called, especially since it is logging in buildLinksObj when called through and not calling when I remove .and.callThrough() I feel like I've written similar code a bunch of times before without any problem. I'm using Jasmine 2.9
The error message I'm getting is:
1) addToLinks should call buildLinksObj if its given an object with children
it should add the personalized links to PageApp.meta.analytics.links
Expected spy buildLinksObj to have been called.
at UserContext.<anonymous> (http://localhost:9877webpack:///tests/specs/common/FetchPersonalContent.spec.js:854:0 <- tests/app-mcom.js:104553:48)
Here's the except of my code:
FetchPersonalContent.js
const buildLinksObj = (responseObj = {}, targetObj, PageApp) => {
console.log('it logs in buildLinksObj') // This is logging!
}
const addToLinks = (responseArr, personalizedLinks) => {
responseArr.forEach((media) => {
const type = media.type;
const typeObj = media[type];
buildLinksObj(typeObj, personalizedLinks, PageApp);
if (typeObj && typeObj.children) {
console.log('has children!')
console.log('typeObj.children is: ', typeObj.children);
typeObj.children.forEach((child) => {
console.log('has a child')
buildLinksObj(child, personalizedLinks, PageApp);
console.log('buildLinksObj was definitely called. what the heck?')
});
}
});
}
export {buildLinksObj, addToLinks, FetchPersonalContent as default,
};
FetchPersonalContent.spec.js
import * as FetchPersonalContent from '../../../src/FetchPersonalContent'; // my path is definitely correct
describe('it should add the personalized links to PageApp.meta.analytics.links', () => {
it('addToLinks should call buildLinksObj if its given an object with children ', () => {
spyOn(FetchPersonalContent, 'buildLinksObj').and.callThrough();
FetchPersonalContent.addToLinks([{
"personalId": 30718,
"type": "carousel",
"carousel": {}
}], {});
expect(FetchPersonalContent.buildLinksObj).toHaveBeenCalled();
});
});
I'd really appreciate any help!
I have a feeling FetchPersonalContent.buildLinksObj in the spec file is not pointing to the same instance as buildLinksObj in the FetchPersonalContent.js file.
Why is export {FetchPersonalContent as default} required? I am assuming you have shared the complete content of FetchPersonalContent.js in your question.
Possible solutions:
You can try removing FetchPersonalContent from the export statement.
Or
Instead of
export {buildLinksObj, addToLinks, FetchPersonalContent as default,
};
You can directly export the constants in FetchPersonalContent.js file.

Resources