Karma unit test for ES6 modules with babel - javascript

I'm following instructions from karma-babel-preprocessor to set up unit tests in a project I'm currently working, but I always the error
'require is not defined'
My karma.conf.js is as follows:
files: [
{ pattern: './test/unit/*.spec.js', watched: true },
{ pattern: './src/js/es6_modules/*.js', watched: false },
],
preprocessors: {
'./src/js/es6_modules/*.js': ['babel'],
'./test/unit/*.spec.js': ['babel'] //, 'coverage'
},
babelPreprocessor: {
options: {
presets: ['es2015'],
sourceMap: 'inline'
},
filename: function (file) {
return file.originalPath.replace(/\.js$/, '.es5.js');
},
sourceFileName: function (file) {
return file.originalPath;
}
}
The scripts in src/js/es6_modules jave ES6 classes exported. Something like:
export default class MyClass {
}
And my spec file would need to import this
import { MyClass } from "../../src/js/es6_modules/myclass";
I have seen some thread here at SO that said I would need to use browserify, but I can't find any doc (or example) on how to use it together with babel in karma. Does anyone know to configure this properly?

I fixed it using browserify instead of babel, and using a babelify transform
preprocessors: {
'./src/js/es6_modules/*.js': ['browserify'],
'./test/unit/*.spec.js': ['browserify']
},
browserify: {
debug: true,
"transform": [
[
"babelify",
{
presets: ["es2015"]
}
]
]
},

Related

Babel module resolver not working with react-native

My babel module resolver is not working with React-Native (neither does intellij in VScode)
Here, Is my babel config
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./'],
alias: {
'#assets': './src/assets',
'#modules': './src/modules',
'#config': './src/config',
'#utils': './src/utils',
},
},
],
],
};
And jsconfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"#assets": ["./assets"],
"#modules": ["./modules"],
"#config": ["./config"],
"#utils": ["./utils"]
}
}
}
I changed import for one of my files and this is the error I get when I executed the build command from Xcode
Error: Error loading assets JSON from Metro. Ensure you've followed
all expo-updates installation steps correctly. Unable to resolve
module ../../modules/store/components/Filters from
src/utils/Router.js:
None of these files exist:
Where I imported the file like this
import Filters from '#modules/store/components/Filters';
I had the same problem, I just removed the '#' from my aliases and it seems working fine now.
Here is my babel.config.js
module.exports = function (api) { ■ File is a CommonJS module; it may be converted to an ES6 module.
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
[
require.resolve("babel-plugin-module-resolver"),
{
root: ["./src/"],
alias: {
// define aliases to shorten the import paths
components: "./src/components",
containers: "./src/containers",
contexts: "./src/contexts",
interfaces: "./src/interfaces",
organizer: "./src/screens/organizer",
screens: "./src/screens",
},
extensions: [".js", ".jsx", ".tsx", ".ios.js", ".android.js"],
},
],
],
};
};
Try resetting the cache, if above suggested answers don't work
react-native start --reset-cache
This worked for me. For more info see here
Change your module-resolver's root to ['./src/']:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./src/'], // <-- here ✅
alias: {
'#assets': './src/assets',
'#modules': './src/modules',
'#config': './src/config',
'#utils': './src/utils',
},
},
],
],
};

Rollup is not generating typescript sourcemap

I am using rollup with svelte + typescript + scss. My problem is that I am not able to generate source maps.
Following is my rollup config file:
import svelte from 'rollup-plugin-svelte'
import resolve from '#rollup/plugin-node-resolve'
import commonjs from '#rollup/plugin-commonjs'
import livereload from 'rollup-plugin-livereload'
import { terser } from 'rollup-plugin-terser'
import typescript from '#rollup/plugin-typescript'
import alias from '#rollup/plugin-alias'
const production = !process.env.ROLLUP_WATCH
const path = require('path').resolve(__dirname, 'src')
const svelteOptions = require('./svelte.config')
function serve() {
let server
function toExit() {
if (server) server.kill(0)
}
return {
writeBundle() {
if (server) return
server = require('child_process').spawn(
'yarn',
['run', 'start', '--', '--dev'],
{
stdio: ['ignore', 'inherit', 'inherit'],
shell: true,
}
)
process.on('SIGTERM', toExit)
process.on('exit', toExit)
},
}
}
export default {
input: 'src/main.ts',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js',
},
plugins: [
alias({
entries: [
{ find: '#app', replacement: `${path}` },
{ find: '#components', replacement: `${path}/components` },
{ find: '#includes', replacement: `${path}/includes` },
{ find: '#styles', replacement: `${path}/styles` },
{ find: '#pages', replacement: `${path}/pages` },
],
}),
svelte(svelteOptions),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte'],
}),
commonjs(),
typescript({ sourceMap: !production }),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser(),
],
watch: {
clearScreen: false,
},
}
I am not sure what exactly am I doing wrong. Here is the link to code I am using.
Any help will be deeply appreciated!
This is what worked for me: you need to set sourceMap: false in the typescript rollup plugin options.
export default {
input: 'src/main.ts',
output: {
sourcemap: true,
format: 'iife',
...
},
plugins: [
...
svelte(...),
typescript({ sourceMap: false }),
...
]
}
It turns out rollup's sourcemap collapser conflicts with the typescript's plugin sourcemap generator. That's why it works on prod builds but not in dev builds (because originally it is sourceMap: !production). Just let rollup do the heavy lifting.
As also mentioned by others, it seems like the combination of TypeScript and Rollup leads to the problem. Disabling the source map in TypeScript only fixes the problem of mapping Svelte to TypeScript. However you only receive a source map showing source in the compiled JavaScript, not in the original TypeScript. I finally found a solution, that worked for me: Just add the Option inlineSources: true to the TypeScript options:
typescript({ sourceMap: !production, inlineSources: !production }),
This circumvents the problem by simply not creating a duplicate SourceMap, but by copying the source code from TypeScript into the SourceMap.
For anyone using terser, not svelte, this solved the same problem for me:
import sourcemaps from 'rollup-plugin-sourcemaps';
import { terser } from 'rollup-plugin-terser';
import typescript from '#rollup/plugin-typescript';
export default [
{
input: 'dist/index.js',
output: [
{
file: 'dist/cjs/index.js',
format: 'cjs'
},
{
file: 'dist/fesm2015/index.js',
format: 'es'
}
],
plugins: [
sourcemaps(),
terser(),
typescript({ sourceMap: true, inlineSources: true })
]
}
];
Apparently rollup-plugin-sourcemaps is needed to do the magic necessary to utilize the map files generated by the TypeScript compiler and feed them to terser.
For me, I am able to map, by making sourcemap: "inline"
In the /build/index.esm.js file will have mapping inside.
export default {
input: "src/index.ts",
output: [
{
file: 'build/index.esm.js',
format: 'es',
sourcemap: "inline"
},
],
plugins: [
typescript({ sourceMap: false, inlineSources: true }),
]
}
I was having a similar issue with Karma, rollup, and typescript. I fixed it by adding "sourceRoot":"/base/" to my tsconfig.json file.
Before: map file entries pointed to /src/.
After: map file entries pointed to /base/src/ and everything worked.
// tsconfig.rollup.json
"compilerOptions": {
"module": "ES2022",
"esModuleInterop": true,
"target": "ES2022",
"moduleResolution": "classic",
"sourceMap": true,
"sourceRoot": "/base/"
...
}
// rollup.config.js
import typescript from '#rollup/plugin-typescript';
export default [
{
input: './src/test/test_context.spec.ts',
output: {
file: './dist/test/test_context.spec.js',
format: 'es',
sourcemap: 'inline'
},
plugins: [
typescript({
tsconfig: './tsconfig.rollup.json'
})
]
}
];

Webpack renames functions

Hello i have some problems with webpack. I have this config for webpack
module.exports = {
name: "front",
mode: "production",
context: path.resolve(__dirname, 'src'),
entry: [
'./jquery/photoswipe.addon_offer_and_order.min.js',
'./jquery/photoswipe.min.js',
'./jquery/photoswipe-ui-default.min.js',
'./deprecated.js',
'./index.js',
],
output: {
filename: "index.min.js",
path: path.resolve(__dirname, 'dist')
},
optimization: {
moduleIds: 'named'
}
}
All good but i have a deprecated.js and have all deprecated functions in it...
Example:
function updateSearchCharacteristic(url, category_id) {
console.warn("This method is deprecated please use shopSearch.updateCharacteristic()");
return shopSearch.updateCharacteristic(url, category_id);
}
function moveBlockAnfrageGuest() {
console.warn("This method is deprecated please use shopUser.moveOrderAndOfferLinkForGuest()");
return shopUser.moveOrderAndOfferLinkForGuest();
}
Webpack rename all these functions, if someone used the old functions, he does not see errors and the return does not work ..
How not to rename functions in this file, but compress
I resolved this problem :
npm install -D script-loader terser-webpack-plugin
Added a module into config and 'require' a plugin
const TerserPlugin = require('terser-webpack-plugin')
module: {
rules: [
{
test: /deprecated.js/,
use : [
{
loader: 'script-loader',
options:{
plugins: [
new TerserPlugin({
terserOptions: {
keep_fnames: true,
}
})
]
}
}
]
}
]
}

'Unexpected string' when running karma with webpack/babel

I'm trying to run karma using webpack to preprocess code with babel that can then be tested with mocha. However whenever I run it I get errors.
spec/tests.spec.js:
import 'chai/register-expect';
karma.conf.js:
const webpackConfig = require('./webpack.config.js');
const tests = './spec/**/*.spec.js'
module.exports = function(config) {
config.set({
singleRun: true,
browsers: ['Chrome'],
frameworks: ['mocha'],
files: [
tests
],
preprocessors: {
tests: ['webpack'],
},
webpack: webpackConfig,
})
}
webpack.config.js:
module.exports = {
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', {
'modules': false
}]
}
}
]
}
}
When I run karma I get the following output:
'Uncaught SyntaxError: Unexpected string\nat http://localhost:9876/base/spec/tests.spec.js?af68737606dd067ef21aa6efadfc004fb1d05454:1:8\n
Which corresponds to the import line.
If I remove all es6 code from the test, then it runs successfully, implying that webpack/babel isn't being invoked properly.
Any ideas why this isn't working?
So it was nothing to do with any of the tools, and turned out to be a JS gotcha.
In karma.conf.js I was doing:
const tests = './spec/**/*.spec.js'
...
preprocessors: {
tests: ['webpack'],
}
The problem here is that tests as an object key translates to the string "tests".
The solution was to use:
preprocessors: {
[tests]: ['webpack'],
}
So that tests gets expanded properly to the variable value.

Babel Brunch doesn't seems to compile #polymer/lit-element module

I'm trying to integrate Lit-element into brunch. However, it seems like Babel plugin doesn't try to compile the lit-element module into the output, as it still use the original ES6 syntax of import / export.
Here's my brunch config :
`
exports.config = {
// See http://brunch.io/#documentation for docs.
files: {
javascripts: {
// joinTo: 'js/app.js'
joinTo: {
'js/app.js': [
/^node_modules/,
/\app.js$/
],
'js/editor.js': [
/\editor.js$/
],
'js/select.js': [
/select.js$/,
]
}
},
stylesheets: {
joinTo: 'css/app.css',
order: {
after: ['../priv/static/css/app.scss'] // concat app.css last
}
},
templates: {
joinTo: 'js/app.js'
}
},
conventions: {
// This option sets where we should place non-css and non-js assets in.
// By default, we set this to '/web/static/assets'. Files in this directory
// will be copied to `paths.public`, which is 'priv/static' by default.
assets: /^(web\/static\/assets)/
},
// Phoenix paths configuration
paths: {
// Dependencies and current project directories to watch
watched: [
'static', 'css', 'js', 'vendor'
],
// Where to compile files to
public: '../priv/static'
},
// Configure your plugins
plugins: {
babel: {
// Do not use ES6 compiler in vendor code
},
sass: {
mode: 'native'
},
uglify: {
mangle: false,
compress: {
global_defs: {
DEBUG: false
}
}
}
},
modules: {
autoRequire: {
"js/app.js": ["js/app"]
}
},
npm: {
enabled: true
}
}
Here is my app.js code
import {LitElement, html} from '#polymer/lit-element'
function autoComplete(options){ ... }
export var App = {
autoComplete
}
And last is the compiled code, along with console log :
...
require.register("#polymer/lit-element/lit-element.js", function(exports, require, module) {
require = __makeRelativeRequire(require, {}, "#polymer/lit-element");
(function() {
import { PropertiesMixin } from '#polymer/polymer/lib/mixins/properties-mixin.js';
// "Uncaught SyntaxError: Unexpected token {" on above line
import { camelToDashCase } from '#polymer/polymer/lib/utils/case-map.js';
import { render } from 'lit-html/lib/shady-render.js';
export { html, svg } from 'lit-html/lib/lit-extended.js';
...

Categories