karma-jspm icon indicating copy to clipboard operation
karma-jspm copied to clipboard

baseURL in config.js causes 404s

Open richburdon opened this issue 8 years ago • 22 comments

Struggling with the lack of documentation or working example:

I can't tell if this is the same issue a bunch of people seem to be having (https://github.com/Workiva/karma-jspm/issues/68)

I have a baseURL spec in my config.js; this is my global config, so I don't want to change it for the sake of karma (I'm assuming the intent is that karma-jspm should be made to work with the same runtime config?)

System.config({
  "baseURL": "/js",

So in my karma.conf.js:

"jspm": {
  "loadFiles": [
    "app/testing/**/*.js"
  ],

But I get 404s

[web-server]: 404: /js/app/testing/sandbox.js

By trial and error changing "paths" and "proxies" I can get different errors, but no solution. E.g.,

  "paths": {
    "*": "../*.js"      // Counteract the "/js" config.js baseURL?
  }

[web-server]: 404: /app/testing/sandbox.js

The docs are not clear about how this is supposed to work.

richburdon avatar Aug 20 '15 00:08 richburdon

For me it actually works, so maybe I can help. I am running jspm-0.16.0 and karma-jspm-2.0.1-beta.2. karma.conf.js:

{
    basePath: '.',
    frameworks: ['jspm', 'jasmine'],
    browsers: ['PhantomJS'],
    port: 9876,
    plugins: [
      'karma-jasmine',
      'karma-phantomjs-launcher',
      'karma-jspm'
    ],
    jspm: {
      loadFiles: [
        'src/**/*.spec.ts'
      ],
      serveFiles: [
        'src/**/!(*.spec).ts'
      ]
    }
}

config.js

System.config({
  defaultJSExtensions: true,
  transpiler: "typescript",
  typescriptOptions: {
    "noImplicitAny": true
  },
  paths: {
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*"
  },
  packages: {
    "src": {
      "defaultExtension": "ts"
    }
  }
  ....
});

We keep sources and their spec in the same folder tree.

bjorndown avatar Aug 21 '15 13:08 bjorndown

Thanks bjorm, but the issue is with non-empty baseURLs in config.js: e.g., "baseURL": "/js"

richburdon avatar Aug 22 '15 00:08 richburdon

Same problem. I don't understand how this could possibly work. I keep sources and specs in parallel directories.

A working example would be great.

nateabele avatar Aug 25 '15 00:08 nateabele

karma-jspm currently does not support projects that use a custom baseURL in config.js. It will work fine if you structure your project in such a way that does not require you to set a custom baseURL.

I just attempted a fix that looks something like this in adapter.js:

    var baseURL = karma.config.baseURL ? 'base/' + karma.config.baseURL : 'base';
    System.config({ baseURL: baseURL });

The idea here is that you would configure a baseURL setting in karma.conf.js that matches what you have in config.js. If it is there, karma-jspm would use it while adding the required base/ to the beginning to satisfy the needs of the Karma environment.

But that doesn't work. It seems that if baseURL is set in config.js, the call to System.config({baseURL: ...}) does not change anything. I'm not sure why. Perhaps @guybedford has an idea?

maxwellpeterson-wf avatar Aug 25 '15 19:08 maxwellpeterson-wf

@maxwellpeterson-wf hey, sure it should actually be possible to know the baseURL by:

  • Setting client.jspm.baseURL = getJspmPackageJson(basePath).directories.baseURL || '.'; in https://github.com/Workiva/karma-jspm/blob/master/src/init.js#L76.
  • Then using 'base/' + karma.config.jspm.baseURL + '/' as the baseURL in the adapter.

Yes there is an issue with setting the baseURL last these days as it needs to be set before any other config is loaded due to config normalization. This should be possible by moving the config file to be loaded after the adapter in the ordering at https://github.com/Workiva/karma-jspm/blob/master/src/init.js#L99.

guybedford avatar Aug 26 '15 12:08 guybedford

I second @nateabele - an example would be great. Generally most of the example setups with JSPM put everything in the root whereas I would like to separate my tests from the sources. Anyone have a working example with separate source and test directories? Thanks

poenneby avatar Aug 28 '15 07:08 poenneby

This seems to work okay for me in my config.js

System.config({
  defaultJSExtensions: true,
  transpiler: "babel",
  baseURL: window.__karma__ ? "base" : "/",
  ...
});

My file structure is like this:

├── config.js
├── coverage
├── example
├── jspm_packages
├── karma.conf.js
├── lib
├── node_modules
├── package.json
├── README.md
└── test

Still a hack, I know.

Edit:

This will also run in node:

    baseURL: (typeof __karma__ !== "undefined") ? "base" : "/",

Edit 2: Running jspm install seems to revert the baseURL entirely to "/". Very annoying. The above might not be a workable solution unfortunately.

NervosaX avatar Aug 30 '15 23:08 NervosaX

I have created a basic working project: https://github.com/Workiva/karma-jspm/pull/98 I actually started off integrating the changes proposed by @guybedford but it turned out I didn't need them to achieve what I wanted. With this basic project I can move around config.js, redefine baseURL in config.js and package.json directories. Not really able to reproduce @richburdon issue after all...

poenneby avatar Aug 31 '15 08:08 poenneby

I was able to resolve my problems after much trial and error with the following configuration. My file structure is like this:

└ client/
    └ mycode/ (all my code to be tested is in here)
    └ jspm_packages/
    └ config.js
└ tests/
    └ client/mycode (path follows whatever it is above)
└ node_modules
└ package.json
└ karma.conf.js

This is the baseURL in my config.js

System.config({
  "baseURL": "/static/foo",

This is the baseURL in my package.json (it's different from config.js)

{
  "jspm": {
    "directories": { 
      "baseURL": "client" 
    }
  }
}

Here's my karma.conf.js, notice the use of urlRoot and jspm.paths configurations:

config.set({
  browsers: ['PhantomJS'],
  frameworks: ['jspm', 'jasmine'],
  files: [
    'node_modules/karma-babel-preprocessor/node_modules/babel-core/browser-polyfill.js'
  ],
  jspm: {
    config: 'client/config.js',
    packages: 'client/jspm_packages',
    loadFiles: ['tests/**/*.js'],
    serveFiles: ['client/**/*.js'],
    paths: {
      'mycode/*': 'base/client/mycode/*',
      'tests/*': 'base/tests/*',
      'github:*': 'base/client/jspm_packages/github/*',
      'npm:*': 'base/client/jspm_packages/npm/*'
    }
  },
  urlRoot: '/static/foo/'
});

I found that all of those jspm.paths overrides were necessary to get it to work.

An example of a test file does its imports like this:

import bar from 'mycode/bar';

onlywei avatar Sep 03 '15 22:09 onlywei

@zewa666 Had PR'd a fix for this in v1 that seems to have been lost.

Unfortunately for Aurelia users you will need to move your baseURL setting in to your index.html or w/e view so that it is ignored while running tests until this is fixed :(

plwalters avatar Oct 01 '15 23:10 plwalters

+1

alexcastillo avatar Oct 09 '15 15:10 alexcastillo

+1

Bretto avatar Nov 10 '15 02:11 Bretto

2 more cents, as I had a related issue when playing with Aurelia's minimal app and transform it to use a non-flat project structure.

Everything went fine until I changed jspm's baseURL in package.json (as per this snapshot). From that point I started to have 404s when running the tests, and scratched my head for several hours until I found this discussion.

Replacing the jspm's config file's path values with the ones that are supposed to override them (as per the karma config file) fixes the problem: tkhyn/karma-jspm_baseURL-issue@f904c3456d7361dc88575de50039ae78884b36f2.

My temporary workaround to solve this problem was therefore to automatically generate a karma-specific jspm config file with the correct paths values before running the tests.

That said, with a little bit of manual debugging, I could see that, when the page is loaded in the client:

  1. the default (from the jspm's config file) configuration is loaded
  2. some files are mapped using the default configuration
  3. the configuration's paths attribute is updated with the paths provided in the karma config file
  4. the files are now mapped using the correct overriden configuration

Basically, my understanding is that paths is updated too late and allows some mappings to be created before the karma-specific configuration is loaded. All these mappings become invalid and therefore lead to 404 errors.

I hope it's clear enough, that's all I could find with my relatively shallow knowledge of jspm and node.js.

tkhyn avatar Nov 29 '15 05:11 tkhyn

@tkhyn I can validate your findings! After I tried a whole week to get karma-jspm to run with my React setup, I tried your approach and now all tests run smoothly. Thanks a lot. The paths settings in the karma config for jspm are not working as intended. You can see my config file in issue #83. I removed all the path overrides and added the paths manually in the jspm config.

chauthai avatar Dec 18 '15 17:12 chauthai

I'm completely lost on this. I can't even remove the baseUrl from the config.js because remapping the paths paths: { 'studio/': 'base/studio/',

somehow adds base twice the base

XHR error (404 Not Found) loading http://localhost:9876/base/base/studio

I guess we can forget about a fix for this issue given the time it has been open. But I don't see what the alternatives are. What would you recomment that I move my sources and jspm_packages to /base or did some of you do a custom systemJS load (i.e. not using this library?)

martinsson avatar Mar 02 '16 12:03 martinsson

maybe try karma-systemjs

chauthai avatar Mar 02 '16 14:03 chauthai

@martinsson what I do as a workaround is have a gulp task that copies the config.js to config-test.js and modifies the baseURL on the fly before running the tests. Then the karma config uses the config-test.js as jspm config

sarod avatar Mar 02 '16 17:03 sarod

For 0.17 beta users, the following has worked for us. Assuming your code lives in <project-root>/static, the solution was to create a custom 'browser' config specifically for testing.

// <project-root>/static/jspm.browser.js
SystemJS.config({
  baseURL: "/static",
  paths: {
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*",
  }
});
// <project-root>/static/jspm.karma.js
SystemJS.config({
  baseURL: "",  // notice the empty baseURL, also seems to work with "/base"
  paths: {
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*",
  }
});
// <project-root>/karma.conf.js
    basePath: 'static',
    jspm: {
        config: 'jspm.config.js',
        browser: 'jspm.karma.js',  // <-- not 'jspm.browser.js'
        packages: 'jspm_packages',

        stripExtension: false,

        // app files
        serveFiles: [],

        // test files
        loadFiles: [],
    },

rpkilby avatar Apr 13 '16 17:04 rpkilby

Thank you guys for the tips I'll have to give jspm it another try

martinsson avatar Apr 15 '16 06:04 martinsson

If you're still experiencing the 404-issues with Karma and JSPM: this simple configuration has helped me to solve the 404 file-not-found problems:

Note: Previously, I used the workardound that was mentioned by NervosaX (see above):

System.config({
  baseURL: (typeof __karma__ !== "undefined") ? "base" : "/",
  defaultJSExtensions: true,
  transpiler: "babel",
  ...
});

But as the file 'config.js' will be overwritten each time as 'jspm install' is executed, this solution was abandoned.

Instead, I'm using now the following proxy setting in my karma.conf.js:

	proxies: {
		"/jspm_packages/": "/base/jspm_packages/",
		"/node_modules/": "/base/node_modules/",
		"/dist/": "/base/dist/",
		"/test/": "/base/test/"
	},

FYI: my project structure is as follows:

component root
|
  dist/           => here are my compiled ES6 JS-files (the distribution package)
  jspm_packages/  => jspm-dependencies
  node_modules/   => node-dependencies
  src/            => the source files (Typescript sources)
  test/           => Karma unit-test files that test against the modules in "dist" folder
  config.js       => jspm/SystemJS config file
  index.js        => main index of the component (this imports the module that is stored in the 'dist' folder)
  karma.conf.js   => Karma config file
  package.json    => npm config file

And my full karma.conf.js:

module.exports = function(config) {
  config.set({

    basePath: '',

    files: [
    ],

    autoWatch: false,

    frameworks: ['jspm','jasmine'],

    browsers: ['Chrome'],

    plugins: [
      'karma-jspm',
      'karma-chrome-launcher',
      'karma-firefox-launcher',
      'karma-ie-launcher',
      'karma-jasmine',
      'karma-babel-preprocessor',
      'karma-spec-reporter'
    ],
    
    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,
    
    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true,
    
    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'dist/**/*.js': ['babel'],
      'test/**/*.js': ['babel']
    },
    
    jspm: {
        config: 'config.js',
        
        // Edit this to your needs
        loadFiles: [
            'jspm_packages/github/angular/[email protected]/angular.js',
            'jspm_packages/github/angular/[email protected]/angular-mocks.js',
            'dist/**/*.js',
            'dist/**/*.html',
            'dist/**/*.css',
            'test/*_test.js'
        ],
            
        serveFiles: [
            'jspm_packages/**/*.js'
        ]

    },
    
    proxies: {
        "/jspm_packages/": "/base/jspm_packages/",
        "/node_modules/": "/base/node_modules/",
        "/dist/": "/base/dist/",
        "/test/": "/base/test/"
    },
    
    // web server port
    port: 9876,
    
    reporters: ['spec'],
    
    // enable / disable colors in the output (reporters and logs)
    colors: true

  });
};

I hope this helps you.

Hintalo avatar Dec 21 '16 12:12 Hintalo

Using a function to make a copy of the config-file, and make som adjustments works fine :)


    jspm: {
        // Edit this to your needs
        loadFiles: ['index.js', 'test/*.test.js'],

        /**
        make copy of jspm.config.js, change baseURL to '/base'
        and save as jspm.karma-config.js,
        then just return the new config's filename
        */
        browser: (function(){
            var fs = require('fs');

            fs.writeFileSync("jspm.karma-config.js", (fs.readFileSync("jspm.config.js") + "").replace('"baseURL": "/"', '"baseURL": "/base"'));
            
            return "jspm.karma-config.js";
        })(),
        stripExtension: false
    },

larscmagnusson avatar Dec 28 '16 20:12 larscmagnusson

Angular has the same problem but I don't know how to apply the jspm config to another karma.conf.

ghost avatar Jun 12 '17 21:06 ghost