WebStorm using ES6 import with CommonJS module - webstorm

I'm using WebStorm and want to use ES6 import instead of require. However when using import with libraries that use CommonJS like lodash I get a warning from WebStorm "cannot resolve symbol".
The code work perfectly as babel transform the import to require, I just want WebStorm to play along and not showing any error. I don't want to partly use ES6 import and partly require.
I'm using WebStorm version 2016.2.2.

webstorm can resolve es6 imports from CommonJS modules, but just in cases when modules are exported explicitly, like module.exports = module_name; or similar; but lodash modules are exposed in a tricky way:
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
var moduleExports = freeModule && freeModule.exports === freeExports;
...
var _ = runInContext();
...
if (freeModule) { (freeModule.exports = _)._ = _; freeExports._ = _; }
that's why WebStorm can't find modules there...

Related

How do I access ENV from config/environment in an addon?

This is a question that was asked by #dbendaou over on the Ember Discord
What is the best way to access ENV from config/envirnoment in an addon?
I was thinking about getOwner(this).lookup('config:environment') but it doesn't work
neither does import ENV from '../config/environment'; 😅
From addons, specifically, since your context doesn't define the environment, you need a slightly different API:
import { getOwner } from '#ember/application';
// ....
export default class MyAddonComponent extends Component {
get env() {
getOwner(this).resolveRegistration('config:environment')
}
}
import ENV from '../config/environment' is an alias for import ENV from '<app-name>/config/environment'; which, addons can't know what the <app-name> is.
Maybe related, because this has come up a number of times in the discord, is that this would also be how you get access to environment variables at runtime.
environment.js is a build-time file, so it has access to the node environment your app builds in and it outputs a JSON object for your app to consume.
For example:
// <your-app>/config/environment.js
const MY_ENV_VAR = process.env;
module.exports = function (environment) {
let ENV = {
// ...
MY_ENV_VAR,
};
return ENV;
}
Then, your addon can access MY_ENV_VAR via resolveRegistration. and apps can access it via the import.
Apps:
import ENV from '<app-name>/config/environment'
// ...
ENV.MY_ENV_VAR
Addons:
getOwner(this).resolveRegistration('config:environment').MY_ENV_VAR;

Is there anyway to let WebStorm understand the aliases in .eslinrc made using eslint-import-resolver-alias

In my project, I used eslint-import-resolver-alias for imports like below in .eslintrc:
{
"settings":{
"alias": [
["pckg", "pckg/src"]
]
}
}
And I use as below in my .js files
import pckg from 'pckg'
But when I try to find the declaration using a Cmd+Click by clicking on 'pckg' in the import statement, WebStorm says that there is no declaration to go to. I realize that WebStorm is not able to understand the import alias resolver plugin, but is there anyway to make it work
You can try using webpack aliases instead: create a dummy webpack configuration file with aliases like
...
alias: {
'pckg': path.resolve(__dirname, './pckg/src'),
},
...
and specify a path to it in Settings | Languages & Frameworks | JavaScript | Webpack, or use a workaround from https://youtrack.jetbrains.com/issue/WEB-22717#focus=streamItem-27-1558931-0-0:
create a file config.js (you can use a different name if you like) in your project root dir
define your aliases there using the following syntax:
System.config({
"paths": {
"pckg/*": "./pckg/src/*"
}
});

How to mock global Vue.js variable in JEST test

I have a global property/variable with my app urls:
Vue.prototype.$apiUrls = {
root: 'http://localhost:8080/',
api: 'api/v1/'
// etc.
}
I use it inside my components as axios request:
axios.get(`${this.$apiUrls.root}${this.$apiUrls.api}/users/`)
Now I want to test my component's code, I've mocked axios already, but still I receive an error:
TypeError: Cannot read property '$apiUrls' of undefined
I've tried to define/mock this property inside each test and/or in JEST's setup file, like e.g.
global.$apiUrls = {...}
// or
Vue.prototype.$apiUrls = {...}
// or
Object.defineProperties(Vue.prototype, {$apiUrls: {...}})
I've also tried mocking it to window or this (yeah, thats silly), but with no success - I still receive that error - please help.
There is two ways to achieve this. One is using the Config option, as mentioned by #Aldarund. You can read about it here.
If you are using Jest, I recommend doing this in the jest.init.js file:
import { config } from '#vue/test-utils'
config.mocks['$apiUrls'] = {
'some/endpoint'
}
Then add this to the jest section of your package.json:
"setupFiles": [
"<rootDir>/jest.init.js"
]
Now it is globally mocked. If you want to do this on a per test basis, you can use the mocks mounting option:
const wrapper = shallowMount(Foo, {
mocks: {
$apiUrls: 'some/endpoint'
}
})
Hopefully this helps!
If you are interested I am compiling a collection of simple guides on how to test Vue components here. It's under development, but feel free to ask make an issue if you need help with other related things to testing Vue components.
I don't think the answers above work anymore (in 2020).
Here's what worked for me:
For vue-test-utils 1.x.x (Vue 2)
Create a new file, name it eg. jest.init.js
Give it the following content:
import { config } from "#vue/test-utils";
config.mocks["yourGlobalProperty"] = label => label; //you can replace it with your own mock
Add this to your jest.config.js (actually write "rootDir", don't replace anything with a real path)
module.exports = {
setupFiles: ["<rootDir>/jest.init.js"]
}
These files will be only ran before jest runs unit tests.
Note that I'm importing {config}, not the default export. I don't know why the default didn't work for me. Even the documentation for vue test utils doesn't import the default export anymore
Also make sure you're not trying to import from the old vue-test-utils package. (The new one is #vue/test-utils)
For #vue/test-utils 2.x.x (vue-test-utils-next) (Vue 3)
Follow steps like for 1.x.x above, but in step two, do this instead:
import { config } from "#vue/test-utils"; //2.0.0-beta.5
config.global.mocks = {
yourGlobalProperty: label => label
};
You can do it with vue-test-utils beta 15 and later.
Here docs
And some example would be:
import VueTestUtils from '#vue/test-utils'
VueTestUtils.config.mocks['$apiUrls'] = {
...
}

TypeScript UnitTests on Module

I want to run unit tests in typescript. I have a simple folder structure where directory app contains an app.ts like following
export module app {
export class Config {
testMe() {
return "Hallo";
}
}
}
The unit tests that lies in directory test:
import app = require('../app/conf');
import * as chai from 'chai';
var config = new app.app.Config();
chai.expect(config.testMe()).to.equals("Hallo");
As TypeScripts documentation states in http://www.typescriptlang.org/Handbook#modules-pitfalls-of-modules when TypeScript code is used as an external module it does not make sense to use the module concept at all.
As you can see app.app.Config is not a very elegant way.
I can only run my unit tests on compiled TypeScript code. So I can only use modules if I don't care about unit tests or is there a simpler way?
Have app.ts:
export class Config {
testMe() {
return "Hallo";
}
}
and test.ts:
import app = require('../app/conf');
import * as chai from 'chai';
var config = new app.Config();
chai.expect(config.testMe()).to.equals("Hallo");
And if your original code worked, so will this. No more app.app and no more needless internal modules.

WebStorm Marking Files as Invalid when using Require

I' using the latest release version of webstorm (9.03) and most of my JavaScript files show up as invalid. I'm showing the code below.
'use strict';
function SpeakerDetailsController (speaker, CONFIG, $sce, $scope) {
this.speaker = speaker;
this.showSessions = CONFIG.showSessions === 'True';
$scope.someSafeContent = $sce.trustAsHtml("<i>Hello</i> <b>World!</b>");
}
SpeakerDetailsController.$inject = ['speaker', 'CONFIG', '$sce', '$scope'];
export default SpeakerDetailsController;
Please make sure to set JavaScript Language Version to 'ECMAScript 6' (or 'JSX Harmony') in Settings/Languages&Frameworks/JavaScript to get ES6 syntax correctly recognized.