Chutzpah does not let me reference a function with <reference path - node.js

I am trying to use Jasmine, via NodeJs and Chutzpah to test the javascript in my project. This is in Visual Studio
The Jasmine test looks like
/// <reference path ='../../net5.Ui/wwwroot/Shared/Javascript/helpers.js' />
describe('Helpers test', function () {
it('Test contains', function () {
const result = helpers.isMatch();
expect(result).toBe(true);
});
});
My javascript files all have a similar structure (a singleton approach)
const helpers = new function(){
this.isMatch = function(){ return true; }
}
Visual Studio is able to detect the tests.
Node version 14.15.4
UPDATE
(I have stripped some of my original post as it's no longer valuable)
I have even removed the <reference path> and replaced it with chutzpah.json at the root of the project with
{
"Framework": "jasmine",
"References": [
{
"Path": "../../net5.Ui/wwwroot/Shared/Javascript/",
"Include": "*.js",
"Exclude": "*app.js"
}
],
"Tests": [
{
"Path": "Tests/",
"Includes": [ "*Spec.js" ]
}
]
}

ES6 features are only partially implemented in IE 11, that is why you get those errors about Invalid character. Template literals $ that you refer to are not implemented. Check more about the compatibility here https://kangax.github.io/compat-table/es6/#ie11
Depending on how you have set up your testing environment, you can change the browser that runs those tests to a different one, like Chrome or Firefox. For example if you use Karma as your test runner, you need to install the npm plugin karma-chrome-launcher and configure karma.conf.js so it uses Chrome.
You haven't given details about your testing environment, but it looks like you are still setting it up, so you could continue using Jasmine as your testing framework and additionally use Karma as your test runner and the free Visual Studio plugin Chutzpah Test Adapter, which enables you to run JavaScript unit tests from the command line and from inside of Visual Studio.
This will require a bit of effort for setting it up from your side, however I there is a very detailed guide about how to integrate all these here.

Related

How to import a node module inside an angular web worker?

I try to import a node module inside an Angular 8 web worker, but get an compile error 'Cannot find module'. Anyone know how to solve this?
I created a new worker inside my electron project with ng generate web-worker app, like described in the above mentioned ng documentation.
All works fine until i add some import like path or fs-extra e.g.:
/// <reference lib="webworker" />
import * as path from 'path';
addEventListener('message', ({ data }) => {
console.log(path.resolve('/'))
const response = `worker response to ${data}`;
postMessage(response);
});
This import works fine in any other ts component but inside the web worker i get a compile error with this message e.g.
Error: app/app.worker.ts:3:23 - error TS2307: Cannot find module 'path'.
How can i fix this? Maybe i need some additional parameter in the generated tsconfig.worker.json?
To reproduce the error, run:
$ git clone https://github.com/hoefling/stackoverflow-57774039
$ cd stackoverflow-57774039
$ yarn build
Or check out the project's build log on Travis.
Note:
1) I only found this as a similar problem, but the answer handles only custom modules.
2) I tested the same import with a minimal electron seed which uses web workers and it worked, but this example uses plain java script without angular.
1. TypeScript error
As you've noticed the first error is a TypeScript error. Looking at the tsconfig.worker.json I've found that it sets types to an empty array:
{
"compilerOptions": {
"types": [],
// ...
}
// ...
}
Specifying types turns off the automatic inclusion of #types packages. Which is a problem in this case because path has its type definitions in #types/node.
So let's fix that by explicitly adding node to the types array:
{
"compilerOptions": {
"types": [
"node"
],
// ...
}
// ...
}
This fixes the TypeScript error, however trying to build again we're greeted with a very similar error. This time from Webpack directly.
2. Webpack error
ERROR in ./src/app/app.worker.ts (./node_modules/worker-plugin/dist/loader.js!./src/app/app.worker.ts)
Module build failed (from ./node_modules/worker-plugin/dist/loader.js):
ModuleNotFoundError: Module not found: Error: Can't resolve 'path' in './src/app'
To figure this one out we need to dig quite a lot deeper...
Why it works everywhere else
First it's important to understand why importing path works in all the other modules. Webpack has the concept of targets (web, node, etc). Webpack uses this target to decide which default options and plugins to use.
Ordinarily the target of a Angular application using #angular-devkit/build-angular:browser would be web. However in your case, the postinstall:electron script actually patches node_modules to change that:
postinstall.js (parts omitted for brevity)
const f_angular = 'node_modules/#angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js';
fs.readFile(f_angular, 'utf8', function (err, data) {
var result = data.replace(/target: "electron-renderer",/g, '');
var result = result.replace(/target: "web",/g, '');
var result = result.replace(/return \{/g, 'return {target: "electron-renderer",');
fs.writeFile(f_angular, result, 'utf8');
});
The target electron-renderer is treated by Webpack similarily to node. Especially interesting for us: It adds the NodeTargetPlugin by default.
What does that plugin do, you wonder? It adds all known built in Node.js modules as externals. When building the application, Webpack will not attempt to bundle externals. Instead they are resolved using require at runtime. This is what makes importing path work, even though it's not installed as a module known to Webpack.
Why it doesn't work for the worker
The worker is compiled separately using the WorkerPlugin. In their documentation they state:
By default, WorkerPlugin doesn't run any of your configured Webpack plugins when bundling worker code - this avoids running things like html-webpack-plugin twice. For cases where it's necessary to apply a plugin to Worker code, use the plugins option.
Looking at the usage of WorkerPlugin deep within #angular-devkit we see the following:
#angular-devkit/src/angular-cli-files/models/webpack-configs/worker.js (simplified)
new WorkerPlugin({
globalObject: false,
plugins: [
getTypescriptWorkerPlugin(wco, workerTsConfigPath)
],
})
As we can see it uses the plugins option, but only for a single plugin which is responsible for the TypeScript compilation. This way the default plugins, configured by Webpack, including NodeTargetPlugin get lost and are not used for the worker.
Solution
To fix this we have to modify the Webpack config. And to do that we'll use #angular-builders/custom-webpack. Go ahead and install that package.
Next, open angular.json and update projects > angular-electron > architect > build:
"build": {
"builder": "#angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./extra-webpack.config.js"
}
// existing options
}
}
Repeat the same for serve.
Now, create extra-webpack.config.js in the same directory as angular.json:
const WorkerPlugin = require('worker-plugin');
const NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
module.exports = (config, options) => {
let workerPlugin = config.plugins.find(p => p instanceof WorkerPlugin);
if (workerPlugin) {
workerPlugin.options.plugins.push(new NodeTargetPlugin());
}
return config;
};
The file exports a function which will be called by #angular-builders/custom-webpack with the existing Webpack config object. We can then search all plugins for an instance of the WorkerPlugin and patch its options adding the NodeTargetPlugin.

writing nodejs applications in kotlin with intellij idea ce

I am trying to develop a Nodejs application using Kotlin 1.3.11 using the IntelliJ IDEA CE development environment. Unfortunately I haven't made any progress towards a running application. To ensure everything is setup correctly I want to print out a simple "hello world".
I searched for articles or tutorials about the topic but I didn't find much about bringing those three together (Kotlin, IntelliJ, Nodejs). The most specific ones which I found are:
a medium post and another post.
As far as I (believe to) know, there are three major steps:
calling initializing the node app via npm and using npm to install the node dependencies like kotlin and expressjs
creating a build.gradle to define other dependencies and tasks
creating an IntelliJ IDEA project
I tried to perform the steps in different orders but I never came to a running application. Also I searched in IntelliJ's documentation but the Nodejs integration isn't a feature of the free community edition. There isn't a description how to make Kotlin and Nodejs work together too.
Has anyone here successfully tried to do that (or failed and knows why it is not going to work)? Do I have to use another IDE or to write my own build tools/toolchain?
Sincerely J.
I haven't done this in IDEA CE, but theoretically, this should work.
Prerequisites: You have node installed, you can execute gradle tasks
This is a Minimum Configuration, There is a comprehensive one. Add a comment if intrested for that
Step 1:Create a new Kotlin/JS project (with gradle) and make sure that your gradle build file looks like this
group 'node-example'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.3.11'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin2js'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}
task npmInit(type: Exec) {
commandLine "npm", "init", "-y"
}
task npmInstall(type: Exec) {
commandLine "npm", "install", "kotlin", "express", "--save"
}
task npmRun(type: Exec) {
commandLine "node", "node/index.js"
}
npmRun.dependsOn(build)
Step 2: After syncing your build.gradle in step 1 run the gradle tasks npmInit and npmInstall
./gradlew :npmInit
./graldew :npmInstall
Step 3:
Create your kotlin file (index.kt/main.kt/whatever.kt) in src/main/kotlin and test the code below
external fun require(module:String):dynamic
fun main(args: Array<String>) {
println("Hello JavaScript!")
val express = require("express")
val app = express()
app.get("/", { req, res ->
res.type("text/plain")
res.send("Kotlin/JS is kool")
})
app.listen(3000, {
println("Listening on port 3000")
})
}
Step 4: RTFA - Run The App
Run the gradle task npmRun
./gradlew :npmRun
Hope that helps
Note:
1. This template was pulled from the medium post you asked above and modified a little
2. Remember to run your gradle tasks using sudo (if you are using linux)
Edit: Alternatively, you could clone https://github.com/miquelbeltran/kotlin-node.js and follow the instructions in the read me.
I managed to get the Medium post to work by replacing gradle build with the following (since the post was published in 2017(!) and requires a much older version of Gradle):
Comment out the entire contents of build.gradle like so:
/*group 'node-example'
...
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}*/
Run this command in the command prompt: (3.4.1 was the latest version of Gradle just before the Medium post was published.)
gradle wrapper --gradle-version=3.4.1
Uncomment out build.gradle:
group 'node-example'
...
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "node/index.js"
}
Run this command in place of gradle build:
gradlew build
And finally run this command as in the post: (As of writing this answer on StackOverflow, Node.js does not be downgraded and the current LTS version 10.16.0 works perfectly.)
node node/index.js

Mocha - Running test ReferenceError: regeneratorRuntime is not defined

I am trying to run tests with async/await using mocha. The project architecture was setup before I started working on it and I have been trying to update it's node version to 8.9.4. The project is an isomorphic application and uses babel, gulp and webpack to run.
To run the tests we run a gulp task. There are two .bablerc files in the project. One in the root folder of the project and another in the test fodler.
Both have the same configuration:
{
"presets": [
["env", {"exclude": ["transform-regenerator"]}],
"react",
"stage-1"
],
"plugins": [
"babel-plugin-root-import"
]
}
When I run the app locally there is no error returned anymore. However when I run the tests with gulp test:api I constantly get the error: ReferenceError: regeneratorRuntime is not defined
This is my gulp file in the test folder:
var gulp = require('gulp')
var gutil = require('gulp-util')
var gulpLoadPlugins = require('gulp-load-plugins')
var plugins = gulpLoadPlugins()
var babel = require('gulp-babel')
require('babel-register')({
presets:["es2015", "react", "stage-1"]
});
// This is a cheap way of getting 'test:browser' to run fully before 'test:api' kicks in.
gulp.task('test', ['test:browser'], function(){
return gulp.start('test:api')
});
gulp.task('test:api', function () {
global.env = 'test'
gulp.src(['test/unit-tests/server/**/*.spec.js'], {read: false})
.pipe(plugins.mocha({reporter: 'spec'}))
.once('error', function (error) {
console.log(error)
process.exit(1);
})
.once('end', function () {
process.exit(0);
})
});
gulp.task('default', ['test']);
Any help on why this is happening wouldd be much appreciated.
Node version 8 already has support for async/await so you do not need Babel to transform it; indeed, your root .babelrc includes this preset to exclude the regenerator that would transform async/await (and introduce a dependency on regeneratorRuntime):
["env", {"exclude": ["transform-regenerator"]}]
However, in your test file, the configuration does not specify this preset. Instead, it specifies the preset "es2015", which does include the unwanted transform-regenerator (as you can see at https://babeljs.io/docs/plugins/preset-es2015/). If you change this to match the presets in the root .babelrc, you'll get more consistent results.
Strangely i ran into this issue after i upgraded to Node v8.10.0 from v8.6.x . I had used babel-require like so in my test-setup.js
require('babel-register')();
and the testing tools are Mocha,chai,enzyme + JSDOM . I was getting the same issue when i was making a async call to a API, also while using generator functions via sagas. Adding babel-polyfill seemed to have solved the issue.
require('babel-register')();
require('babel-polyfill');
i guess even babel docs themselves advocate using polyfill for generators and such
Polyfill not included
You must include a polyfill separately when using features that require it, like generators.
Ran into the same issue when running mocha tests from within Visual Studio Code.
The solution was to add the necessary babel plugins in the Visual Studio Code settings.json :
"mocha.requires": [
"babel-register",
"babel-polyfill"
],
I've run into this error before myself when using async/await, mocha, nyc, and when attempting to run coverage. There's never an issue when leveraging mocha for running tests, just with mocha tests while leveraging nyc for running coverage.
11) Filesystem:removeDirectory
Filesystem.removeDirectory()
Should delete the directory "./tmp".:
ReferenceError: regeneratorRuntime is not defined
at Context.<anonymous> (build/tests/filesystem.js:153:67)
at processImmediate (internal/timers.js:461:21)
You can fix the issue a couple of different ways.
Method 1 - NPM's package.json:
...
"nyc": {
"require": [
"#babel/register",
"#babel/polyfill"
],
...
},
...
It really depends which polyfill package you're using. It's recommended to use the scoped (#babel) variant: #babel/pollyfill. However, if you're using babel-polyfill then ensure that's what you reference.
Method 2 - Direct Import
your-test-file.js (es6/7):
...
import '#babel/polyfill';
...
OR
your-test-file.js (CommonJS):
...
require("#babel/polyfill");
...
Don't assign it to a variable, just import or require the package. Again, using the package name for the variant you've sourced. It includes the polyfill and resolves the error.
HTH

how to use chutzpah in current project

I am going through setting up chutzpah and Jasmine for unit testing my project in typescript.
I have installed Jasmine using npm but I am quite confused how to include chutzpah in visual studio code.
I went to this GitHub but nothing is clear to me:-
https://github.com/mmanela/chutzpah
Also, I downloaded files for visual studio code from below sources:-
https://marketplace.visualstudio.com/items?itemName=vs-publisher-2795.ChutzpahTestRunnerContextMenuExtension
https://marketplace.visualstudio.com/items?itemName=vs-publisher-2795.ChutzpahTestAdapterfortheTestExplorer
When I try to load above-downloaded files as an extension in visual code I get the error:-
extension/package.json not found inside zip.
How to include or install chutzpah in my project and then use the chutzpah.json file?
Thanks in advance.
First from command line go to you project location and do:
npm init
this will create package.json
Than:
chuzpah.json you can create manually and run at first from Visual Studio with right click, if you installed plugin properly, you will see run Unit tests option.
Seting up chutzpah.json is tricky part.
here is template for setup:
{
"Framework": "qunit|jasmine|mocha",
"FrameworkVersion": "",
"EnableTestFileBatching": "true|false",
"InheritFromParent": "true|false",
"InheritFromPtah": "<Path to another chutzpah.json>",
"IgnoreResourceLoadingErrors": "true|false"
"TestFileTimeout": "<Timeout in milliseconds>",
"TestHarnessLocationMode": "TestFileAdjacent|SettingsFileAdjacent|Custom",
"TestHarnessDirectory": "<Path to a folder>",
"TestHarnessReferenceMode": "Normal|AMD",
"RootReferencePathMode":"DriveRoot|SettingsFileDirectory",
"CodeCoverageIncludes": [],
"CodeCoverageExcludes": [],
"CodeCoverageIgnores": [],
"CodeCoverageExecutionMode": "Manual|Always|Never",
"CodeCoverageSuccessPercentage": <Number from 0 to 100>,
"CodeCoverageTimeout": <Timeout in milliseconds>
"References": [],
"Tests": [],
"CustomTestHarnessPath": "<Path to custom test harness file>",
"Compile": <A compile configuration object>,
"Server": <A server configuration object>,
"TestPattern": "<Regex test name pattern>",
"AMDBaseUrl": "<Path to same location that your Require.js config baseurl points to>",
"AMDAppDirectory": "<The root folder for your AMD paths>",
"UserAgent": "<Custom user agent to use during testing>",
"Transforms": [],
"EnableTracing": true|false,
"TraceFilePath": "<Path to log file. Defaults to %temp%/chutzpah.log>",
"Parallelism": "<Max degree of parallelism for Chutzpah. Defaults to number of CPUs>",
"BrowserArguments": <A map of browser name (keys) to corresponding browser arguments (values), i.e.; { 'chrome': '--allow-file-access-from-files' }.>
}
After all, you can use commang line and Chutzpah runner to run you unit test as part of CI

Create and use Babel plugin without making it a npm module

In my project, I'm using Babel 6 with the require hook. I need to load a custom babel plugin that I wrote. But do I really need to publish my plugin using npm first, and then include the plugin name in my main project's .babelrc?
Is there any way to just directly load the plugin code? In other words, can I just load the following directly?
export default function({types: t }) {
return {
visitor: {
...
}
};
}
Where you list your plugins in your .babelrc, provide the path to your plugin instead of your standard published plugin name.
"plugins": ["transform-react-jsx", "./your/plugin/location"]
When exporting your plugin function, you'll probably need to use module.exports = instead of export default, since ES2015 modules haven't been fully implemented in Node yet.
This is my entire babel.config.js file.
module.exports = function (api) {
api.cache(true);
const presets = ["#babel/preset-env", "#babel/preset-react"];
const plugins = [
["#babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }],
"c:\\projects\\my-babel-plugin"
];
return {
presets,
plugins
};
}
First item in the plugins array is a plugin with options in form of an array. Second item is my own local plugin.
Inside of my-babel-plugin folder there needs to be a package.json with the "main" entry, usually "main": "lib/index.js" or "main": "src/index.js".

Resources