Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot get electron.remote.require to work #29

Closed
michelwilson opened this issue Dec 15, 2017 · 10 comments
Closed

Cannot get electron.remote.require to work #29

michelwilson opened this issue Dec 15, 2017 · 10 comments
Labels

Comments

@michelwilson
Copy link

I'm trying to get an angularjs-app, which I package with electron, to play together with karma-electron. Previously we used PhantomJS, but I would like to move away from this. The problem is that in a couple of places I have a require('electron').remote.require('./main.js') to get access to some Node stuff from within the renderer process. I cannot seem to get this to work. Using the full path of main.js makes it work, but that is (obviously) undesirable.
I have set __filenameOverride to the location of index.html and loadScriptsViaRequire is set to true. Doesn't seem to make a difference. Clearly, the require is looking in the wrong place for my script (it's in the same directory as index.html). What magic is required to get it working? Issue #11 seems to suggest that it should just work, but doesn't provide me with the detail to get it working in my case...

@michelwilson
Copy link
Author

It seems that remote.require is looking in node_modules/karma-electron/lib for ./main.js, so apparently it is using the cwd of the launcher to look for modules. __filenameOverride seems to refer to the normal require, it isn't picked up by the remote.require.

@twolfson
Copy link
Owner

I've got a few questions:

  • Can you verify there's no bundler being used that might affect require? (e.g. browserify, webpack)
  • What's the error message you're receiving?
  • Would it be possible to get a minimal test case reproducing this issue?

@michelwilson
Copy link
Author

michelwilson commented Dec 21, 2017

I've tried to create an example which is as minimal as possible (not easy), I've uploaded it to https://github.com/michelwilson/karma-electron-minimal-example. The uploaded version works in karma-electron, do a npm install; bower install; karma start to make it go. Comment out src/script.js:4 and comment src/script.js:6 to break it. The working version doesn't work when you do a electron ..

The error I get is:

Electron 1.7.10 (Node 7.9.0) ERROR
  Uncaught Error: Cannot find module './main.js'
  Error: Cannot find module './main.js'
      at Module._resolveFilename (module.js:470:15)
      at Function.Module._resolveFilename (/XXX/minimal/node_modules/electron/dist/resources/electron.asar/common/reset-search-paths.js:35:12)
      at Function.Module._load (module.js:418:25)
      at Module.require (module.js:498:17)
      at EventEmitter.<anonymous> (/XXX/minimal/node_modules/electron/dist/resources/electron.asar/browser/rpc-server.js:263:70)
      at emitTwo (events.js:106:13)
      at EventEmitter.emit (events.js:194:7)
      at WebContents.<anonymous> (/XXX/minimal/node_modules/electron/dist/resources/electron.asar/browser/api/web-contents.js:256:13)
      at emitTwo (events.js:106:13)
      at WebContents.emit (events.js:194:7)
  at /XXX/minimal/node_modules/electron/dist/resources/electron.asar/renderer/api/remote.js:234

@twolfson
Copy link
Owner

Great, that helped a bunch! Here's what the issues I found:

  • We aren't preprocessing src/*.js which is causing __filename and __dirname to be set as the Electron index.html
    • Once this was resolved and client.loadScriptsViaRequire was set back to true, require('../main.js') started working from the renderer (i.e. require, not electron.remote.require)
  • This library mostly targets renderer only testing. As a result, the require('electron').remote path issue was unexpected
  • What is happening: electron.remote.require is resolving from the remote context, meaning it's resolving from the main file of karma-electron (i.e. node_modules/karma-electron/lib/electron-launcher.js)

To summarize, the following fixes should resolve everything but we recommend the launcher require option instead of electron.remote.require:

karma.conf.js:

// ...
        preprocessors: {
            'src/**/*.js': ['electron'],
            'test/**/*.js': ['electron']
        },
        client: {
            useIframe: false,
            loadScriptsViaRequire: true
        },

// ...

script.js:

// ...
node_script = require('electron').remote.require(__dirname + '/../main.js');
// ...

@michelwilson
Copy link
Author

Ah that gives some insight. I've got the minimal example working, now. To get the actual application to work, a bit more is required, as the __dirname trick doesn't seem to work there ... in karma-electron, __dirname refers to the directory of script.js, in electron itself it points to the directory of index.html.

I am not sure what use the launcher require option has. If I use it to require the main Electron script, this seems to start the application, in parallel with the test. Certainly not what I wanted to achieve ;)

@michelwilson
Copy link
Author

Well, I don't fully understand why, but I got things working. For anyone encountering similar problems (you never know, and I hate finding problems without solutions ;)):

  • I've disabled loadScriptsViaRequire
  • __filenameOverride is set to the correct location of index.html (the one in the dev output directory, in my case
  • this can be checked by printing __dirname from the script in which you want to remote.require something, very useful!
  • and finally, this allows you to do remote.require(__dirname + '/something.js').

No idea if this is the 'right' way, but it makes it work for me :) Thanks for the assistance!

@twolfson
Copy link
Owner

Glad to hear we got it working. If you'd like, I can help direct you in the direction with respect to main.js. Could you provide more context on why you need to load main.js?

@michelwilson
Copy link
Author

In case of the real application, main.js exposes certain functionality that can only be handled outside of the renderer process: sending a UDP broadcast for server discovery. The reason for using karma-electron is to build midway tests at the frontend level of the stack, which talk to an actual backend. This gets us three things: midway tests of the frontend code, tests of the protocol between frontend and backend, and integration tests for the backend. Downside is of course that any test failures pose an interesting puzzle ;)
Anyway: it seems to be working, I can call frontend service layer functions, that call all the way into the backend, so I'm happy.

@twolfson
Copy link
Owner

Cool, thanks for the info. Here's a few options:

@michelwilson
Copy link
Author

Interesting reading, thanks! I particularly like the idea of contract-based fixtures, as this circumvents the problem of not really testing the API by explicitly defining it. Even gives you a form of documentation for the API :) Thanks! I believe that I'll continue to use the current approach, due to time/budget constraints, unfortuntely. However, there'll always be future projects :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants