Code Monkey home page Code Monkey logo

Comments (27)

trusktr avatar trusktr commented on July 20, 2024

I've been able to get this all working with karma-webpack, but using karma-webpack has the downside that it compiles a bundle of every single test file in the project which is sloooooooooooooooow, and complete defeats the purpose of concurrent tests. I may as well just compile a single test bundle myself and feed that to Karma, which is what I'm thinking of doing if I can't get karma-electron to work.

I'm running electron with xvfb-maybe so that I can run it headless.

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

That initial config does look correct. We dealt with a similar multi-layer compilation recently in #30 but it looks like this config is fine as is

Is there a test repo you can point me to to reproduce? (minimal size would be ideal)

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Maybe what's causing issues is that my configs and scripts are outside of my project? Here's a gist of what it looks like:

shared_build_stuff
  config
    karma.config.js
  node_modules
my_project
  tests/...
  node_modules

where shared_build_stuff is npm linked into my_project.

Here's how to reproduce:

❯ git clone -b karma-electron-issue-32 [email protected]:trusktr/builder-js-package.git
❯ git clone -b karma-electron-issue-32 [email protected]:trusktr/infamous.git
❯ cd builder-js-package
❯ npm i && npm link # might need sudo
❯ cd ../infamous
❯ npm i && npm link builder-js-package
❯ ELECTRON_BIN=./node_modules/.bin/electron ./node_modules/.bin/xvfb-maybe ./node_modules/.bin/karma start --single-run --browsers Electron ./node_modules/builder-js-package/config/karma.config.js

That should get you the error

Electron 1.8.6 (Node 8.2.1) ERROR
  {
    "message": "Uncaught SyntaxError: Unexpected token import\nat /home/trusktr/Downloads/src/trusktr+infamous/src/core/Mixin.test.js:1:156\n\nundefined",
    "str": "Uncaught SyntaxError: Unexpected token import\nat /home/trusktr/Downloads/src/trusktr+infamous/src/core/Mixin.test.js:1:156\n\nundefined"
  }

Inside of the linked ./node_modules/builder-js-package/config/karma.config.js config, you'll see

        preprocessors: {
            '@(src|test)/**/*.js': ['babel', 'electron'],
            //'@(src|test)/**/*.js': ['babel'],
        },

The first one, which includes 'electron', seems to cause the babel preprocessor not to work, because it results in import statements causing syntax errors.

If you use the second line instead, the import statement errors go away, but then it seems that require is not able to find modules, which give you a different error:

Electron 1.8.6 (Node 8.2.1) ERROR
  {
    "message": "Uncaught Error: Cannot find module './Mixin'\nat module.js:487:5\n\nundefined",
    "str": "Uncaught Error: Cannot find module './Mixin'\nat module.js:487:5\n\nundefined"
  }

Electron 1.8.6 (Node 8.2.1): Executed 0 of 0 ERROR (0.24 secs / 0 secs)

If you have a desktop so that you can see the electron window, you don't need the xvfb-maybe part of the command for running electron headless, so:

❯ ELECTRON_BIN=./node_modules/.bin/electron ./node_modules/.bin/karma start --single-run --browsers Electron ./node_modules/builder-js-package/config/karma.config.js

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

There's only a couple .test.js files inside infamous/src/core, which is where the import syntax errors happen when electron preprocessor is enabled.

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

Great, thanks. I'll try to take a shot at reproducing by the end of the week

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Awesome! Thanks for being so responsive!

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

For now, I'm using karma-webpack with a single test entry point, and running it in Chrome headless with karma-chrome-launcher. The electron approach is cleaner and more performant, without sacrificing features that are lost when using a single test entry point.

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

Going to take a shot at reproducing this now

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

Going to side-step the npm link by updating the git reference in infamous' package.json to use the karma-electron-issue-32 branch

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

Okay, I understand what's going on now. We're using babel-karma to transpile files. This is normally for transpiling hosted files -- not transpiling files that are loaded via require/similar. As a result, once we require our first file, it's no transpiling the second file

I believe a solution to this would be to use babel-node or whatever the Electron equivalent is. Going to try out a couple things and report back

One more option is to avoid needing Babel and sticking to what the platform supports directly but you might be too indebted to turn around at this point =/

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

I'm having trouble wrangling this repo but I'm pretty sure we want to do the following changes:

  • Remove babel-karma from build chain and keep on using loadScriptsViaRequire (this will enable us to use babel-runtime for all files instead of one-off replacements
  • Add a file at the start of files which loads babel-runtime
  • Somehow get .babelrc/similar properly configured with babel-runtime (this is what I was struggling with)

I'm going to try to get a quick and dirty example running in karma-electron that handles the import syntax

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

Yep, got it running in this repo. The steps I enumerated in the last comment will get it working. Here's the diff of changes I had to do in karma-electron to verify it works:

https://github.com/twolfson/karma-electron/compare/7422c3900ef5bc5d37b8800e13978c4284300225

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Awesome, thanks for looking at it! I'd tried babel-register, but I didn't see how to get it to have my own Babel config rather than it looking for babelrc. The problem is, I don't want to to load all babelrc files that it may find inside node_modules. I'll let you know how it works after I give it a shot this weekend.

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

I'm pretty sure that Babel only transpiles for the local directory unless you tell it explicitly to do a global search. Otherwise, that would make everything very very slow ._.

Their docs seem to agree with me -- node_modules are ignored by default

https://babeljs.io/docs/usage/babel-register/#ignores-node_modules-by-default

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

I gave it a shot, but it says it can not find the @babel/register module. My config now looks like this now:

const CWD = process.cwd()

module.exports = function(config) {

    config.set({

        frameworks: ['jasmine'],
        reporters: ['spec'],
        port: 9876,  // karma web server port
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: false,
        concurrency: Infinity,
        basePath: CWD,

        browsers: ['Electron'],
        files: [
            'node_modules/builder-js-package/babel-register.js',
            { pattern: 'src/**/!(*.test).js', included: false },
            'src/**/*.test.js',
            'tests/**/*.js',
        ],
        preprocessors: {
            '@(src|test)/**/*.js': ['electron'],
        },
        client: {
            // otherwise "require is not defined"
            useIframe: false,
            loadScriptsViaRequire: true,
        },

    })

}

where babel-register.js looks like

require('@babel/register')({
    presets: [
        ['@babel/preset-env', {
            targets: {
                node: 6,
            },
        }],
    ],
})

and when I try to run it:

❯ ELECTRON_BIN=./node_modules/.bin/electron ./node_modules/.bin/xvfb-maybe ./node_modules/.bin/karma start --single-run --browsers Electron ./node_modules/builder-js-package/config/karma.config.js
05 05 2018 00:23:47.119:INFO [karma]: Karma v2.0.2 server started at http://0.0.0.0:9876/
05 05 2018 00:23:47.122:INFO [launcher]: Launching browser Electron with unlimited concurrency
05 05 2018 00:23:47.129:INFO [launcher]: Starting browser Electron
05 05 2018 00:23:50.051:INFO [Electron 2.0.0 (Node 8.9.3)]: Connected on socket kNhMblLY4L_4katwAAAA with id 94279078
Electron 2.0.0 (Node 8.9.3) ERROR
  {
    "message": "Uncaught Error: Cannot find module '@babel/register'\nat module.js:545:5\n\nundefined",
    "str": "Uncaught Error: Cannot find module '@babel/register'\nat module.js:545:5\n\nundefined"
  }

Electron 2.0.0 (Node 8.9.3): Executed 0 of 0 ERROR (0.262 secs / 0 secs)

Failed with exit code: 1
Output:

It seems, no matter what I try to require() inside my babel-register.js file, it can not be found.

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Just thinking out loud: if I console.log(__dirname) in my babel-register.js file, I see /home/trusktr/Downloads/src/trusktr+lowclass/node_modules/electron/dist/resources/electron.asar/renderer which is not the babel-register.js file. Maybe that's causing my issue. hmmmm...

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Hmmmmm, changing the import line to

require(process.cwd() + '/node_modules/@babel/register')({

works, but then I get a bunch of syntax errors on the import statements of all my test files again. Hmmmm....

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

We need to preprocess node_modules/builder-js-package/babel-register.js via electron (our karma-electron wrapper) for it to get the proper filepath/require path bindings. Although, I guess that process.cwd() is a nice trick to get it to work for now

        preprocessors: {
            'node_modules/builder-js-package/babel-register.js': ['electron'],
            '@(src|test)/**/*.js': ['electron'],
        },

I'm not sure what babel-register is doing when it crosses between node_modules/builder-js-package and process.cwd(). I suggest simplifying the repo (e.g. colocating files, reducing amount of files) or starting with a proof of concept (e.g. copy/paste core contents and get import working like in the karma-electron branch). We do know that this will work though via the work here:

https://github.com/twolfson/karma-electron/compare/7422c3900ef5bc5d37b8800e13978c4284300225

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

That indeed fixes the import path problem. Thanks!

I noticed in your example you're requireing the to-be-transpiled module from the same file as where you required babel-register, but in my case I am not doing that, I'm only listing the entry points in the tests option. Maybe that's the difference, let me see...

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Ah, yep that's exactly it! So if I change my config to

        browsers: ['Electron'],
        files: [
            'node_modules/builder-js-package/babel-register.js',
        ],
        preprocessors: {
            'node_modules/builder-js-package/babel-register.js': ['electron'],
        },
        client: {
            useIframe: false,
            loadScriptsViaRequire: true,
        },

then have node_modules/builder-js-package/babel-register.js import one of the test files, it works great:

require('@babel/register')({
    presets: [ ['@babel/preset-env', { targets: { node: 6 } }] ],
})
require(process.cwd() + '/tests/basics.test.js') // this works, like in your example.

So the question is, how do I force the babel-register import to happen for each test entry point listed in files?

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Alright, I got it to work with all my test files using the following hack, but it doesn't seem ideal:

const CWD = process.cwd()
const glob = require('globby')
const fs = require('fs')

/*
 * Generate an entry point that imports all test files:
 */
let testFiles = null

glob([
    CWD+'/src/**/*.test.js',
    CWD+'/tests/**/*.js',
]).then(paths => testFiles = paths)

// wait for glob call to finish
while (!testFiles) {
    require('deasync').sleep(100)
}

testFiles = testFiles.map(file => {
    return `require('${ file }')`
}).join('\n')

fs.writeFileSync(CWD+'/.test-entry.js', testFiles)

module.exports = function(config) {

    config.set({

        frameworks: ['jasmine'],
        reporters: ['spec'],
        port: 9876,  // karma web server port
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: false,
        concurrency: Infinity,
        basePath: CWD,

        /*
         * karma-electron + babel-register
         */
        browsers: ['Electron'],
        files: [
            'node_modules/builder-js-package/babel-register.js',
        ],
        preprocessors: {
            'node_modules/builder-js-package/babel-register.js': ['electron'],
        },
        client: {
            useIframe: false,
            loadScriptsViaRequire: true,
        },

    })

}

where node_modules/builder-js-package/babel-register.js has

require('@babel/register')({
    presets: [ ['@babel/preset-env', { targets: { node: 6 } }] ],
})

require(process.cwd() + '/.test-entry.js')

If I do it this way, there's a single entry point in the same file that import babel-register, similar to your example.

Do I lose out on features like concurrent tests if I do it this way? I was hoping to list my entry points in the files option and gain concurrency (or, at least allowed for this possibility if it isn't the case yet). Having a single entry point negates the possibility, and also negates other features like running specific tests (this always runs all tests).

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

I'm going to roll with this for now, because at least it is much cleaner/faster than bundling with Webpack or Browserify. I still wonder if it is possible to use files instead of my generated entry point.

I wonder if there's some way to plug into Electron's (/Node's) require to make it always import certain files without my files having to explicitly require them?

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Plus, with the single-entry-point approach, now the tests are failing because they change the same global state (f.e. customElements.define calls try to register the same element name, which fails).

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Maybe I can do another even uglier hack: generate a folder of entry points, where each entry point imports babel-register and a corresponding test file! Yaaaaaaaaaaas, that will get me to where I need to beeeeeeeee. 🤣

from karma-electron.

twolfson avatar twolfson commented on July 20, 2024

Ah, that is quite clarifying. Glad to hear you got it working =)

To answer your question about concurrency, Karma doesn't really care about concurrency -- it will run entire test suite at a time. It's the job of the test runner (e.g. Mocha, Jasmine, tape) to handle concurrency. There's often plugins for this or separate testers which are parallel out of the box (e.g. ava, vows)

Here's a handful of alternatives for loading the babel-register call:

  • Perform the glob + require calls inside of a single file that is loaded by karma.files
    • Also as a heads up, glob has a glob.sync so no need for the deasync call
  • Babelify all JS files via a watch task into a separate folder (e.g. compiled/) and load those inside of karma (e.g. files: ['compiled/test/**/*.js'])
    • Partial benefit here: No need for babel-register to reparse files when using its require on every test run since it sounds like the require cache gets blown away
  • Wait for #31 to turn around and add generic BrowserWindow options, then use Electron's preload support to preload the babel-register calls
  • Use a Karma preprocessor to prepend content into each file

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Wait for #31 to turn around and add generic BrowserWindow options, then use Electron's preload support to preload the babel-register calls

That's sounds like the best solution. Would it preload the file in every child window that karma opens?

from karma-electron.

trusktr avatar trusktr commented on July 20, 2024

Nvm, I see, for each new-window we'd pass the option in.

from karma-electron.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.