Closed EmiM closed 5 months ago
Hello,
The URL that Electron loads during startup should match the value of "mainWindowUrl" option. Based on your log:
What do you mean by "dynamically"? Can I pass a function in testcafe config somehow?
I have an access to electron's APPDIR env variable that contains this needed path however testcafe config is loaded before APPDIR (or any other information about app) is known.
Yes, you can pass a function to the TestCafe config, and you can try to use a getter for late binding (since APPDIR
is not available when the config is read):
get-main-window-url.js
function getMainWindowUrl() {
return `${process.env.APPDIR}/dist/main/index.html#/`;
}
export default getMainWindowUrl;
.testcafe-electron-rc.js
import getMainWindowUrl from './get-main-window-url';
module.exports = {
get mainWindowUrl() {
return getMainWindowUrl();
},
electronPath: `./dist/OurAppName.AppImage`
}
test.js
import getMainWindowUrl from './get-main-window-url';
const MAIN_PAGE = getMainWindowUrl();
fixture `Fixture 1`
.page `${MAIN_PAGE}`;
//...
fixture `Fixture 2`
.page `${MAIN_PAGE}/some-page`;
Please let me know your results.
Thank you for the response!
Unfortunately it still doesn't work. It's called too early.
I had to add setter to the getter from your suggestion because otherwise I was getting TypeError: Cannot set property mainWindowUrl of #<Object> which has only a getter
I printed a traceback in the mainWindowUrl getter. You can see that's called right at the start in get-config and only before starting electron process.
e2e-tests: > cross-env E2E_TEST=true NODE_ENV=development DEBUG='waggle*,quiet*,testcafe:*electron*' testcafe --color --hostname localhost -S --screenshots-full-page -p '${DATE}_${TIME}_${TEST_ID}.png' "electron:../frontend" "./**/*.e2e.ts"
e2e-tests: Trace: Here mainWindowUrl getter from testcafe config file://undefined/dist/main/index.html#/
e2e-tests: at Object.get mainWindowUrl [as mainWindowUrl] (/home/me/dev/monorepo/packages/frontend/.testcafe-electron-rc.js:17:16)
e2e-tests: at exports.default (/home/me/dev/monorepo/packages/e2e-tests/node_modules/testcafe-browser-provider-electron/lib/utils/get-config.js:45:16)
e2e-tests: at BrowserProviderPluginHost._callee3$ (/home/me/dev/monorepo/packages/e2e-tests/node_modules/testcafe-browser-provider-electron/lib/index.js:177:62)
e2e-tests: at tryCatch (/home/me/dev/monorepo/packages/e2e-tests/node_modules/babel-runtime/node_modules/regenerator-runtime/runtime.js:62:40)
e2e-tests: at Generator.invoke [as _invoke] (/home/me/dev/monorepo/packages/e2e-tests/node_modules/babel-runtime/node_modules/regenerator-runtime/runtime.js:296:22)
e2e-tests: at Generator.prototype.<computed> [as next] (/home/me/dev/monorepo/packages/e2e-tests/node_modules/babel-runtime/node_modules/regenerator-runtime/runtime.js:114:21)
e2e-tests: at step (/home/me/dev/monorepo/packages/e2e-tests/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
e2e-tests: at /home/me/dev/monorepo/packages/e2e-tests/node_modules/babel-runtime/helpers/asyncToGenerator.js:35:14
e2e-tests: at new Promise (<anonymous>)
e2e-tests: at new F (/home/me/dev/monorepo/packages/e2e-tests/node_modules/core-js/library/modules/_export.js:36:28)
e2e-tests: at BrowserProviderPluginHost.<anonymous> (/home/me/dev/monorepo/packages/e2e-tests/node_modules/babel-runtime/helpers/asyncToGenerator.js:14:12)
e2e-tests: at BrowserProviderPluginHost.openBrowser (/home/me/dev/monorepo/packages/e2e-tests/node_modules/testcafe-browser-provider-electron/lib/index.js:243:26)
e2e-tests: at BrowserProvider.openBrowser (/home/me/dev/monorepo/packages/e2e-tests/node_modules/testcafe/src/browser/provider/index.ts:317:27)
e2e-tests: at BrowserConnection._runBrowser (/home/me/dev/monorepo/packages/e2e-tests/node_modules/testcafe/src/browser/connection/index.ts:203:33)
e2e-tests: at /home/me/dev/monorepo/packages/e2e-tests/node_modules/testcafe/src/browser/connection/index.ts:173:37
e2e-tests: at processTicksAndRejections (internal/process/task_queues.js:79:11)
In the meantime I noticed that I don't have access to APPDIR on the test level so unfortunately this wouldn't work anyway.
I can see that electron-mocks.js has access to the app.getAppPath
.
If we know that we are testing built version of electron app and app dir will be created dynamically then I'm wondering why mainWindowUrl
can't be passed as a relative path (e.g /dist/main/index.html#/) and resolved to a full path later with getAppPath?
The fixture's page
value produces similar but worse problem because there is no way to access app's directory (value of getAppPath) from the test file.
I've also gave it at shot and I've sort was able to make progress, but I'm definitely not happy with direction it took.
I was able to get through initial verification making local change to following file: node_modules/testcafe-browser-provider-electron/templates/hook.js.mustache
:
(function () {
const originalConfig = {{{CONFIG}}};
const config = {
...originalConfig,
get mainWindowUrl() {
const mainPage = `file://${process.env.APPDIR}/resources/app.asar/dist/main/index.html#/`;
return mainPage;
},
set mainWindowUrl(value) {}
}
require('module')._load({{{INJECTABLE_PATH}}})(config, {{{TEST_PAGE_URL}}})
})();
The reason I need to move mainWindowUrl getter in here, is that the electron-side code is rendered like this:
export default function (config, testPageUrl) {
return renderTemplate(HOOK_TEMPLATE, {
INJECTABLE_PATH: INJECTABLE_PATH,
CONFIG: JSON.stringify(config),
TEST_PAGE_URL: JSON.stringify(testPageUrl)
});
(testcafe-browser-provider-electron/src/hook.js)
therefore the getter/setter defined in .testcafe-electron-rc.js
is not transfered over to the electron-side.
This change allowed my to pass through verification during launching of TestCafe.
Unfortunately I got stuck in different place. In my tests I have:
fixture`Electron test`.page(getMainWindowUrl())
test('User can create new community, register and send few messages to general channel', async t => {
....
It appears that the page
can only be specified during load of the module and testcafe loads this module before spawning electron, therefore the APPDIR is not known yet.
What would allow me to have this working, would be if it were possible to specify the page
dynamically on runtime from within the body of test
. This is because test
is executed after the electron has been started, therefore the path is already known. Do you know a way to specify page
later than upon module load?
I looked at the testcafe examples and I found out that there is a way to specify a 'page' from within the test body - await t.navigateTo(getMainWindowUrl())
I managed to run tests but only with hacking testcafe electron plugin code.
mainWindowUrl
in configuration file (/dist/main/index.html#/
)mainWindowUrl
value in get-config.jsmainWindowUrl
inside electron-mocks.js loadUrl
(config.mainWindowUrl = 'file://' + app.getAppConfig() + config.mainWindowUrl
)t.navigateTo
It's obviously not the solution.
@VasilyStrelyaev
I ended up forking the plugin and adding few changes to be able to set mainWindowUrl
properly.
However I still have a problem with setting test case's page url.
page
is accessed and modified in testcafe's api/structure/testing-unit
but I don't see any electron plugin code called at the moment of accessing the page so I could adjust it to my needs.page
instead of navigateTo
but it would be something. However, while I was playing with Helpers and trying to call getMainMenuItems
(or other helper function), I received an error:1) TypeError: Cannot read property 'browserConnection' of undefined
e2e-tests: Browser: Electron 12.1.0 / Linux 0.0
e2e-tests: 137 | isMultiBrowser: true,
e2e-tests: 138 | openedBrowsers: {},
e2e-tests: 139 |
e2e-tests: 140 | _getBrowserHelpers: function _getBrowserHelpers() {
e2e-tests: 141 | var testRun =
e2e-tests: _testRunTracker2.default.resolveContextTestRun();
e2e-tests: > 142 | var id = testRun.browserConnection.id;
e2e-tests: 143 |
e2e-tests: 144 | return
e2e-tests: ElectronBrowserProvider.openedBrowsers[id].helpers;
I checked what is going on in resolveContextTestRun
and this.activeTestRuns
is an empty object that's why it doesn't work. I also can't see addActiveTestRun
being called at any time.
I would want to be able to pass a relative (to electron.app.getAppPath) path in a test file or at least access the app.getAppPath from the test case. Is there a way to achieve this right now?
Do you use a different form of communication than github issues? Like Gitter? I think it would be much easier to talk this way.
Hi @EmiM,
Please share an example that demonstrates how you start your electron app and TestCafe tests. We will try to find a suitable solution for you.
Hi, sorry for the late response.
I created a simple example based on electron-react-boilerplate: https://github.com/EmiM/electron-react-boilerplate
Running the test:
npm i
npm run package
npm run e2e
You will see the same mainWindowUrl
error that we encountered in our setup. It's possible that I set the wrong mainWindowUrl but then again - I'm wondering what should it be and README doesn't explain it very well in my opinion.
Hi @EmiM
I ran your example and got another error:
Please check your example again step-by-step.
Sorry, I didn't predict that it will be run on Windows as I've been using your plugin only on Linux (AppImage file).
I pushed a fix with handling app path for 3 different platforms but it still doesn't work on Windows as I would expect. Electron produces Setup exe file for Windows. Using this file directly gave me:
PS C:\dev\electron-react-boilerplate\release\build> npm run e2e
> electron-react-boilerplate@ e2e C:\dev\electron-react-boilerplate
> testcafe "electron:." "test.e2e.ts"
ERROR Unable to open the "electron:." browser due to the following error:
Error: Unable to connect
at NodeInspect._callee2$ (C:\dev\electron-react-boilerplate\node_modules\testcafe-browser-provider-electron\lib\node-inspect.js:123:39)
at tryCatch (C:\dev\electron-react-boilerplate\node_modules\babel-runtime\node_modules\regenerator-runtime\runtime.js:62:40)
at Generator.invoke [as _invoke] (C:\dev\electron-react-boilerplate\node_modules\babel-runtime\node_modules\regenerator-runtime\runtime.js:296:22)
at Generator.prototype.<computed> [as next] (C:\dev\electron-react-boilerplate\node_modules\babel-runtime\node_modules\regenerator-runtime\runtime.js:114:21)
at step (C:\dev\electron-react-boilerplate\node_modules\babel-runtime\helpers\asyncToGenerator.js:17:30)
at C:\dev\electron-react-boilerplate\node_modules\babel-runtime\helpers\asyncToGenerator.js:28:13
So I manually run Setup exe file and then set the full path to the installed exe: (...)AppData\\Local\\Programs\\electron-react-boilerplate\\ElectronReact.exe'
as electronPath
with (...)/AppData/Local/Programs/electron-react-boilerplate/resources/app.asar/dist/renderer/index.html
as mainWindowUrl
. It worked, test passed. Great but it produces more problems:
Thank you for the example. I reproduced this behavior. We will research it and update this thread once we have any news.
For the team: remove the electronPath
property from .testcafe-electron-rc.js
This issue has been automatically marked as stale because it has not had any activity for a long period. It will be closed and archived if no further activity occurs. However, we may return to this issue in the future. If it still affects you or you have any additional information regarding it, please leave a comment and we will keep it open.
We're closing this issue after a prolonged period of inactivity. If it still affects you, please add a comment to this issue with up-to-date information. Thank you.
Hello,
I was looking through issues but I did not find anything helpful for my problem. We were using this testcafe plugin to test project (js app). Everything works fine (well, maybe except reopening app in another test case but that's a different issue). Now I want to test the built (executable) version of the app. I'm trying to first make it work with .AppImage. I can try it with .exe but I assume that the problem will be the same.
The app starts but I have a problem with
mainWindowUrl
. The README (especially code snippets) suggests that it would be the same setting as for the js app. However it doesn't work for me.This is the current configuration:
This is the error I get:
It's great that the output suggests the page I should use but
tmp/.mount_Quiet-yOG9W1/
is being created when the app starts and I don't have access to this path at the configuration level.Is there something that I don't understand? I don't see any examples in the repo of testing executable code. I would really appreciate the help.