I have some repositories (A, B, C and TestRepo) all of them in local, i get karma to load spec files from repos A or B or C with a param (node script).
Now im trying to transpile the files cause some test are using import so i need babel. I configured babel as a preprocessor and it seems like it is working but know i get this error:
Uncaught Error: Module name "builder" has not been loaded yet for context: _. Use require([])
I tried all configs i know but still not working.
My karma.config.js is this:
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine', 'requirejs'],
files: [
'test-main.js'
],
exclude: [
],
preprocessors: {
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
concurrency: Infinity
});
}
My test-main.js for requirejs:
var allTestFiles = []
var TEST_REGEXP = /(spec|test)\.js$/i
Object.keys(window.__karma__.files).forEach(function (file) {
if (TEST_REGEXP.test(file)) {
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '')
allTestFiles.push(normalizedTestModule)
}
})
require.config({
baseUrl: '/base',
deps: allTestFiles,
callback: window.__karma__.start
})
And my node file, where i set karma files, preprocessor and so on base on the repository i got from params is this:
const cfg = require('karma').config;
const stopper = require('karma').stopper;
const runner = require('karma').runner;
const Server = require('karma').Server;
const path = require('path');
const REPOSITORY = process.argv[2] || '';
let karmaConfig = cfg.parseConfig(path.resolve('./karma.conf.js'), { port: 9876 } );
let BASE_PATH;
if (REPOSITORY !== 'all') {
BASE_PATH = `/Users/fernando.delolmo/${REPOSITORY}`;
karmaConfig.files.push({pattern: BASE_PATH + '/test/**/*.spec.js'});
karmaConfig.files.push({pattern: BASE_PATH + '/src/**/*.js', included: true});
karmaConfig.preprocessors[BASE_PATH + '/src/**/*.js'] = ['babel'];
karmaConfig.preprocessors[BASE_PATH + '/test/**/*.spec.js'] = ['babel'];
karmaConfig.exclude.push(BASE_PATH + '/node_modules/**/*.spec.js');
} else {
BASE_PATH = '/Users/fernando.delolmo/';
karmaConfig.files.push({pattern: BASE_PATH + '**/test/**/*.spec.js'});
karmaConfig.files.push({pattern: BASE_PATH + '**/src/**/*.js', included: true});
karmaConfig.preprocessors[BASE_PATH + '**/src/**/*.js'] = ['babel'];
karmaConfig.preprocessors[BASE_PATH + '**/test/**/*.spec.js'] = ['babel'];
karmaConfig.exclude.push(BASE_PATH + '**/node_modules/**/*.spec.js');
}
karmaConfig.basePath = BASE_PATH;
var server = new Server(karmaConfig, function(exitCode) {
process.exit(exitCode);
});
server.start();
server.on('browser_start', function() {
runner.run(karmaConfig, function(exitCode) {
process.exit(exitCode);
});
});
server.on('browser_complete', function() {
stopper.stop(karmaConfig, function(exitCode) {
process.exit(exitCode);
});
});
Its my first time configuring karma, requirejs and babel all together so any help will be great :)
Okay finally i got what's the problem here. Just in case some one get here finding any solution to problems like this.
If you want to run test with ES2015 modules with karma, you will use babel to transpile into CommonJS modules at first, good! but... you will get errors like export is undefined.. and.. why?? Simple, export/import still not supported on the browsers, this means you CAN'T run CommonJS modules on the browser without any module bundler (browersify or webpack).
So, keep this clear:
1st -> Babel only transpile your ES2015 code and test into CommonJS modules
2nd -> Webpack / Browersify get CommonJS modules and bundle them into a bundle.js and then you can run that on the browser with karma.
Related
I have a nw.js native application with angular.js inside. My app bundled with webpack and contains native node.js modules. My entry point is index.js file that I organized like this:
var gui = require('nw.gui');
var angular = require('angular');
require('./app.css');
// other modules
var myApp = angular.module('myApp', [
'ngRaven',
'ngMaterial',
'ngMessages'
]).constant(
'fs', require('fs')
)
require('./services')(myApp);
require('./directives')(myApp);
require('./factories')(myApp);
require('./filters')(myApp);
require('./controllers')(myApp);
require('./app.js')(myApp);
My webpack config looks like this:
const path = require('path');
const config = {
entry: [
'./app/index.js'
],
output: {
path: path.resolve(__dirname, 'app'),
filename: 'bundle.js'
},
devtool: "source-map",
target: 'node-webkit',
module:{
// css, html loaders
},
node: {
os: true,
fs: true,
child_process: true,
__dirname: true,
__filename: true
}
};
module.exports = config;
So every dependency include Node.js native modules like fs, path, child_process bundled in one big file bundle.js that i include in html and then package my nw.js app. So my app structure looks like:
my_project:
--app
----controllers
------welcome
--------welcome.js // Page controller
--------welcome.html // Page HTML
------index.js // here I include each page controller
----app.js // My angular app initialization
----index.js // here I include all dependencies
I'm trying to run tests with this structure. I tried karma+jasmine, karma+mocha, tried different configurations, my last one looks like:
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [
'app/bundle.js',
'app/**/*spec.js'
],
exclude: [],
preprocessors: {
'app/bundle.js': ['webpack']
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
flags: ['--no-sandbox']
}
},
singleRun: true,
webpack: {
// you don't need to specify the entry option because
// karma watches the test entry points
// webpack watches dependencies
// ... remainder of webpack configuration (or import)
},
webpackMiddleware: {
// webpack-dev-middleware configuration
// i.e.
noInfo: true,
// and use stats to turn off verbose output
stats: {
// options i.e.
chunks: false
}
}
});
};
But my tests still not see the angular application.
describe('Welcome page', function() {
beforeEach(angular.mock.module('WelcomePageCtrl'));
});
P.S I don't require exactly karma and jasminne, so any solution will be appreciated. I just want to cover my project with tests
I have gone through something similar myself. I don't think you need the bundle.js for your tests.
Here is how would do it:
I assume your controller/service/etc implementation is as follows:
/* app/controller/welcome.js */
module.exports = function(app) {
return app.controller("MyCtrl", function($scope) {
$scope.name = "lebouf";
});
};
I like my test code to sit right beside the code I'm testing (Welcome.spec.js in the same directory as Welcome.js). That test code would look like so:
/* app/controller/welcome.spec.js */
beforeEach(function() {
var app = angular.module("myApp", []); //module definition
require("./welcome")(app);
});
beforeEach(mockModule("myApp"));
describe("MyCtrl", () => {
var scope = {};
beforeEach(mockInject(function($controller) {
$controller("MyCtrl", {
$scope: scope
});
}));
it("has name in its scope", function() {
expect(scope.name).to.equal("not lebouf"); //the test will fail
});
});
Except, this is an angular controller we're testing and it's not that simple. We need the angular object itself. So lets set it up. I'll explain why it is done how it is done next:
/* test-setup.js */
const jsdom = require("jsdom").jsdom; //v5.6.1
const chai = require("chai");
global.document = jsdom("<html><head></head><body></body></html>", {});
global.window = document.defaultView;
global.window.mocha = true;
global.window.beforeEach = beforeEach;
global.window.afterEach = afterEach;
require("angular/angular");
require("angular-mocks");
global.angular = window.angular;
global.mockInject = angular.mock.inject;
global.mockModule = angular.mock.module;
global.expect = chai.expect;
console.log("ALL SET");
And we'll run the tests as:
node_modules/.bin/mocha ./init.js app/**/*.spec.js
#or preferably as `npm test` by copying the abev statement into package.json
extra info
Here is how init.js is setup as is:
jsdom: f you require("angular/angular") you'll see that it needs a window instance. jsdom can create documents and windows and so on without a web browser!
window.mocha: we need angular-mocks to populate our angular with the necessary utilities. But if you look at the code you'll notice that window.mocha || window.jasmine needs to be true. Thats whywindow.mocha = true`
window.beforeEach, window.afterEach: the same reason as above; because angular-mocks.js demands it.
I set some global variables that I plan to use commonly in my tests: angular, expect, mockInject, mockModule.
Also these may provide some additional information:
https://kasperlewau.github.io/post/angular-without-karma/
https://gist.github.com/rikukissa/dcb422eb3b464cc184ae
I was using webpack+aurelia for a project and recently switch to JSPM version 0.16.52. I use jasmine's spyOn for utility or factory functions that are imported into my classes. However tests that have spyOn(object, 'method') have this error:
"Module Exports Cannot Be Changed Externally"
This occurs when jasmine sets the spied method on the module obj[methodName] = spiedMethod'
Here is a very simple example:
test.js
import * as env from '../../src/env';
describe('stackoverflow example', () => {
it('runs the test', () => {
// this gets thrown and swallowed. jasmine does not report an error, but does not increase the test count.
let envSpy = spyOn(env, 'getBaseUrl');
});
});
env.js
export function getBaseUrl(location) {
return location.port ? `http://${location.hostname}:9001/api/`: '/api/';
}
karam.conf.js
'use strict'
const path = require('path')
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns
basePath: __dirname,
// frameworks to use
frameworks: ['jspm', 'jasmine'],
// list of files / patterns to load in the browser
files: [],
// list of files to exclude
exclude: [],
jspm: {
// Edit this to your needs
loadFiles: [
'test/unit/setup.js',
'test/unit/**/*.js'
],
serveFiles: [
'src/**/*.*',
'jspm_packages/system-polyfills.js'
],
paths: {
'*': 'src/*',
'test/*': 'test/*',
'github:*': 'jspm_packages/github/*',
'npm:*': 'jspm_packages/npm/*'
}
},
// preprocess matching files before serving them to the browser
preprocessors: {
'test/**/*.js': ['babel'],
'src/**/*.js': ['babel']
},
'babelPreprocessor': {
options: {
sourceMap: 'inline',
presets: [ ['es2015', { loose: true }], 'stage-1'],
plugins: [
'syntax-flow',
'transform-decorators-legacy',
'transform-flow-strip-types',
[ 'istanbul', { 'ignore': 'test/' } ]
]
}
},
// test results reporter to use
reporters: ['mocha'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
browsers: ['Chromium'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
setup,js
import 'babel-polyfill'; // for async/await
import 'aurelia-polyfills';
import {initialize} from 'aurelia-pal-browser';
initialize();
UPDATE
When I pulled down a fresh copy of Aurelia-esnext I did not receive the error. So commented out all my tests in my production app and the first spyOn worked, but as i added more tests I started recieving the error again, and it seems to be the way the module is loaded by systemjs. Below is how the imported module object looks when it is loaded into the test
Fresh Copy does not throw
{
__esModule: true,
getBaseUrl: (),
__proto__: Object
}
Original that throws
{
__esModule: (...)
get __esModule: ()
set __esModule: ()
getBaseUrl: (...)
get getBaseUrl: ()
set getBsaeUrl: ()
_proto__: Object
}
Update
I found the snippet of code in system.js where the difference in import occurs. In my larger original project loader.defined[name]; returned undefined and the fresh copy of aurelia loader.defined[name]; is defined...still have not found a workaround
system.src.js
function getModule(name, loader) {
var exports;
var entry = loader.defined[name];
if (!entry) {
exports = loader.get(name);
if (!exports)
throw new Error('Unable to load dependency ' + name + '.');
}
else {
if (entry.declarative)
ensureEvaluated(name, entry, [], loader);
else if (!entry.evaluated)
linkDynamicModule(entry, loader);
exports = entry.module.exports;
}
if ((!entry || entry.declarative) && exports && exports.__useDefault)
return exports['default'];
return exports;
}
i have a project on Angularjs which covered by unit tests with help of bower and jasmine. Every thing worked fine until I added a new module (angular-treeview). Module works fine in browser but not in Phantomjs while testing. The js is missing by some reason. Here is my gulp task for test :
'use strict';
var gulp = require('gulp');
var wiredep = require('wiredep');
var karmaServer = require('karma').Server;
/**
* Run the unit tests
*/
gulp.task('test', ['templates'], function() {
var bowerDeps = wiredep({
directory: 'src/bower_components',
exclude: [],
dependencies: true,
devDependencies: true
});
bowerDeps.js.unshift('src/bower_components/jquery/dist/jquery.js');
var testFiles = bowerDeps.js.concat([
'src/app/app.js', // loading the module first to make Karma avoid nomod-errors
'src/{app,components}/**/*.js',
'.tmp/templates/*.js', // HTML-templates converted to JS for directives/etc
'test/unit/**/*.js'
]);
new karmaServer({
files: testFiles,
singleRun: false,
autoWatch: true,
configFile: __dirname + '/../test/karma.conf.js'
}).start();
});
angular-treeview is in src/bower_components but is still missing.
Any ideas?
I want to build a quick nodejs script to package a Typescript app as SystemJS modules, a lot like what Angular2 bundles look like.
I tried different configurations but I can't seem to put my finger on it, and haven't found clear enough documentation as of yet.
Note that for this "test", I am not using Gulp or Jspm at all, just systemjs-builder for the time being (and don't plan on using jspm at all either)
Here's what my "project" looks like:
---- Project's Root
-------- index.ts // export * from './modules/index' and eventually more
-------- modules
------------ index.ts // export * from './menu/index'
------------ menu
---------------- menu.component.ts // export class
---------------- menu.service.ts // export class
I want to package this under a single file, where I will have multiple SystemRegister modules that can be consumed in an app thereafter
I tried the following without success:
var Builder = require('systemjs-builder');
// optional constructor options
// sets the baseURL and loads the configuration file
var builder = new Builder('./modules');
builder.bundle('./modules/index.ts', {
/* SystemJS Configuration Here */
baseURL: './modules',
transpiler: 'typescript',
typescriptOptions: {
"module": "system",
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
defaultExtension: 'ts',
packages: {
'modules': {
defaultExtension: 'ts'
}
}
}, 'infrastructure.js')
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.error(err);
})
First of all, the defaultExtension options doesn't seem to work at all
So when I do import {something} from 'filePath'; (without extension), it tries to load filePath, instead of filePath.ts;
Second, if I try adding the .ts extension in my imports (which I don't want to do), it complains that the code is invalid (unexpected token #, unexpected token menuItem and so forth)
Anyone have a good example or some explanations on how this is supposed to work?
Thank you
here you have an example: angular typescript skeleton
build task looks like this:
const path = require('path');
const Builder = require('jspm').Builder;
const builder = new Builder();
const packageJson = require(path.join(config.projectDir, 'package.json'));
return beginBuild()
.then(buildSFX)
.catch((err) => console.log('Build Failed', err));
function beginBuild() {
builder.reset();
return builder.loadConfig(path.join(config.projectDir, packageJson.jspm.configFile))
}
function buildSFX() {
const appName = packageJson.name;
const distFileName = `${appName}.min.js`;
const outFile = path.join(config.distDir, distFileName);
const moduleName = 'app';
const buildConfig = {
format: 'global',
minify: true,
sourceMaps: true
};
return builder.buildStatic(moduleName, outFile, buildConfig);
}
and jspm conf looks like this:
System.config({
defaultJSExtensions: true,
transpiler: "typescript",
typescriptOptions: {
"tsconfig": "src/tsconfig.json"
},
paths: {
"github:*": "vendor/jspm_packages/github/*",
"npm:*": "vendor/jspm_packages/npm/*",
"app": "src/index"
}
/// ...
}
Why do you want to bundle typescript? Bundling is a method used for optimizing the delivery of source code to the browser. The browser doesn't know typescript, it only knows javascript (unless you do on the fly transpiling).
Background: I am compiling 2 dependent TypeScript files to js, which produces also source maps (one source map per file) using tsc 1.0
I'm using -m commonjs and then use browserify to generate a single bundle.js
However I noticed that I get the original source map references twice in the bundle, which doesn't seem to work.
Passing --debug doesn't seem to do the trick either.
I had a feeling this issue: https://github.com/substack/node-browserify/issues/325 is somewhat related, but I couldn't figure out how the issue was resolved.
Also https://github.com/substack/browser-pack was suggested, but again I don't fully understand how to use it, is it a replacement to browserify?
Bottom line, I would like to merge the 2 js files but "merge" the js to ts source maps using browserify. Is that possible?
tsify is a browserify plugin that is better and replaces e.g. typescriptifier.
npm install tsify browserify watchify
You use tsify like this:
browserify src/index.ts -p tsify --debug -o build/index.js
Notice that this supports browserify --debug switch, no extra tricks required. So you can also use it with watchify like this:
watchify src/index.ts -p tsify --debug -o build/index.js
Using the minifyify browserify plugin I believe you can use TypeScript with Browserify and retain the source maps. After compiling the TypeScript files you should be able to pass the "entry" file (the one that imports the other one via commonjs syntax) through browserify with the minifyify plugin.
var browserify = require('browserify'),
bundler = new browserify();
bundler.add('entry.js');
bundler.plugin('minifyify', {map: 'bundle.js.map'});
bundler.bundle({debug: true}, function (err, src, map) {
if (err) console.log(err);
fs.writeFileSync('bundle.js', src);
fs.writeFileSync('bundle.js.map', map);
});
Here is my working solution:
var settings = {
projectName : "test"
};
gulp.task("bundle", function() {
var mainTsFilePath = "src/main.ts";
var outputFolder = "bundle/src/";
var outputFileName = settings.projectName + ".min.js";
var pkg = require("./package.json");
var banner = [
"/**",
" * <%= pkg.name %> v.<%= pkg.version %> - <%= pkg.description %>",
" * Copyright (c) 2015 <%= pkg.author %>",
" * <%= pkg.license %>",
" */", ""
].join("\n");
var bundler = browserify({
debug: true,
standalone : settings.projectName
});
// TS compiler options are in tsconfig.json file
return bundler.add(mainTsFilePath)
.plugin(tsify)
.bundle()
.pipe(source(outputFileName))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(header(banner, { pkg : pkg } ))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(outputFolder));
});
I created example project.
You can run it with $(npm bin)/gulp build --env=dev for development environment and source maps will be generated.
There is gulpfile.js:
'use strict';
var path = require('path'),
gulp = require('gulp'),
del = require('del'),
typescript = require('gulp-typescript'),
sourcemaps = require('gulp-sourcemaps'),
browserify = require('browserify'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer'),
uglify = require('gulp-uglify'),
gutil = require('gulp-util'),
inject = require('gulp-inject'),
babel = require('gulp-babel'),
argv = require('yargs').argv;
var devEnvironment = 'dev',
prodEnvironment = 'prod',
environment = argv.env || prodEnvironment,
isDevelopment = environment === devEnvironment;
var projectPath = __dirname,
srcDir = 'src',
srcPath = path.join(projectPath, srcDir),
buildDir = path.join('build', environment),
buildPath = path.join(projectPath, buildDir),
distDir = 'dist',
distRelativePath = path.join(buildDir, distDir),
distPath = path.join(buildPath, distDir);
var tsSrcPath = path.join(srcPath, 'typescript'),
tsGlob = path.join(tsSrcPath, '**', '*.ts'),
tsBuildPath = path.join(buildPath, 'tsc');
var indexHtmlName = 'index.html',
indexJsName = 'index.js';
var distIndexJsPath = path.join(distPath, 'index.js'),
distIndexHtmlPath = path.join(distPath, indexHtmlName);
var tsProject = typescript.createProject('tsconfig.json');
console.log('Environment: ' + environment);
gulp.task('clean', function () {
return del([buildPath]);
});
gulp.task('tsc', ['clean'], function () {
var stream = gulp.src([tsGlob]);
if (isDevelopment) {
stream = stream
.pipe(sourcemaps.init());
}
stream = stream
.pipe(typescript(tsProject))
.pipe(babel({
presets: ['es2015']
}));
if (isDevelopment) {
stream = stream.pipe(sourcemaps.write({sourceRoot: tsSrcPath}));
}
return stream.pipe(gulp.dest(tsBuildPath));
});
gulp.task('bundle', ['tsc'], function () {
var b = browserify({
entries: path.join(tsBuildPath, indexJsName),
debug: isDevelopment
});
var stream = b.bundle()
.pipe(source(indexJsName))
.pipe(buffer());
if (!isDevelopment) {
stream = stream.pipe(uglify());
}
return stream
.on('error', gutil.log)
.pipe(gulp.dest(distPath));
});
gulp.task('build', ['bundle'], function() {
return gulp.src(path.join(srcPath, indexHtmlName))
.pipe(inject(gulp.src([distIndexJsPath], {read: false}), {ignorePath: distRelativePath, addRootSlash: true}))
.pipe(gulp.dest(distPath));
});
You should pay attention to lines:
stream = stream.pipe(sourcemaps.write('', {sourceRoot: tsSrcPath})); - write inline source maps with sourceRoot pointing to your typescript sources path. Inline maps are written directly to .js files generated by tsc to build/dev/tsc.
debug: isDevelopment - in development environment make browserify generate his own source maps for resulting bundle build/dev/dist/index.js file so it will have source maps referencing .js files from build/dev/tsc which in turn have source maps referencing .ts files from src/typescript.
With this setup you will be able to see and debug .ts files in browser:
I faced similar issue when trying to debug my Angular2 app running in Chrome in Visual Studio Code (Using Debugger for Chrome extension)
I use gulp as my task runner and my setup is as follows:
Typescript files -> tsc -> intermediate es5 js -> browserify (plus uglify in production build) -> compiled bundle
My directory structure is as follows:
|- src
|- my .ts files here
|- main.ts - my entry file
|- dist
|- intermediate files go here
|- web
|- app.js - final bundle
|- app.js.map - final bundle map
|- gulpfile.js
gulpfile.js:
var gulp = require('gulp'),
tsc = require('gulp-typescript'),
browserify = require('browserify'),
uglify = require('gulp-uglify'),
sourcemaps = require('gulp-sourcemaps'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer');
gulp.task('tsc', [], () => {
return gulp.src(['src/**/*.ts'])
.pipe(sourcemaps.init())
.pipe(tsc({
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [ "es2015", "dom" ],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
}))
.pipe(sourcemaps.write(null, {
"sourceRoot": function(file) {
let parts = file.relative.split('\\');
let root = Array(parts.length + 1).join('../') + 'src';
return root;
}
}))
.pipe(gulp.dest('dist/'));
});
gulp.task('bundle', ['tsc'], () => {
let b = browserify({
entries: 'dist/main.js',
debug: true,
});
return b.bundle()
.pipe(source('app.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(sourcemaps.write('./', {
"sourceRoot": "../",
}))
.pipe(gulp.dest('web/'));
})
gulp.task('default', ['bundle']);
Explanation/reasoning:
For some reason browserify doesn't read and parse .js.map files linked in .js file (via special comment at the end) but it does when the source map is embedded in js file. So, by passing null instead of path to sourcemaps it will embed it at the end of generated .js file.
Next issue I noticed was that sourcemaps doesn't automatically follow directory structure (add '../' to sourceRoot when it goes to next directory level), so I made a quick function to complement this. Keep in mind that it only works on Windows - on Linux you'd have to change split character.
function(file) {
let parts = file.relative.split('\\'); // put '/' here on Linux
let root = Array(parts.length + 1).join('../') + 'src';
return root;
}
Certainly there is a way to detect correct path separator, I'm debugging only on Windows thus it's not important for my purposes.
I hope it helps someone, cause I've spent whole Sunday morning tracking down this problem.