h is not defined error while running test cases in preact - babeljs

I have a preact application which uses #testing-library/preact library for test cases. When I try to run a test for a component it throws an error stating that h is not defined. The app works without the import statement in the components but the test cases doesn't work. I get the it is required for converting jsx to h() calls. But is there any way to avoid it so that I don't have to import it in every component in the app ? PS: I tried to configure babel with this plugic babel-plugin-jsx-pragmatic for automatic import but it didn't work. This is my .babelrc file.
{
"plugins": [
["plugin-transform-react-jsx", {
"runtime": "automatic",
"importSource": "preact"
}]
]
}

Related

Jest stranspiles code differently then ts-node

I can't make my code work when running the project normally and running in Jest.
Running the project requires this kind of imports for dayjs:
import * as dayjs from 'dayjs';
import * as utc from 'dayjs/plugin/utc';
import * as customParseFormat from 'dayjs/plugin/customParseFormat';
npm run dev (nodemon --exec ./node_modules/.bin/ts-node ./src/app.ts): No issues
Jest: TypeError: t is not a function
Running the Jest tests requires this kind of imports for dayjs:
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import customParseFormat from 'dayjs/plugin/customParseFormat';
npm run dev (nodemon --exec ./node_modules/.bin/ts-node ./src/app.ts):
dayjs.extend(utc);
^
TypeError: Cannot read property 'extend' of undefined`
Jest: Success!
So now it is impossible for me to write Tests. Why is it transpiled differntly?
In my case,
tsconfig.json
{
"compilerOptions": {
"esModuleInterop": true
}
}
solved it.
I switched to ts-jest and it solved my problem. I was assuming that I could write JS tests to test the TS code but I suppose that is not possible.

Vue import failing

I've created a vue application scaffolded from the vue cli. Almost everything is reacting as expected with my app except for an issue with import.
The following works fine:
import Vuex from 'vuex';
but, this throws errors:
import { VuetronVue, VuetronVuex } from 'vuetron';
vue.use(VuetronVue);
Linting error:
"export 'VuetronVue' was not found in 'vuetron'
and Console error:
Uncaught TypeError: Cannot read property 'install' of undefined
Changing the code to:
import vuetron from 'vuetron'
vue.use(vuetron.VuetronVue);
resolves the issue...
This original code was taken directly from the Vuetron documentation. Does anyone have a suggestion as to why the ES6 notation would cause an issue?
This seems to be because
vuetron/packages/vuetron-plugins/index.js
only exports the default object:
import VuetronVue from './vuetron-vue';
import VuetronVuex from './vuetron-vuex';
export default {
VuetronVue,
VuetronVuex
};
For named imports as stated in the docs you would need a named export.

unable to specify path to javascript file in Karma

My JS file (which I need to test) is /JasmineTest/src/mySource.js. It has myObj object
myObj={
setA:function(value){
a=value;
},
getA:function(){
return a;
},
};
My Jasmine spec file is /JasmineTest/spec/mySpec.js. It tests myObj
describe("Jasmine sample suite",function(){
it("tracks that spy was called",function(){
expect(myObj.getA).toHaveBeenCalled();
});
In karma, I have specified the spec file location as
files: [
'spec/*.js'
],
when I start Karma in /JasmineTest, the test gives error
Chrome 60.0.3112 (Windows 10 0.0.0) Jasmine sample suite tracks that spy was called FAILED
ReferenceError: myObj is not defined
at UserContext.<anonymous> (spec/mySpec.js:4:9)
I tried exporting myObj module.exports = myObj; and importing it in spec file using require('../src/mySource.js') but I got error require is not defined
How do I make myObj visible in the specs file?
Karma doesn't know how to do module requiring unless you configure it specially to do bundling. In general I would expect to use the same sort of bundling in Karma as you do for your web app, so Webpack or Browserify or similar.
Another way is to list mySource.js in under the "files" field in karma.conf.js, which will just execute it and put myObj in as a global, but that doesn't scale very well.

how do you get flow to work with babel module-alias?

I am trying to get flow to type check my code but it is giving me an error when it can't find paths that have been rewritten using babel-plugin-module-alias.
I have unsuccessfully tried to use the resolve_dirname option in the flowconfig.
Can someone please tell me if it is possible to use this babel plugin with flow?
.babelrc
{
"plugins": [
"transform-flow-strip-types",
["module-alias", [
{ "src": "./app", "expose": "app" },
]]
]
}
.flowconfig
[options]
module.system.node.resolve_dirname=app
app/main.js
import bar from 'app/foo';
app/main.js:3
3: import bar from 'app/foo';
^^^^^^^^^^ app/foo. Required module not found
module.system.node.resolve_dirname actually tells Flow where to start resolving things from. If you want Flow to resolve starting from 'app', you need to point it one directory higher than app.
Alternatively, you can probably also use `module.name_mapper='^app/([a-z-A-Z0-9$_/]+)$' -> 'src/\1'
Here is how this can be achieved with module.name_mapper setting in .flowconfig [options]. Works in flow version 0.56.0
module.name_mapper='^app/\([-a-zA-Z0-9$_/]+\)$' -> '<PROJECT_ROOT>/src/\1'

How can I use my webpack's html-loader imports in Jest tests?

I am just getting started with the Jest test framework and while straight up unit tests work fine, I am having massive issues testing any component that in its module (ES module via babel+webpack) requires a HTML file.
Here is an example:
import './errorHandler.scss';
import template from './errorHandler.tmpl';
class ErrorHandler {
...
I am loading the component specific SCSS file which I have set in Jest's package.json config to return an empty object but when Jest tries to run the import template from './errorHandler.tmpl'; line it breaks saying:
/Users/jannis/Sites/my-app/src/scripts/errorHandler/errorHandler.tmpl.html:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<div class="overlay--top">
^
SyntaxError: Unexpected token <
at transformAndBuildScript (node_modules/jest-runtime/build/transform.js:284:10)
My Jest config from package.json is as follows:
"jest": {
"setupTestFrameworkScriptFile": "<rootDir>/test/setupFile.js",
"moduleDirectories": ["node_modules"],
"moduleFileExtensions": ["js", "json", "html", "scss"],
"moduleNameMapper": {
"^.+\\.scss$": "<rootDir>/test/styleMock.js"
}
}
It seems that the webpack html-loader is not working correctly with Jest but I can't find any solution on how to fix this.
Does anyone know how I can make these html-loader imports work in my tests? They load my lodash template markup and i'd rather not have these at times massive HTML chunks in my .js file so i can omit the import template from x part.
PS: This is not a react project, just plain webpack, babel, es6.
I encountered this specific problem recently and creating your own transform preprocesser will solve it. This was my set up:
package.json
"jest": {
"moduleFileExtensions": [
"js",
"html"
],
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.html$": "<rootDir>/test/utils/htmlLoader.js"
}
}
NOTE: babel-jest is normally included by default, but if you specify a custom transform preprocessor, you seem to have to include it manually.
test/utils/htmlLoader.js:
const htmlLoader = require('html-loader');
module.exports = {
process(src, filename, config, options) {
return htmlLoader(src);
}
}
A bit late to the party, but wanted to add that there is also this html-loader-jest npm package out there to do this if you wanted to go that route.
Once you npm install it you will add it to your jest configuration with
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.html?$": "html-loader-jest"
}
For Jest > 28.x.x with html-loader:
Create a custom transformer as documented here.
jest/html-loader.js
const htmlLoader = require("html-loader");
module.exports = {
process(sourceText) {
return {
code: `module.exports = ${htmlLoader(sourceText)};`,
};
},
};
Add it to your jest config.
jest.config.js
...
// A map from regular expressions to paths to transformers
transform: {
"^.+\\.html$": "<rootDir>/jest/html-loader.js",
},
...
It will fix the error : Invalid return value: process() or/and processAsync() method of code transformer found at "<PATH>" should return an object or a Promise resolving to an object.
Maybe your own preprocessor file will be the solution:
ScriptPreprocessor
Custom-preprocessors
scriptpreprocessor: The path to a module that provides a synchronous function from pre-processing source files. For example, if you wanted to be able to use a new language feature in your modules or tests that isn't yet supported by node (like, for example, ES6 classes), you might plug in one of many transpilers that compile ES6 to ES5 here.
I created my own preprocessor when I had a problems with my tests after added transform-decorators-legacy to my webpack module loaders.
html-loader-jest doesn't work for me. My workaround for this:
"transform": {
'\\.(html)$': '<rootDir>/htmlTemplateMock.html'
}
htmlTemplateMock.html is empty file
For Jest 28+ you can use jest-html-loader to make Jest work with code that requires HTML files.
npm install --save-dev jest-html-loader
In your jest config, add it as a transformer for .HTML files:
"transform": {
"^.+\\.html?$": "jest-html-loader"
},