Node Version: 18.19.1
I have a project with some simple Cypress tests, which work. I am trying to write an additional Cypress test which accesses a db2 database using ibm_db.
Repo structure:
The test file DB.cy.js looks like this:
const { getTestData } = require('../support/db2Utils.js');
describe('Test the getTestData method', () => {
it('Data should be returned', (done) => {
getTestData((err: Error | null, data: any) => {
if (err) {
done(err); // fail test in case of errors
} else {
if (data && data.length > 0) {
done(); // If data has been returned, close test as successful
} else {
done(new Error('No data returned.')); // test failed because no data was returned
}
}
});
}).timeout(4000);
});
/support/db2Utils.js looks like this:
const ibmdb = require('ibm_db');
function getTestData(callback) {
const connString = process.env.DB_CONN_STRING;
if (connString === undefined) {
throw new Error('DB_CONN_STRING is missing. Needed to run test.');
}
ibmdb.open(connString, function (err, conn) {
if (err) {
console.error("Error when trying to open connection:", err);
callback(err, null);
return;
}
conn.query("SELECT konto FROM ENTW.XY where END_KREDIT_NEHMER = 11753215", function (err, data) {
if (err) {
console.error("Error at query:", err);
callback(err, null);
} else {
callback(null, data);
}
conn.close(function () {
console.log("Connection closed.");
});
});
});
}
module.exports = { getTestData };
When copying DB.cy.js to a folder called /test/ and renaming it "DB.test.js", it can be executed using mocha. (Therefore I suspect there is something going on with Cypress.) (Often there is a timeout for the first execution, but the second is successful.)
Error and Stacktrace:
1) An uncaught error was detected outside of a test:
TypeError: The following error originated from your test code, not from Cypress.
> Cannot read properties of undefined (reading 'indexOf')
When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.
Cypress could not associate this error to any specific test.
We dynamically generated a new test to display this failure.
at Function.getFileName (node_modules/bindings/bindings.js:178:0)
at bindings (node_modules/bindings/bindings.js:82:0)
at Object.eval (node_modules/ibm_db/lib/odbc.js:57:0)
at Object.eval (https://myrepo/__cypress/tests?p=cypress/e2e/DB.cy.js:8991:4)
at 38../climacros (https://myrepo/__cypress/tests?p=cypress/e2e/DB.cy.js:8991:17)
at o (node_modules/browser-pack/_prelude.js:1:0)
at eval (node_modules/browser-pack/_prelude.js:1:0)
at Object.eval (cypress/support/db2Utils.js:1:14)
at Object.eval (https://myrepo/__cypress/tests?p=cypress/e2e/DB.cy.js:55:4)
at 2._process (https://myrepo/__cypress/tests?p=cypress/e2e/DB.cy.js:55:17)
/support/e2e.ts:
import './commands'
import 'cypress-plugin-tab'
package.json:
{
"scripts": {
"test:e2e": "cypress run --e2e",
"test:db2": "mocha",
"test:db2:debug": "mocha --inspect"
},
"engines": {
"npm": ">=8.0.0 <11.0.0",
"node": ">=16.0.0 <21.0.0"
},
"stepDefinitions": [
"cypress/e2e/[filepath]/**/*.{js,ts}",
"cypress/e2e/[filepath].{js,ts}",
"cypress/support/step_definitions/**/*.{js,ts}"
],
"devDependencies": {
"@cypress/webpack-preprocessor": "^6.0.2",
"@types/ibm_db": "^3.2.0",
"@types/node": "^22.7.5",
"cypress": "13.6.2",
"cypress-cucumber-preprocessor": "^4.3.1",
"cypress-plugin-tab": "^1.0.5",
"mocha": "^10.6.0",
"terser-webpack-plugin": "^5.3.11",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"typescript": "^5.6.3"
},
"dependencies": {
"ibm_db": "^3.2.4"
}
}
/cypress.config.ts:
import {defineConfig} from 'cypress'
const cucumber = require('cypress-cucumber-preprocessor').default;
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
const cucumberOptions = {
typescript: require.resolve('typescript'),
}
on('file:preprocessor', cucumber(cucumberOptions))
return config;
},
video: true,
specPattern:
['cypress/integration/*.feature', 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}'],
supportFile:
'cypress/support/e2e.ts',
excludeSpecPattern:
[
'cypress/e2e/**/T002*.cy.ts'
],
baseUrl:
'https://my_app.net',
viewportWidth:
1920,
viewportHeight:
1080
}
})
In the cypress.config.ts I have also tried using the webpack-preprocessor instead of the cucumber-preprocessor, or setting the options to:
{ ...
const webpackOptions = webpackPreprocessor.defaultOptions;
webpackOptions.optimization = {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
reduce_vars: false,
},
},
}),
],
};
on('file:preprocessor', webpackPreprocessor(webpackOptions));
... }
Because of these posts: https://github.com/TooTallNate/node-bindings/issues/50 and https://github.com/TooTallNate/node-bindings/issues/61 Unfortunately, the error remained.
What is going on here? How can I fix it?
If you look at the npm page for ibm_db you can see that it's for nodejs
An asynchronous/synchronous interface for node.js
which means you shouldn't run it directly in the test as you have done, instead set it up in a task. The differenc e is the test code runs in the browser, and cy.task()
is the command to initiate code that runs in Cypress' nodejs background process.
So roughly the task is
const { getTestData } = require('./e2e/support/db2Utils.js');
const connString = ...
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('task', {
getTestData({query}) {
...
return data || error
},
and the test is
cy.task('getTestData', {query: 'SELECT konto FROM ...etc'})
.then((dataOrError) => {
...
})
You probably can't pass the full callback from the test to the task because it's inter-process and the parameters need to be serializable, which means a little bit of refactoring will be required.