Closed hari49951 closed 4 years ago
Hi @hari49951 - using multiple config files should work fine, it seems you are already following the examples from the cypress docs. What you need to change is the order of execution. The line
config = ntlmAuth.initNtlmAuth(config);
adds properties to the config, but when you do
return getConfigurationByFile(file)
after it, those changes are ignored.
Try this way:
const file = config.env.configFile || 'test'
config = getConfigurationByFile(file);
config = ntlmAuth.initNtlmAuth(config);
return config;
Hi @bjowes thank you so much for the quick reply. I modified the code as you suggested and after trying open cypress test runner below is error I am getting. Is there something I am missing? Appreciate you help!
The function exported by the plugins file threw an error.
We invoked the function exported by C:\Users{pathtoproject}\cypress\plugins\index.js, but it threw an error.
TypeError: Cannot set property 'NTLM_AUTH_PROXY' of undefined
at setupProxyEnvironment (C:\Users{pathtoproject}\node_modules\cypress-ntlm-auth\dist\plugin\index.js:23:32)
at C:\Users{pathtoproject}\node_modules\cypress-ntlm-auth\dist\plugin\index.js:32:22
at new Promise (
code after change: const fs = require('fs-extra') const path = require('path') const cucumber = require('cypress-cucumber-preprocessor').default; const ntlmAuth = require("cypress-ntlm-auth/dist/plugin"); /**
on
is used to hook into various events Cypress emits
// config
is the resolved Cypress config
on('file:preprocessor', cucumber());
const file = config.env.configFile || 'test'
config = getConfigurationByFile(file);
config = ntlmAuth.initNtlmAuth(config);
return config;
}function getConfigurationByFile(file) {
const pathToConfigFile = path.resolve(
'cypress/config', cypress.${file}.json
);
return fs.readJson(pathToConfigFile)
}
Update: Now I am not able to run cypress as I do before "npm run cypress-ntlm". I see an error in index.js file, please refer to attached image.
@hari49951 try this
const ntlmAuth = require('cypress-ntlm-auth/dist/plugin'); const fs = require('fs-extra'); const path = require('path');
const getConfigurationByFile = async (config) => {
const file = config.env.configFile || 'dev';
const pathToConfigFile = path.resolve('cypress/', 'config', ${file}.json
);
return fs.readJson(pathToConfigFile);
};
module.exports = async (on, config) => { config = await getConfigurationByFile(config); await ntlmAuth.initNtlmAuth(config); return config; };
Hi @testtek thanks for the reply. When I try above solution, getting the below error.
The plugins file is missing or invalid.
Your pluginsFile is set to C:\Users{pathtoproject}\cypress\plugins\index.js, but either the file is missing, it contains a syntax error, or threw an error when required. The pluginsFile must be a .js or .coffee file.
Or you might have renamed the extension of your pluginsFile to .ts. If that's the case, restart the test runner.
Please fix this, or set pluginsFile to false if a plugins file is not necessary for your project.
C:\Users{pathtoproject}\cypress\plugins\index.js:34
config = await getConfigurationByFile(config);
^^^^^
SyntaxError: await is only valid in async function
at Module._compile (internal/modules/cjs/loader.js:896:18)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:986:10)
at Module.load (internal/modules/cjs/loader.js:816:32)
at Module._load (internal/modules/cjs/loader.js:728:14)
at Module._load (electron/js2c/asar.js:717:26)
at Function.Module._load (electron/js2c/asar.js:717:26)
at Module.require (internal/modules/cjs/loader.js:853:19)
at require (internal/modules/cjs/helpers.js:74:18)
at module.exports (C:\Users\AppData\Local\Cypress\Cache\4.8.0\Cypress\resources\app\packages\server\lib\plugins\child\run_plugins.js:208:15)
at Object.
The variant from @testtek adds async execution, but it won't change the result. Also, the return value from initNtlmAuth must be returned from the function.
If you go back to my suggestion, I think the issue is that initNtlmAuth assumes that the config object contains a "env" property, which it will always do when the config object comes from cypress itself. When you read the config directly from a json file, this might not be true. You could add an empty env property in your config files with a line like
"env": {}
Or you can modify the code slightly to add it for you, so you don't need to pollute the config files with it. Add it like this
config = getConfigurationByFile(file);
config.env = {};
config = ntlmAuth.initNtlmAuth(config);
Hi @bjowes, thanks a lot. It worked but I need to use "env": {} in config file and config.env = {}; in plugin. However after running a test on cypress test runner, I am getting another error. I am using "npm run cypress-ntlm" to open test runner. Scripts--> "cypress-ntlm": "npm run ntlm-proxy && (cypress-ntlm open --env configFile=test & ntlm-proxy-exit)",
Error The cypress-ntlm-auth plugin must be loaded before using this method node_modules/cypress-ntlm-auth/dist/commands/index.js:22:1 20 | const ntlmConfigApi = Cypress.env('NTLM_AUTH_API'); 21 | if (!ntlmProxy || !ntlmConfigApi) {
22 | throw new Error('The cypress-ntlm-auth plugin must be loaded before using this method'); | ^ 23 | } 24 | let ntlmConfig = { 25 | ntlmHost: ntlmHost,
Wierd, that indicates that the config object is not updated. Could you paste your plugin file again? Make sure you are returning the config object from the module.exports = (on, config) =>
method.
@bjowes Here is the plugins/index.js file. Given config file is loading (In test ruuner settings/config section I can see the data that I want to use) which has test data and env data like url, username and password. Test is failing at cy.ntlm() request.
const fs = require('fs-extra') const path = require('path') const cucumber = require('cypress-cucumber-preprocessor').default; const ntlmAuth = require("cypress-ntlm-auth/dist/plugin");
/**
on
is used to hook into various events Cypress emits
// config
is the resolved Cypress config
on('file:preprocessor', cucumber());
const file = config.env.configFile || 'test'
config = getConfigurationByFile(file);
config.env = {};
config = ntlmAuth.initNtlmAuth(config);
return config;
};function getConfigurationByFile(file) {
const pathToConfigFile = path.resolve(
'cypress/config', ${file}.json
);
return fs.readJson(pathToConfigFile)
}
@bjowes I don't see these NTLM_AUTH_PROXY, NTLM_AUTH_API under settings/configuration tab from cypress test runner while loading config file other than default cypress.json file using cypress-ntlm-auth. If I load default cypress.json then I can see these NTLM_AUTH_PROXY, NTLM_AUTH_API under settings/configuration tab from cypress test runner. Appreciate you help on this issue
Hi @hari49951 - sorry to keep you waiting, I've had some time away from coding. I reproduced this on my own machine and found that fs.readJson is actually an async function (returns a promise). All the solutions I've suggested assumed it was a synchronous function. To use fs.readJson, do something like this:
module.exports = (on, config) => {
// on is used to hook into various events Cypress emits
// config is the resolved Cypress config
on('file:preprocessor', cucumber());
const file = config.env.configFile || 'test'
return getConfigurationByFile(file).then((config) => {
config.env = {};
return ntlmAuth.initNtlmAuth(config);
});
};
Hi @bjowes Thanks for taking time to checking on this issue. I have tried your above solution and now I see that test config file is being loaded under settings/configuration tab from cypress test runner but values are from default cypress.json file. It's seems wired. Please go through below details and correct me if I am missing anything.
plugins/index.js file:
module.exports = (on, config) => {
// on
is used to hook into various events Cypress emits
// config
is the resolved Cypress config
on('file:preprocessor', cucumber());
const file = config.env.configFile || 'test'
return getConfigurationByFile(file).then((config) => {
config.env = {};
return ntlmAuth.initNtlmAuth(config);
});
};
function getConfigurationByFile(file) {
const pathToConfigFile = path.resolve(
'cypress/config', ${file}.json
);
return fs.readJson(pathToConfigFile)
}
Scenario A. Loading test.json (npm run cypress:open:qa where cypress:open:qa => "npm run ntlm-proxy && (cypress-ntlm open --env configFile=test & ntlm-proxy-exit)") test.json file: { "baseUrl": "https://baseurl.com", "video": false, "defaultCommandTimeout": 10000, "pageLoadTimeout": 40000, "ignoreTestFiles": [".js",".md"], "testFiles": "*/.{feature,features}", "env": { "AuthUrl": "https://hosturlfromtest.jon", "username": "testuserfromtest.json", "password": "testpassfromtest.json" } }
values under settings tab: baseUrl:"https://baseurl.com" fixturesFolder:"cypress/fixtures" blacklistHosts:null chromeWebSecurity:true modifyObstructiveCode:true integrationFolder:"cypress/integration" env: AuthUrl:"https://somehosturlfromcypress.json" username:"testuserfromcypress.json" password:"testpassfromcypress.json" configFile:"test" NTLM_AUTH_PROXY:"http://127.0.0.1:51415" NTLM_AUTH_API:"http://127.0.0.1:51414" pluginsFile:"cypress/plugins" hosts:null
Scenario B: Loading default cypress.json (npm run cypress-ntlm where cypress-ntlm ==> "npm run ntlm-proxy && (cypress-ntlm open & ntlm-proxy-exit)")
Cypress.json file: { "baseUrl": "https://baseurl.com", "video": true, "defaultCommandTimeout": 10000, "pageLoadTimeout": 40000, "ignoreTestFiles": [ ".js", ".md" ], "testFiles": "*/.{feature,features}", "env": { "AuthUrl": "https://somehosturlfromcypress.json", "username": "testuserfromcypress.json", "password": "testpassfromcypress.json" } }
values under settings tab: baseUrl:"https://baseurl.com" fixturesFolder:"cypress/fixtures" blacklistHosts:null chromeWebSecurity:true modifyObstructiveCode:true integrationFolder:"cypress/integration" env: AuthUrl:"https://somehosturlfromcypress.json" username:"testuserfromcypress.json" password:"testpassfromcypress.json" NTLM_AUTH_PROXY:"http://127.0.0.1:51260" NTLM_AUTH_API:"http://127.0.0.1:51259" pluginsFile:"cypress/plugins" hosts:null
I see that you now have content inside the env property in your custom config file. Then you must remove the line config.env = {}
since it clears the env property. It is only needed if env is null.
Also, did you look into the —config-file
Argument to cypress? I think it could also solve what you are trying to achieve without so much code in the plugins file. https://docs.cypress.io/guides/guides/command-line.html#cypress-run-config-file-lt-config-file-gt
@bjowes Thank you so much, now I am able to load different config files. And the document is also informative.
@bjowes Hi, I am trying to read different config files along with ntlm config. I am not sure how to do that. can you please suggest how to read both files?
const fs = require('fs-extra') const path = require('path') const cucumber = require('cypress-cucumber-preprocessor').default; const ntlmAuth = require("cypress-ntlm-auth/dist/plugin"); /**
on
is used to hook into various events Cypress emits //config
is the resolved Cypress config on('file:preprocessor', cucumber()); const file = config.env.configFile || 'test' config = ntlmAuth.initNtlmAuth(config); //return config; return getConfigurationByFile(file)}
function getConfigurationByFile(file) { const pathToConfigFile = path.resolve( 'cypress/config',
cypress.${file}.json
); return fs.readJson(pathToConfigFile) }