twolfson / karma-electron

Karma launcher and preprocessor for Electron
The Unlicense
59 stars 21 forks source link

Cannot get electron.remote.require to work #29

Closed michelwilson closed 6 years ago

michelwilson commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

I've got a few questions:

michelwilson commented 6 years ago

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 commented 6 years ago

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

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 commented 6 years ago

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 commented 6 years ago

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 ;)):

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

twolfson commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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

michelwilson commented 6 years ago

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 :)