The Problem
I am attempting to run a Cucumber test using a Karma test runner in my Npm project using the karma-cucumber-js adapter. However, when running my test, I find the following error in my console:
START:
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
ReferenceError: Can't find variable: __adapter__
at features/Test.steps.js:80
For more context, I am in the middle of a platform migration. We had a complex system in place previously that essentially used karma 1.7.x, cucumber 1.2.x, karma-cucumber-js 0.3.3, and Node 0.8.x. I am trying to set up a simple npm project with the same exact versions (except now I'm using Node 8.x as I am not allowed to use 0.8.x). We have a suite of thousands of old tests that we'd like to minimize modifications for, and it would be easiest to get the karma-cucumber-js plugin working due to how tightly coupled our test system is with both karma and cucumber.
Things I've Tried
I played around with the dependent karma-cucumber-js source code a bit by tweaking the code in my package's node_modules directory as an attempt to better understand the issue at hand. I was able to bypass the issue above by modifying these lines in adapter.js to globalize the adapter variable in the window as follows:
var __adapter__;
(function (win) {
var adapter = new karma.CucumberAdapter(__karma__);
__adapter__ = adapter;
__karma__.start = adapter.getStart();
win.__adapter__ = __adapter__;
})(window);
Which lead to the next error:
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
ReferenceError: Can't find variable: Cucumber
at node_modules/karma-cucumber-js/src/adapter.js:242
Which I worked around by adding the following line of code to the top of that very file after 'use strict':
var Cucumber = require('../../cucumber/release/cucumber.js');
Which lead to this issue:
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
ReferenceError: Can't find variable: CucumberHTML
at node_modules/karma-cucumber-js/src/adapter.js:177
And the workaround was to manually require that file adapter.js as well:
var CucumberHTML = require('../../cucumber-html/src/main/resources/cucumber/formatter/formatter.js');
With this "hack" in place, the cucumber tests are now able to run successfully:
START:
PhantomJS 2.1.1 (Mac OS X 0.0.0) LOG: 'Found features: /base/features/Test.feature'
PhantomJS 2.1.1 (Mac OS X 0.0.0) LOG: 'Tags: '
Is it Friday yet?
Friday is Friday
✔ Given today is Friday
✔ When I ask whether it's Friday yet
✔ Then I should be told "TGIF"
Finished in 0.002 secs / 0.002 secs # 19:36:12 GMT-0700 (PDT)
SUMMARY:
✔ 3 tests completed
The underlying issue seems to be that [these Typescript variables][4] declared at the end of the karma-cucumber-js packages are, for some reason, not available to use. Which I believe is due to a webpack wiring issue.
Some other things I've tried:
Using other karma-cucumber adapters (there are 2 others), no luck.
Playing around with karma/phantomjs/cucumber version combinations
Using Firefox and Chrome in replacement of PhantomJS
My questions
I need help understanding why this webpack setup is not working. How can I fix this?
Are there any steps I'm missing or alternative approaches I should be taking to debug and resolve the issue at hand?
I've included some of the project code below, thank you for your time!
Project Code
package.json:
{
"name": "npm-pretty-much-local-example",
"version": "1.0.0",
"scripts": {
"wp": "webpack",
"wpd": "webpack --debug",
"test": "./node_modules/karma/bin/karma start"
},
"devDependencies": {
"#babel/core": "^7.7.2",
"#babel/preset-env": "^7.7.1",
"#babel/preset-react": "^7.7.0",
"babel-loader": "^8.0.0",
"#babel/preset-typescript": "^7.7.x",
"babel-generator": "^6.26.1",
"babel-core": "^6.26.3",
"cucumber": "^1.2.x",
"jquery": "^3.4.1",
"karma": "^1.7.x",
"karma-cucumber-js": "^0.3.3",
"karma-mocha-reporter": "^2.0.5",
"karma-phantomjs-launcher": "^1.0.x",
"karma-webpack": "^1.7.x",
"socket.io": "^1.4.x",
"webpack": "^3.7.1",
"setimmediate": "^1.0.5",
"karma-typescript-preprocessor": "^0.4.0"
},
"dependencies": {}
}
webpack.config.js:
const path = require('path');
module.exports = {
context: path.resolve('.'),
entry: './src/index.js',
output: {
filename: "./dist/output.js"
},
resolve: {
extensions: ['.js'],
modules: [
path.resolve('./src'),
path.resolve('./node_modules')
]
}
};
Test.feature:
#Test
Feature: Is it Friday yet?
Everybody wants to know when it's Friday
Scenario: Friday is Friday
Given today is Friday
When I ask whether it's Friday yet
Then I should be told "TGIF"
Test.steps.js:
function isItFriday(today) {
if (today === "Friday") {
return "TGIF";
} else {
return "Nope";
}
}
// TODO: why is this not defined, and how was __adapter__ defined in the first place?
__adapter__.addStepDefinitions(function (scenario) {
scenario.Given('today is {string}', function (givenDay) {
this.today = givenDay;
});
scenario.When('I ask whether it\'s Friday yet', function () {
this.actualAnswer = isItFriday(this.today);
});
scenario.Then('I should be told {string}', function (expectedAnswer) {
return this.actualAnswer === expectedAnswer;
});
});
src/index.js
var dummyVar = "";
Related
I'm attempting to transpile Salesforce Commerce Cloud's .ds files to JavaScript so we can apply standard testing tools (Jest, Mocha, etc.). The SFCC docs indicate that .ds files are "Rhino JavaScript", with a non-standard extension for Flow-like type checking.
So far, stripping out the type annotations has been simple, using the transform-flow-strip-types plugin. But SFCC supports a deprecated "for each...in" statement from JavaScript 1.6 that Babel is choking on.
All code below is available on github.
Here's my source src/index.ds file:
function dump(a: Array) {
for each (var x in a) {
console.log(x);
}
}
module.exports = dump;
And my gulfile.js:
const gulp = require('gulp');
const babel = require('gulp-babel');
gulp.task('test', function () {
gulp.src('src/**/*.ds')
.pipe(babel())
.pipe(gulp.dest('dst'));
});
And this is my package.json:
{
"name": "dspoc",
"version": "1.0.0",
"description": "poc",
"main": "index.ds",
"author": "cjr",
"license": "ISC",
"devDependencies": {
"babel": "^6.23.0",
"babel-core": "^6.26.3",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"gulp": "^3.9.1",
"gulp-babel": "^7.0.1"
},
"babel": {
"plugins": [
"transform-flow-strip-types"
]
}
}
When I run gulp test, I get this:
%> gulp test
[11:23:06] Using gulpfile ~/dev/dspoc/gulpfile.js
[11:23:06] Starting 'test'...
[11:23:06] Finished 'test' after 9.15 ms
events.js:163
throw er; // Unhandled 'error' event
^
SyntaxError: /Users/craser/dev/dspoc/src/index.ds: Unexpected token, expected ( (2:5)
1 | function dump(a: Array) {
> 2 | for each (var x in a) {
| ^
3 | console.log(x);
4 | }
5 | }
at Parser.pp$5.raise (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:4454:13)
at Parser.pp.unexpected (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:1761:8)
at Parser.pp.expect (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:1749:33)
at Parser.pp$1.parseForStatement (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:2008:8)
at Parser.pp$1.parseStatement (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:1836:19)
at Parser.parseStatement (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:5910:22)
at Parser.pp$1.parseBlockBody (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:2268:21)
at Parser.pp$1.parseBlock (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:2247:8)
at Parser.pp$3.parseFunctionBody (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:4235:22)
at Parser.parseFunctionBody (/Users/craser/dev/dspoc/node_modules/babylon/lib/index.js:5897:20)
I've spent quite a bit of time digging for a plugin that will let Babel transpile this to something like the for...of statement, but I can't seem to find anything.
I'm now at the precipice of digging into the for-of transform was built and creating something similar to transform for each...in, but I really don't want to have to put that work in if I can avoid it.
I feel like I'm missing something obvious here. Anyone know how this can be done?
for each...in was never an official part of the spec and didn't exist by the time Babel came around, so it is not supported by Babel. I'm afraid you've have to update all usage of that syntax before Babel will be able to process it.
I have installed Visual Studio 2015 (with no other previous versions) on a new laptop and have pulled down the source for our MVC web app. We have a gulp file with tasks to compile our less and typescript.
When running this task ...
cmd.exe /c gulp -b "C:\Code\Trunk\MyProj\MyProj.Web" --color --gulpfile "C:\Code\Trunk\MyProj\MyProj.Web\Gulpfile.js" typescript
... I get the following error:
[09:43:16] Using gulpfile C:\Code\Trunk\MyProj\MyProj.Web\Gulpfile.js
[09:43:16] Starting 'typescript'...
[09:43:34] Plumber found unhandled error:
Error: UNKNOWN, open 'C:\Code\Trunk\MyProj\MyProj.Web\app\allergy\main.js'
Process terminated with code 0.
Here is the task in the gulp file (with other parts removed for brevity):
var gulp = require("gulp");
var plumber = require("gulp-plumber");
var sourcemaps = require("gulp-sourcemaps");
var typescript = require("gulp-typescript");
var merge = require("merge2");
var paths = {
typescript: {
globpatterns: {
all: "./Scripts/**/*.ts",
excludedefinitions: "!./Scripts/**/*.d.ts"
}
}
};
gulp.task("typescript", function () {
var result = gulp.src([
paths.typescript.globpatterns.all,
paths.typescript.globpatterns.excludedefinitions
])
.pipe(plumber())
.pipe(sourcemaps.init())
.pipe(typescript({
removeComments: true,
declarationFiles: false,
noImplicitAny: false,
noEmitOnError: true,
module: "amd",
target: "ES5"
}));
return merge([
result.js.pipe(gulp.dest("./")),
result.pipe(sourcemaps.write()).pipe(gulp.dest("./"))
]);
});
My colleague has the same set-up as me and gets no error.
Typescript is set to version 1.0 in the project file (<TypeScriptToolsVersion>1.0</TypeScriptToolsVersion>) and I can't change this just now. I wondered if the reason was beacuse I don't have this version installed on my machine but my colleague doesn't either. C:\Program Files (x86)\Microsoft SDKs\TypeScript only has a folder for 1.7
I noticed that the task completes successfully if I remove either of the 2 lines with in the merge block.
It's a different .js file in the error message each time
I searched the web to see what the UNKNOWN error even means but couldn't find anything obvious / helpful. Anyone know how to fix this error? Or how I go about finding out why it's being thrown?
EDIT 20-Jan-2016
So, I was getting this error consistently for about a week ... and now it has stopped happening. I haven't made any changes to my development environment either. I'd like to leave this question open since I'm curious as to why this happened.
I am developing a web project using ES 6 in combination with the Babel transpiler and System.js as module loader. In all browsers from IE 9 up, that works well, unfortunately I have to support IE 8 though.
In the unbundled file, IE 8 can't even load my main.js file. It fails with the following console message without indicating any line of code.
Potentially unhandled rejection [4] SyntaxError: Error loading "main" at http://localhost:8080/assets/js/main.js
Error loading "npm:babel-core#5.8.22" at http://localhost:8080/assets/libs/npm/babel-core#5.8.22.js
expected identifier
I am using jspm as a dependency manager. The bundled sfx file built with jspm bundle-sfx yields a different error:
cannot read property "call" of undefined
Here, at least a line is given, it points to the following function of the system.js core:
function forEachGlobal(callback) {
iterateGlobals(function(globalName) {
if (indexOf.call(ignoredGlobalProps, globalName) != -1)
return;
try {
var value = loader.global[globalName];
}
catch(e) {
ignoredGlobalProps.push(globalName);
}
callback(globalName, value);
});
}
indexOf is indeed undefined here when logging it to the console, although it shouldn't, because it is defined earlier in the file.
The only relevant additional info I can give you is my package.json:
{
// some metadata
"devDependencies": {
"jspm": "^0.15.7",
"jspm-bower-endpoint": "^0.3.2",
// some more grunt tasks
},
"jspm": {
"directories": {
"baseURL": "source",
"packages": "source/assets/libs"
},
"dependencies": {
// frontend libraries
},
"devDependencies": {
"babel": "npm:babel-core#^5.1.13",
"babel-runtime": "npm:babel-runtime#^5.1.13",
"core-js": "npm:core-js#^0.9.4"
},
}
}
Officially, both system.js and babel support IE 8. I couldn't find everyone else with this issue, so I hope someone can help me solving that issue.
Thanks in advance!
I will preface this by saying I am very new to using Ember (1 week) and JS frameworks in general but have been developing .Net WebAPIs and building by own JS front ends for a few years.
I've looked everywhere and can't seem to find any clues on how to debug this issue. I recently integrated Semantic-UI into my app and was able to use it fine for a little while. However, this morning my application started throwing a 404 when trying to access the bundled stylesheet.
I've tried reverting to previous versions and I've even run ember init neither of which resolved the issue.
Currently, I am trying to just create a new app, but am facing issues on that front as well...
$ ember version
version: 1.13.8
node: 0.12.7
npm: 2.13.4
os: win32 x64
bower.json:
"dependencies": {
"ember": "1.13.7",
"ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
"ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
"ember-data": "1.13.8",
"ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5",
"ember-qunit": "0.4.9",
"ember-qunit-notifications": "0.0.7",
"ember-resolver": "~0.1.18",
"jquery": "^1.11.3",
"loader.js": "ember-cli/loader.js#3.2.1",
"qunit": "~1.18.0",
"semantic-ui": "~2.0.8"
}
EDIT:
Below is my ember-cli-build.js file:
/* global require, module */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
lessOptions: {
paths: [
'bower_components/semantic-ui'
]
}
});
return app.toTree();
};
I can't even create a new ember project in a new directory now to validate this because I keep getting the following error:
EPERM, rename 'C:\Users\me\AppData\Roaming\npm-cache\debug\2.2.0\package\package.json'
Error: EPERM, rename 'C:\Users\me\AppData\Roaming\npm-cache\debug\2.2.0\package\package.json'
at Error (native)
I set up grunt to run node.js jasmine tests. For some reason, with this config, the results always show double the tests.
Here is my config:
I'm using jasmine-node which plugs into grunt.
/spec/some-spec.js:
var myModule = require('../src/myModule.js');
describe('test', function(){
it('works', function(done){
setTimeout(function(){
expect(1).toBe(1);
done();
}, 100);
});
});
Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({
jasmine_node: {
options: {
forceExit: true
},
all: ['spec/']
}
});
grunt.loadNpmTasks('grunt-jasmine-node');
grunt.registerTask('default', ['jasmine_node']);
};
This results in two tests running rather than one.
> grunt
Running "jasmine_node:all" (jasmine_node) task
..
Finished in 0.216 seconds
2 tests, 2 assertions, 0 failures, 0 skipped
I was able to reproduce the behavior. This is what seems to be happening:
The task looks in the specified folder (spec in your case) for files with spec in the name.
Then it looks again in every folder in the whole project for files with spec in the name.
What it ends up with is 2 overlapping sets of test files to run.
My first attempt at trying to coerce it into more logical behavior was to set specNameMatcher: null (default is 'spec'), and leave the folder set to 'spec/'. This results in no tests being run, since apparently both conditions (name and folder) must be met for files in the specified folder. You get the same problem if specNameMatcher is left at the default value, but the files in the folder don't have 'spec' in the name.
What does work is to set the folder (or 'test set' or whatever you want to call it) to []:
jasmine_node: {
options: {
forceExit: true
},
all: []
}
The catch is that if you have any other files somewhere else in the project with 'spec' in the name, they'll be mistaken for tests by jasmine.
I would consider this behavior a bug, and it should probably be reported via the project's github issues page.
This grunt plugin ( https://github.com/jasmine-contrib/grunt-jasmine-node ) seems to be dead ( https://github.com/jasmine-contrib/grunt-jasmine-node/issues/60 ).
Maybe it is a better to switch to https://github.com/onury/grunt-jasmine-nodejs ?
The jasmine-node project is pretty old. The latest commit is from July of 2014. The grunt-jasmine-node plugin appears to be active, but running against something that is going stale seems a little pointless IMHO.
To test CommonJS modules using Jasmine I'd recommend using Karma along with the
karma-jasmine and karma-commonjs plugins. I got your example working with the following files:
package.json
{
"private": "true",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-jasmine-node": "^0.3.1",
"grunt-karma": "^0.10.1",
"jasmine-core": "^2.3.4",
"karma": "^0.12.31",
"karma-commonjs": "0.0.13",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.1.4"
}
}
karma.conf.js
module.exports = function(config) {
config.set({
basePath: '.',
frameworks: ['jasmine', 'commonjs'],
files: [{
pattern: 'src/**/*.js'
}, {
pattern: 'spec/**/*.js'
}],
preprocessors: {
'src/**/*.js': ['commonjs'],
'spec/**/*.js': ['commonjs']
},
reporters: ['progress'],
browsers: ['PhantomJS']
});
};
Gruntfile.js (optional if you still want to use grunt)
module.exports = function(grunt) {
grunt.initConfig({
karma: {
unit: {
configFile: 'karma.conf.js',
options: {
singleRun: true
}
}
}
});
grunt.loadNpmTasks('grunt-karma');
grunt.registerTask('default', ['karma:unit']);
};
You should also install the karma command line runner globally, just like you probably did with grunt. npm install -g karma-cli
From your command line you can start karma by typing karma start. It will run the tests and then watch your files and re-run them on every save. (VERY NICE)
Alternatively you can run karma start --single-run to have it just run your tests once and exit. If you also updated your Gruntfile you can also just run grunt to run the tests once.
The current up voted answer isn't the solution. You simply modify the expression that's going to match your tests. The answer is as follows:
module.exports = function(grunt) {
grunt.initConfig({
jasmine_node: {
options: {
forceExit: true
},
all: ['spec/*spec.js']
}
});
grunt.loadNpmTasks('grunt-jasmine-node');
grunt.registerTask('default', ['jasmine_node']);
};
Here you can see that 'all' is set to *'spec/spec.js'. This will search for all tests.
Secondly, just because a project hasn't had a recently commit, doesn't mean it's "old". jasmine-node is simply stable.
I have the same issue using grunt-jasmine-node, and as aeryaguzov points out, that project is no longer maintained. Switching to grunt-jasmine-node-new solves the issue for me.
grunt-jasmine-node-new is a fork of grunt-jasmine-node that is actively maintained, and can be found here: https://www.npmjs.com/package/grunt-jasmine-node-new