I saw the way to suppress this with jsLint, tried it, it did not work.
I need the 'new' keyword or my script does notwork.
How can I suppress it in .eslintrc?
Many Thanks
Update: Per Jordan's request.
[Please note my app is written in ReactJs]
// 3rd party
const AnimateSlideShow = require('../js-animation');
export default class Animate extends React.Component {
.......
fetchJsAnimation() {
const animation = this.refs.Animation;
new AnimateSlideShow(animation);
}
......
}
Error: Do not use 'new' for side effects no-new
Now, if I satisfy EsLint, my app craps out:
Uncaught (in promise) TypeError: Cannot set property '_handleMouse' of undefined(…)
Here's the documentation for the ESLint rule in question: http://eslint.org/docs/rules/no-new.html
Disallow new For Side Effects (no-new)
The goal of using new with a constructor is typically to create an object of a particular type and store that object in a variable, such as:
var person = new Person();
It's less common to use new and not store the result, such as:
new Person();
In this case, the created object is thrown away because its reference isn't stored anywhere, and in many cases, this means that the constructor should be replaced with a function that doesn't require new to be used.
I pasted that above because I think it's important to understand what the intent of the rule is, and not just how to make it go away.
If you can't find a way to get rid of new, you can suppress this error with the eslint-disable directive:
fetchJsAnimation() {
/* eslint-disable no-new */
const animation = this.refs.Animation;
new AnimateSlideShow(animation);
}
ESLint directives are block-scoped, so it will be suppressed inside this function only. You can also suppress rules on a single line with the eslint-disable-line directive:
new AnimateSlideShow(animation); // eslint-disable-line no-new
// You can disable the check on the next line as well.
// eslint-disable-next-line no-new
new AnimateSlideShow(animation);
If you really need to disable this rule for your entire project, then in your .eslintrc's "rules" section set the value for this rule to 0:
{
// ...
"rules": {
"no-new": 0,
// ...
}
}
You can also make it a warning instead of an error by setting it to 1 (2 is error).
Try to cover your function into an anonim function
(()=>code)();
in your example
fetchJsAnimation() {
const animation = this.refs.Animation;
(()=>new AnimateSlideShow(animation))();
}
Or you can use this pattern for example modern javascript framework eg. vuejs vue
Here is an example
(() => new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
}))();
Extending on sarkiroka answer, here's an ES5 version (essentially an IIFE with a return statement):
(function (Vue) {
'use strict';
return new Vue({
el: '.unity-header-wrapper'
});
}(Vue));
We're avoiding ESLint unused var error, which appears if used this way:
var myApp = new Vue({
el: '.unity-header-wrapper'
});
We're also avoiding using standalone 'new Vue()' instantiation (which prevents side effects error on ESLint)
var myApp = new Vue({
el: '.unity-header-wrapper'
});
You can also add Vue as a global in ESLint config, to avoid undefined global var error, as seen here: Global variables in Javascript and ESLint
// .eslintrc.json
"globals": {
"Vue": true
}
I use a more declarative form using an init() method inside my class. For example:
class Example {
constructor () { ... }
init () { //this method is using for initialize the instance }
}
So, when you initialize that instance:
const example = new Example()
example.init()
And with this you can avoid the "no new" linter and avoid undefined global without linter comments.
Related
I am trying to write some custom ESLint rules for my typescript based project. In my project I am using eslint/typescript for linting.
I have already written a custom eslint plugin which validates a custom rule. Now I want to write the unit tests for that custom rule. My test file looks like this:
/**
* #fileoverview This rule verifies that logic can only depend on other logic
* #author Dayem Siddiqui
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const typescriptParser = require('#typescript-eslint/parser')
var rule = require("../../../lib/rules/logic-dependency"),
RuleTester = require("eslint").RuleTester;
//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------
typescriptParser.parseForESLint()
var ruleTester = new RuleTester({ parserOptions: {} });
ruleTester.run("logic-dependency", rule, {
valid: [
`class DeleteLogic {
}
class CreateLogic {
constructor(private deleteLogic: DeleteLogic) {}
}`
],
invalid: [
{
code: `class ExternalClient {
}
class UpdateLogic {
constructor(private externalClient: ExternalClient) {}
}`,
errors: [
{
message: "Logic cannot have a dependency on client",
type: "MethodDefinition"
}
]
}
]
});
Right now my tests a failing because by default eslint only understand plain Javascript code. I understand that I need to somehow configure it to use a custom parser that allows it to understand/parse typescript code. However I am unable to find a good example online on how to do that
The RuleTester constructor takes eslint's parser options that allow for configuring the parser itself. So pass it in like this and Bob's your uncle:
const ruleTester = new RuleTester({
parser: '#typescript-eslint/parser',
});
typescript-eslint's own rule tests (e.g. this one) use exactly this.
(Was searching for an answer to this question and kept up ending here, so I posted the solution I found here in the hope it'll be useful.)
eslint 6.0+
Incorporating #Sonata's comment:
Eslint 6.0+ requires an absolute path to the parser (see 6.0 migration guide):
const ruleTester = new RuleTester({
parser: require.resolve('#typescript-eslint/parser'),
});
Use a package such as the typescript-eslint/parser. I can't provide much more than a link in this case. If you need help using it, let me know.
So, I'm working my way through learning Jest, and in a current Aurelia project, the internal working of the generated main.js script imports a configuration object (environment). Note this code is all as-generated.
// main.js
import environment from './environment';
import {PLATFORM} from 'aurelia-pal';
import 'babel-polyfill';
import * as Bluebird from 'bluebird';
// remove out if you don't want a Promise polyfill (remove also from webpack.config.js)
Bluebird.config({ warnings: { wForgottenReturn: false } });
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.feature(PLATFORM.moduleName('resources/index'));
// Uncomment the line below to enable animation.
// aurelia.use.plugin(PLATFORM.moduleName('aurelia-animator-css'));
// if the css animator is enabled, add swap-order="after" to all router-view elements
// Anyone wanting to use HTMLImports to load views, will need to install the following plugin.
// aurelia.use.plugin(PLATFORM.moduleName('aurelia-html-import-template-loader'));
if (environment.debug) {
aurelia.use.developmentLogging();
}
if (environment.testing) {
aurelia.use.plugin(PLATFORM.moduleName('aurelia-testing'));
}
return aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app')));
}
The environment object is just holding a couple simple values:
export default {
debug: true,
testing: true
};
Now, when I want to test the branching logic in main.js, I want to be able to flip those booleans to ensure they do or don't execute the config changes as appropriate:
import {configure} from '../../src/main';
import environment from '../../src/environment';
/* later... */
describe('when the environment is not set to debug', () => {
environment.debug = false;
it('should not configure development logging', () => {
configure(aureliaMock);
expect(aureliaMock.use.developmentLogging.mock.calls.length).toBe(0);
});
});
This does not work, as the version of environment being checked inside the configure() function still has the values in the source module. I recognize that environment in this case is my local value, but what I don't know is how to affect the instance of environment that's being checked.
I tried using the jest.mock() syntax you'd use with an ES6 class constructor, but that doesn't work either. I will probably change the configure() signature to accept an environment for testing, but before doing so I wanted to see if there's a way to do this via mocks first.
I'd like to override some values at test-time, specifically setting my retries for an http service to 1 (immediate failure, no retries). Our project uses node-config. According to the docs I can override with NODE_CONFIG env variable:
node myapp.js --NODE_CONFIG='{"Customer":{"dbConfig":{"host":"customerdb.prod"}}}'
Well I would prefer to do this in my test, but not for all tests. The code says that you can allow config mutations by setting ALLOW_CONFIG_MUTATIONS.
process.env.ALLOW_CONFIG_MUTATIONS = "true";
const importFresh = require('import-fresh');
importFresh("config");
process.env.NODE_CONFIG = JSON.stringify({httpServices:{integration:{enrich: {retryInterval: 1, retries: 1}}}});
expect(process.env.NODE_CONFIG, 'NODE_CONFIG not set').to.exist();
expect(process.env.NODE_CONFIG, 'NODE_CONFIG not set').to.match(/retryInterval/);
expect(process.env.ALLOW_CONFIG_MUTATIONS, 'ALLOW_CONFIG_MUTATIONS not set').to.equal("true");
const testConfig = require("config");
console.dir(testConfig.get("httpServices.integration.enrich"));
expect(testConfig.get("httpServices.integration.enrich.retryInterval"), 'config value not set to 1').to.equal(1);
Result:
{ url: 'https://internal-**********',
retryInterval: 5000,
retries: 5 }
`Error: config value not set to 1: Expected 5000 to equal specified value: 1`
How do I get this override to work?
(expect is from Hapi.js Code library)
I'm one of the maintainers of node-config. Your bug is that you used require the second time when you should have used importFresh again.
Your first use of "importFresh()" does nothing different than require() would, because it is the first use of require().
After setting some variables, you call require(), which will return the copy of config already generated and cached, ignoring the effects of the environment variables set.
You only needed to use importFresh() once, where you currently use require(). This will cause a "fresh" copy of the config object to be returned, as you expected.
Simply changing config's property worked for me.
For example:
const config = require( 'config' );
config.httpServices.integration.enrich.retryInterval = 1;
// Do your tests...
UPD: Make sure that overrides are done before anyone calls the first config.get(), because the config object is made immutable as soon as any client uses the values via get().
Joining late, but other answers did not fit with the testing standard in my project, so here is what I came up with
TL;DR
Use mocks..
Detailed Answer
node-config uses a function get to get the configuration values.
By mocking the function get you can easily modify any configuration you see fit..
My personal favorite library is sinon
Here is an implementation of a mock with sinon
const config = require('config');
const sinon = require('sinon');
class MockConfig {
constructor () {
this.params = {};
this.sandbox = sinon.sandbox.create();
}
withConfValue (confKey, confValue) {
this.params.confValues[confKey] = confValue;
return this;
}
reset () {
this.params.confValues: {};
return this;
}
restore() {
this.sandbox.restore();
}
apply () {
this.restore(); // avoid duplicate wrapping
this.sandbox.stub(config, 'get').callsFake((configKey) => {
if (this.params.confValues.hasOwnProperty(configKey)) {
return this.params.confValues[configKey];
}
// not ideal.. however `wrappedMethod` approach did not work for me
// https://stackoverflow.com/a/57017971/1068746
return configKey
.split('.')
.reduce((result, item) => result[item], config)
});
}
}
const instance = new MockConfig();
MockConfig.instance = () => instance;
module.exports = MockConfig;
Usage would be
const mockConfig = require('./mock_config').instance();
...
beforeEach(function () {
mockConfig.reset().apply();
})
afterEach(function () {
mockConfig.reset().clear();
})
it('should do something') {
mockConfig.withConfValue('some_topic.some_field.property', someValue);
... rest of the test ...
}
Assumptions
The only assumption this approach makes is that you adhere to node-config way of reading the configuration (using the get function) and not bypass it by accessing fields directly.
It's better to create a development.json, production.json et test.json in your config folder node-config will use it your app configuration.
you just net to set your NODE_ENV to use the specific file.
Hope it helps :)
here, I am attempting to set value for read-only property but I am not getting any error:
HERE IS MY CODE:
require('use-strict');
function Employee(firstname) {
var _firstname = firstname;
Object.defineProperty(this, 'firstName', {
get: function () { return _firstname },
//set: function (value) { _firstname = value }
});
}
var employee = new Employee('Fawad');
employee.firstName = 'Yasir'; //Attempting to set a value for read-only property.
console.log(employee.firstName);
From the documentation for the use-strict package:
The implementation works by patching Node's internal module.wrapper
array, and then freezing it, so that further modifications are not
possible.
Also, this means that the current module will not be affected. You
should still "use strict" in the module that does
require('use-strict'). This module applies strictness to all future
modules loaded by your program.
Use of "use strict"; at the top of page worked for me although this approach is usually used for JavaScript development. I was trying to use one of the node.js packages which didn't worked.
I've been following the pattern for setting up TypeScript, RequireJS, and Jasmine that Steve Fenton describes here:
https://www.stevefenton.co.uk/Content/Blog/Date/201407/Blog/Combining-TypeScript-Jasmine-And-AMD-With-RequireJS/
That pattern as really worked well and truly unblocked me (yay!), but I'm now at the point where I need to customize some settings for RequireJS but I can't seem to figure out where to put my require.config call. Everywhere I've tried has caused breaks and regressions. Here are the two approaches that seem most logical/promising
In SpecRunner.cshtml
<script data-main="/Scripts/TypeScript/RequireJsConfig" src="/Scripts/require.js"></script>
In RequireJsConfig.ts
require.config({
baseUrl: "../Scripts",
paths: {
jquery: "../jquery-2.1.3"
}
});
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Attempt 1: When I try it this way I immediately get this error
//
// JavaScript runtime error: Object doesn't support property or method 'config'
//
import TestLoader = require("Tests/TestLoader");
TestLoader.Run();
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Attempt 2: When I try it this way, everything builds and runs without errors, but
// Jasmine doesn't find any of the tests. All I get is "No specs found" even
// though I see the breakpoints on my "it" statements getting hit.
//
require(["Tests/TestLoader"], (testLoader) => {
testLoader.Run();
});
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
jasmine.getEnv().execute();
In TestLoader.ts
import GuidHelperTests = require("Tests/T3/Helpers/GuidHelperTests");
import ObjectHelperTests = require("Tests/T3/Helpers/ObjectHelperTests");
class TestLoader {
public static Run: () => void = () => {
GuidHelperTests.Run();
ObjectHelperTests.Run();
}
}
export var Run = () => TestLoader.Run();
In GuidHelperTests.ts
import T3 = require("T3/T3Lib");
export var Run = () => {
describe("GuidHelper tests", () => {
it("GUID validator validates good GUID", () => {
// etc. ...
My guess is that Attempt 2 doesn't work because of some kind of sequencing issue where the test discovery process is happening before modules are loaded, or something like that. I'm just not versed enough in RequireJS to know what my options are here.
I prefer to keep my configuration away from my application - you can pre-register the configuration like this, and it will be picked up by RequireJS when it loads. No need to add it to your first file.
<script>
var require = {
baseUrl: "../Scripts",
paths: {
jquery: "../jquery-2.1.3"
}
};
</script>
<script data-main="/Scripts/TypeScript/RequireJsConfig" src="/Scripts/require.js"></script>