diff --git a/.eslintrc.js b/.eslintrc.js index 2c7de895d6..36476d2885 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,6 +10,7 @@ module.exports = { 'eslint-plugin', 'filenames', 'import', + 'jest', 'node', 'prettier', 'unicorn' @@ -18,6 +19,8 @@ module.exports = { 'eslint:recommended', 'plugin:eslint-comments/recommended', 'plugin:eslint-plugin/all', + 'plugin:jest/recommended', + 'plugin:jest/style', 'plugin:import/errors', 'plugin:import/warnings', 'plugin:node/recommended', @@ -104,6 +107,24 @@ module.exports = { // Filenames: 'filenames/match-regex': ['error', '^[a-z0-9-]+$'], // Kebab-case. + // Optional jest rules: + 'jest/consistent-test-it': 'error', + 'jest/lowercase-name': 'error', + 'jest/no-duplicate-hooks': 'error', + 'jest/no-expect-resolves': 'error', + 'jest/no-hooks': 'error', + 'jest/no-if': 'error', + 'jest/no-large-snapshots': 'error', + 'jest/no-test-return-statement': 'error', + 'jest/prefer-called-with': 'error', + 'jest/prefer-hooks-on-top': 'error', + 'jest/prefer-spy-on': 'error', + 'jest/prefer-strict-equal': 'error', + 'jest/prefer-todo': 'error', + 'jest/require-top-level-describe': 'error', + 'jest/require-to-throw-message': 'error', + 'jest/valid-title': 'error', + // Optional import rules:     'import/extensions': 'error',     'import/first': 'error', diff --git a/package.json b/package.json index 17637942d7..848e2a5cb9 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "eslint-plugin-eslint-plugin": "^2.1.0", "eslint-plugin-filenames": "^1.3.2", "eslint-plugin-import": "^2.19.1", + "eslint-plugin-jest": "^23.1.1", "eslint-plugin-node": "^10.0.0", "eslint-plugin-prettier": "^3.1.1", "eslint-plugin-unicorn": "^14.0.1", diff --git a/tests/__snapshots__/recommended.js.snap b/tests/__snapshots__/recommended.js.snap index 4e5ef8b237..54fc006ae9 100644 --- a/tests/__snapshots__/recommended.js.snap +++ b/tests/__snapshots__/recommended.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`recommended rules 1`] = ` +exports[`recommended rules has the right list 1`] = ` Array [ "avoid-leaking-state-in-ember-objects", "avoid-using-needs-in-controllers", diff --git a/tests/lib/rules/avoid-leaking-state-in-ember-objects.js b/tests/lib/rules/avoid-leaking-state-in-ember-objects.js index a80ab28c72..a153814be6 100644 --- a/tests/lib/rules/avoid-leaking-state-in-ember-objects.js +++ b/tests/lib/rules/avoid-leaking-state-in-ember-objects.js @@ -11,7 +11,7 @@ const RuleTester = require('eslint').RuleTester; describe('imports', () => { it('should expose the default ignored properties', () => { - expect(rule.DEFAULT_IGNORED_PROPERTIES).toEqual([ + expect(rule.DEFAULT_IGNORED_PROPERTIES).toStrictEqual([ 'classNames', 'classNameBindings', 'actions', diff --git a/tests/lib/utils/ember-test.js b/tests/lib/utils/ember-test.js index ffe92b96f8..794ea8421f 100644 --- a/tests/lib/utils/ember-test.js +++ b/tests/lib/utils/ember-test.js @@ -38,12 +38,12 @@ describe('isDSModel', () => { }); describe("should check if it's a DS Model even if it uses custom name", () => { - it("it shouldn't detect Model when no file path is provided", () => { + it("shouldn't detect Model when no file path is provided", () => { const node = parse('CustomModel.extend()'); expect(emberUtils.isDSModel(node)).toBeFalsy(); }); - it('it should detect Model when file path is provided', () => { + it('should detect Model when file path is provided', () => { const node = parse('CustomModel.extend()'); const filePath = 'example-app/models/path/to/some-model.js'; expect(emberUtils.isDSModel(node, filePath)).toBeTruthy(); @@ -98,7 +98,7 @@ describe('isTestFile', () => { }); describe('isEmberCoreModule', () => { - it('should check if current file is a component', () => { + it('should check if current file is a component (custom)', () => { const context = new FauxContext( 'CustomComponent.extend()', 'example-app/components/path/to/some-component.js' @@ -116,7 +116,7 @@ describe('isEmberCoreModule', () => { expect(emberUtils.isEmberCoreModule(context, node, 'Component')).toBeTruthy(); }); - it('should check if current file is a controller', () => { + it('should check if current file is a controller (custom)', () => { const context = new FauxContext( 'CustomController.extend()', 'example-app/controllers/path/to/some-controller.js' @@ -134,7 +134,7 @@ describe('isEmberCoreModule', () => { expect(emberUtils.isEmberCoreModule(context, node, 'Controller')).toBeTruthy(); }); - it('should check if current file is a route', () => { + it('should check if current file is a route (custom)', () => { const context = new FauxContext( 'CustomRoute.extend()', 'example-app/routes/path/to/some-route.js' @@ -163,13 +163,13 @@ describe('isEmberCoreModule', () => { describe('isEmberComponent', () => { describe("should check if it's an Ember Component", () => { - it('it should detect Component when using Ember.Component', () => { + it('should detect Component when using Ember.Component', () => { const context = new FauxContext('Ember.Component.extend()'); const node = context.ast.body[0].expression; expect(emberUtils.isEmberComponent(context, node)).toBeTruthy(); }); - it('it should detect Component when using local module Component', () => { + it('should detect Component when using local module Component', () => { const context = new FauxContext('Component.extend()'); const node = context.ast.body[0].expression; expect(emberUtils.isEmberComponent(context, node)).toBeTruthy(); @@ -195,13 +195,13 @@ describe('isEmberComponent', () => { }); describe("should check if it's an Ember Component even if it uses custom name", () => { - it("it shouldn't detect Component when no file path is provided", () => { + it("shouldn't detect Component when no file path is provided", () => { const context = new FauxContext('CustomComponent.extend()'); const node = context.ast.body[0].expression; expect(emberUtils.isEmberComponent(context, node)).toBeFalsy(); }); - it('it should detect Component when file path is provided', () => { + it('should detect Component when file path is provided', () => { const context = new FauxContext( 'CustomComponent.extend()', 'example-app/components/path/to/some-component.js' @@ -223,13 +223,13 @@ describe('isEmberComponent', () => { describe('isEmberController', () => { describe("should check if it's an Ember Controller", () => { - it('it should detect Controller when using Ember.Controller', () => { + it('should detect Controller when using Ember.Controller', () => { const context = new FauxContext('Ember.Controller.extend()'); const node = context.ast.body[0].expression; expect(emberUtils.isEmberController(context, node)).toBeTruthy(); }); - it('it should detect Controller when using local module Controller', () => { + it('should detect Controller when using local module Controller', () => { const context = new FauxContext('Controller.extend()'); const node = context.ast.body[0].expression; expect(emberUtils.isEmberController(context, node)).toBeTruthy(); @@ -255,13 +255,13 @@ describe('isEmberController', () => { }); describe("should check if it's an Ember Controller even if it uses custom name", () => { - it("it shouldn't detect Controller when no file path is provided", () => { + it("shouldn't detect Controller when no file path is provided", () => { const context = new FauxContext('CustomController.extend()'); const node = context.ast.body[0].expression; expect(emberUtils.isEmberController(context, node)).toBeFalsy(); }); - it('it should detect Controller when file path is provided', () => { + it('should detect Controller when file path is provided', () => { const context = new FauxContext( 'CustomController.extend()', 'example-app/controllers/path/to/some-feature.js' @@ -315,13 +315,13 @@ describe('isEmberRoute', () => { }); describe("should check if it's an Ember Route even if it uses custom name", () => { - it("it shouldn't detect Route when no file path is provided", () => { + it("shouldn't detect Route when no file path is provided", () => { const context = new FauxContext('CustomRoute.extend()'); const node = context.ast.body[0].expression; expect(emberUtils.isEmberRoute(context, node)).toBeFalsy(); }); - it('it should detect Route when file path is provided', () => { + it('should detect Route when file path is provided', () => { const context = new FauxContext( 'CustomRoute.extend()', 'example-app/routes/path/to/some-feature.js' @@ -415,7 +415,7 @@ describe('isEmberService', () => { expect(emberUtils.isEmberService(context, node)).toBeFalsy(); }); - it('it should detect Service when file path is provided', () => { + it('should detect Service when file path is provided', () => { const context = new FauxContext( 'CustomService.extend()', 'example-app/services/path/to/some-feature.js' @@ -1031,17 +1031,25 @@ describe('isRelation', () => { describe('parseDependentKeys', () => { it('should parse dependent keys from callexpression', () => { const node = parse("computed('model.{foo,bar}', 'model.bar')"); - expect(emberUtils.parseDependentKeys(node)).toEqual(['model.foo', 'model.bar', 'model.bar']); + expect(emberUtils.parseDependentKeys(node)).toStrictEqual([ + 'model.foo', + 'model.bar', + 'model.bar', + ]); }); it('should work when no dependent keys present', () => { const node = parse('computed(function() {})'); - expect(emberUtils.parseDependentKeys(node)).toEqual([]); + expect(emberUtils.parseDependentKeys(node)).toStrictEqual([]); }); it('should handle dependent keys and function arguments', () => { const node = parse("computed('model.{foo,bar}', 'model.bar', function() {})"); - expect(emberUtils.parseDependentKeys(node)).toEqual(['model.foo', 'model.bar', 'model.bar']); + expect(emberUtils.parseDependentKeys(node)).toStrictEqual([ + 'model.foo', + 'model.bar', + 'model.bar', + ]); }); it('should handle dependent keys and function arguments in MemberExpression', () => { @@ -1049,20 +1057,24 @@ describe('parseDependentKeys', () => { computed('model.{foo,bar}', 'model.bar', function() { }).volatile(); `); - expect(emberUtils.parseDependentKeys(node)).toEqual(['model.foo', 'model.bar', 'model.bar']); + expect(emberUtils.parseDependentKeys(node)).toStrictEqual([ + 'model.foo', + 'model.bar', + 'model.bar', + ]); }); }); describe('unwrapBraceExpressions', () => { it('should unwrap simple dependent keys', () => { - expect(emberUtils.unwrapBraceExpressions(['model.foo', 'model.bar'])).toEqual([ + expect(emberUtils.unwrapBraceExpressions(['model.foo', 'model.bar'])).toStrictEqual([ 'model.foo', 'model.bar', ]); }); it('should unwrap dependent keys with braces', () => { - expect(emberUtils.unwrapBraceExpressions(['model.{foo,bar}', 'model.bar'])).toEqual([ + expect(emberUtils.unwrapBraceExpressions(['model.{foo,bar}', 'model.bar'])).toStrictEqual([ 'model.foo', 'model.bar', 'model.bar', @@ -1072,25 +1084,23 @@ describe('unwrapBraceExpressions', () => { it('should unwrap more complex dependent keys', () => { expect( emberUtils.unwrapBraceExpressions(['model.{foo,bar}', 'model.bar', 'data.{foo,baz,qux}']) - ).toEqual(['model.foo', 'model.bar', 'model.bar', 'data.foo', 'data.baz', 'data.qux']); + ).toStrictEqual(['model.foo', 'model.bar', 'model.bar', 'data.foo', 'data.baz', 'data.qux']); }); it('should unwrap multi-level keys', () => { - expect(emberUtils.unwrapBraceExpressions(['model.bar.{foo,qux}', 'model.bar.baz'])).toEqual([ - 'model.bar.foo', - 'model.bar.qux', - 'model.bar.baz', - ]); + expect( + emberUtils.unwrapBraceExpressions(['model.bar.{foo,qux}', 'model.bar.baz']) + ).toStrictEqual(['model.bar.foo', 'model.bar.qux', 'model.bar.baz']); }); it('should unwrap @each with extensions', () => { expect( emberUtils.unwrapBraceExpressions(['collection.@each.{foo,bar}', 'collection.@each.qux']) - ).toEqual(['collection.@each.foo', 'collection.@each.bar', 'collection.@each.qux']); + ).toStrictEqual(['collection.@each.foo', 'collection.@each.bar', 'collection.@each.qux']); }); it('should unwrap complicated mixed dependent keys', () => { - expect(emberUtils.unwrapBraceExpressions(['a.b.c.{d.@each.qwe.zxc,f,g.[]}'])).toEqual([ + expect(emberUtils.unwrapBraceExpressions(['a.b.c.{d.@each.qwe.zxc,f,g.[]}'])).toStrictEqual([ 'a.b.c.d.@each.qwe.zxc', 'a.b.c.f', 'a.b.c.g.[]', @@ -1098,7 +1108,7 @@ describe('unwrapBraceExpressions', () => { }); it('should unwrap complicated mixed repeated dependent keys', () => { - expect(emberUtils.unwrapBraceExpressions(['a.b.{d.@each.qux,f,d.@each.foo}'])).toEqual([ + expect(emberUtils.unwrapBraceExpressions(['a.b.{d.@each.qux,f,d.@each.foo}'])).toStrictEqual([ 'a.b.d.@each.qux', 'a.b.f', 'a.b.d.@each.foo', @@ -1139,7 +1149,7 @@ describe('hasDuplicateDependentKeys', () => { describe('getEmberImportAliasName', () => { it('should get the proper name of default import', () => { const node = babelEslint.parse("import foo from 'ember'").body[0]; - expect(emberUtils.getEmberImportAliasName(node)).toEqual('foo'); + expect(emberUtils.getEmberImportAliasName(node)).toStrictEqual('foo'); }); }); diff --git a/tests/lib/utils/import-test.js b/tests/lib/utils/import-test.js index 3af62770c4..048d002c4b 100644 --- a/tests/lib/utils/import-test.js +++ b/tests/lib/utils/import-test.js @@ -8,16 +8,16 @@ function parse(code) { describe('getSourceModuleName', () => { it('gets the correct module name with MemberExpression', () => { const node = parse('DS.Model.extend()').callee; - expect(importUtils.getSourceModuleName(node)).toEqual('DS'); + expect(importUtils.getSourceModuleName(node)).toStrictEqual('DS'); }); it('gets the correct module name with Identifier', () => { const node = parse('Model.extend()').callee; - expect(importUtils.getSourceModuleName(node)).toEqual('Model'); + expect(importUtils.getSourceModuleName(node)).toStrictEqual('Model'); }); it('gets the correct module name with CallExpression', () => { const node = parse('Model.extend()'); - expect(importUtils.getSourceModuleName(node)).toEqual('Model'); + expect(importUtils.getSourceModuleName(node)).toStrictEqual('Model'); }); }); diff --git a/tests/lib/utils/property-order-test.js b/tests/lib/utils/property-order-test.js index aab43f2b20..c1d5a898d5 100644 --- a/tests/lib/utils/property-order-test.js +++ b/tests/lib/utils/property-order-test.js @@ -10,7 +10,7 @@ describe('addBackwardsPosition', () => { 'empty-method', 'method' ); - expect(newOrder).toEqual(['method', 'empty-method']); + expect(newOrder).toStrictEqual(['method', 'empty-method']); }); it('should not change the order if the desired position is already included as part of another position group', () => { @@ -19,12 +19,12 @@ describe('addBackwardsPosition', () => { 'empty-method', 'method' ); - expect(newOrder).toEqual([['method', 'empty-method'], 'foo']); + expect(newOrder).toStrictEqual([['method', 'empty-method'], 'foo']); }); it('should not add the position, if the target position is not present', () => { const newOrder = propertyOrder.addBackwardsPosition(['foo'], 'empty-method', 'bar'); - expect(newOrder).toEqual(['foo']); + expect(newOrder).toStrictEqual(['foo']); }); it('should add the desired position to the existing target position when the target position is on its own position', () => { @@ -33,7 +33,7 @@ describe('addBackwardsPosition', () => { 'empty-method', 'method' ); - expect(newOrder).toEqual([['method', 'empty-method'], 'foo']); + expect(newOrder).toStrictEqual([['method', 'empty-method'], 'foo']); }); it('should add the desired position to the existing target position when the target position is part of a group', () => { @@ -42,7 +42,7 @@ describe('addBackwardsPosition', () => { 'empty-method', 'method' ); - expect(newOrder).toEqual([['method', 'bar', 'empty-method'], 'foo']); + expect(newOrder).toStrictEqual([['method', 'bar', 'empty-method'], 'foo']); }); }); @@ -55,7 +55,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('service'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('service'); }); it('should determine controller-type props', () => { @@ -65,7 +65,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('controller'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('controller'); }); it('should determine init-type props', () => { @@ -75,7 +75,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('init'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('init'); }); it('should determine component lifecycle hooks', () => { @@ -85,7 +85,9 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual('didInsertElement'); + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual( + 'didInsertElement' + ); }); it('should determine query-params', () => { @@ -95,7 +97,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('query-params'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('query-params'); }); it('should determine inherited properties', () => { @@ -105,7 +107,9 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('inherited-property'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual( + 'inherited-property' + ); }); it('should determine attributes', () => { @@ -115,7 +119,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'model')).toEqual('attribute'); + expect(propertyOrder.determinePropertyType(node, 'model')).toStrictEqual('attribute'); }); it('should determine relationships', () => { @@ -125,7 +129,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'model')).toEqual('relationship'); + expect(propertyOrder.determinePropertyType(node, 'model')).toStrictEqual('relationship'); }); it('should determine observer-type props', () => { @@ -135,7 +139,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('observer'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('observer'); }); it('should determine actions', () => { @@ -145,7 +149,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual('actions'); + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual('actions'); }); it('should determine single-line functions', () => { @@ -155,7 +159,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual( + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual( 'single-line-function' ); }); @@ -169,7 +173,9 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual('multi-line-function'); + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual( + 'multi-line-function' + ); }); it('should determine properties', () => { @@ -179,7 +185,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual('property'); + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual('property'); }); it('should determine empty methods', () => { @@ -189,7 +195,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual('empty-method'); + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual('empty-method'); }); it('should determine methods', () => { @@ -199,7 +205,7 @@ describe('determinePropertyType', () => { });` ); const node = context.ast.body[0].declaration.arguments[0].properties[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual('method'); + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual('method'); }); }); @@ -211,7 +217,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('service'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('service'); }); it('should determine controller-type props', () => { @@ -221,7 +227,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('controller'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('controller'); }); it('should determine init-type props', () => { @@ -231,7 +237,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('init'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('init'); }); it('should determine query-params', () => { @@ -241,7 +247,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('query-params'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('query-params'); }); it('should determine attributes', () => { @@ -251,7 +257,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'model')).toEqual('attribute'); + expect(propertyOrder.determinePropertyType(node, 'model')).toStrictEqual('attribute'); }); it('should determine relationships', () => { @@ -261,7 +267,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'model')).toEqual('relationship'); + expect(propertyOrder.determinePropertyType(node, 'model')).toStrictEqual('relationship'); }); it('should determine observer-type props', () => { @@ -271,7 +277,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'controller')).toEqual('observer'); + expect(propertyOrder.determinePropertyType(node, 'controller')).toStrictEqual('observer'); }); it('should determine single-line functions', () => { @@ -281,7 +287,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual( + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual( 'single-line-function' ); }); @@ -295,7 +301,9 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual('multi-line-function'); + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual( + 'multi-line-function' + ); }); it('should determine properties', () => { @@ -305,7 +313,7 @@ describe('determinePropertyType', () => { }` ); const node = context.ast.body[0].body.body[0]; - expect(propertyOrder.determinePropertyType(node, 'component')).toEqual('property'); + expect(propertyOrder.determinePropertyType(node, 'component')).toStrictEqual('property'); }); }); }); @@ -343,7 +351,7 @@ describe('reportUnorderedProperties', () => { const node = context.ast.body[0].declaration; propertyOrder.reportUnorderedProperties(node, context, 'controller', order); - expect(context.report).toHaveBeenCalled(); + expect(context.report).toHaveBeenCalled(); // eslint-disable-line jest/prefer-called-with }); }); @@ -379,7 +387,7 @@ describe('reportUnorderedProperties', () => { const node = context.ast.body[0].declaration; propertyOrder.reportUnorderedProperties(node, context, 'controller', order); - expect(context.report).toHaveBeenCalled(); + expect(context.report).toHaveBeenCalled(); // eslint-disable-line jest/prefer-called-with }); }); }); diff --git a/tests/lib/utils/types-test.js b/tests/lib/utils/types-test.js index 3c8072fcfb..1a1913da7e 100644 --- a/tests/lib/utils/types-test.js +++ b/tests/lib/utils/types-test.js @@ -7,7 +7,9 @@ function parse(code) { describe('function sort order', function() { it('has exported functions in sorted order', function() { - expect(Object.getOwnPropertyNames(types)).toEqual(Object.getOwnPropertyNames(types).sort()); + expect(Object.getOwnPropertyNames(types)).toStrictEqual( + Object.getOwnPropertyNames(types).sort() + ); }); }); diff --git a/tests/lib/utils/utils-test.js b/tests/lib/utils/utils-test.js index d409147760..67bc899f76 100644 --- a/tests/lib/utils/utils-test.js +++ b/tests/lib/utils/utils-test.js @@ -18,7 +18,7 @@ describe('collectObjectPatternBindings', () => { Ember: ['$'], }); - expect(collectedBindings).toEqual(['$']); + expect(collectedBindings).toStrictEqual(['$']); }); it('collects aliased bindings correctly', () => { @@ -27,7 +27,7 @@ describe('collectObjectPatternBindings', () => { Ember: ['$'], }); - expect(collectedBindings).toEqual(['foo']); + expect(collectedBindings).toStrictEqual(['foo']); }); it('collects only relevant bindings correctly for multiple destructurings', () => { @@ -36,7 +36,7 @@ describe('collectObjectPatternBindings', () => { Ember: ['$'], }); - expect(collectedBindings).toEqual(['$']); + expect(collectedBindings).toStrictEqual(['$']); }); it('collects only relevant bindings correctly for multiple destructurings and aliases', () => { @@ -45,7 +45,7 @@ describe('collectObjectPatternBindings', () => { Ember: ['$'], }); - expect(collectedBindings).toEqual(['foo']); + expect(collectedBindings).toStrictEqual(['foo']); }); it('collects multiple relevant bindings', () => { @@ -54,7 +54,7 @@ describe('collectObjectPatternBindings', () => { Ember: ['$', 'computed'], }); - expect(collectedBindings).toEqual(['foo', 'computed']); + expect(collectedBindings).toStrictEqual(['foo', 'computed']); }); }); @@ -82,7 +82,9 @@ describe('findNodes', () => { describe('function sort order', function() { it('has exported functions in sorted order', function() { - expect(Object.getOwnPropertyNames(utils)).toEqual(Object.getOwnPropertyNames(utils).sort()); + expect(Object.getOwnPropertyNames(utils)).toStrictEqual( + Object.getOwnPropertyNames(utils).sort() + ); }); }); @@ -117,32 +119,32 @@ describe('getPropertyValue', () => { it('should return null when property value not found for simpleObject', () => { const value = utils.getPropertyValue(simpleObject, 'blah'); - expect(value).toEqual(undefined); + expect(value).toBeUndefined(); }); it('should return value when using a simple property path for simpleObject', () => { const value = utils.getPropertyValue(simpleObject, 'foo'); - expect(value).toEqual(true); + expect(value).toStrictEqual(true); }); it('should return value when using a full property path for simpleObject', () => { const buzz = utils.getPropertyValue(simpleObject, 'bar.fizz.buzz'); - expect(buzz).toEqual('buzz'); + expect(buzz).toStrictEqual('buzz'); }); it('should return null when property value not found for node', () => { const value = utils.getPropertyValue(node, 'blah'); - expect(value).toEqual(undefined); + expect(value).toBeUndefined(); }); it('should return value when using a simple property path for node', () => { const type = utils.getPropertyValue(node, 'type'); - expect(type).toEqual('CallExpression'); + expect(type).toStrictEqual('CallExpression'); }); it('should return value when using a full property path for node', () => { const name = utils.getPropertyValue(node, 'callee.object.name'); - expect(name).toEqual('Ember'); + expect(name).toStrictEqual('Ember'); }); }); @@ -152,7 +154,7 @@ describe('getSize', () => { ); it('should check size of given expression', () => { - expect(utils.getSize(node)).toEqual(6); + expect(utils.getSize(node)).toStrictEqual(6); }); }); @@ -173,7 +175,7 @@ describe('parseArgs', () => { const node = parse('Ember.computed("asd", "qwe", "zxc", function() {})'); const parsedArgs = utils.parseArgs(node); expect(parsedArgs).toHaveLength(3); - expect(parsedArgs).toEqual(['asd', 'qwe', 'zxc']); + expect(parsedArgs).toStrictEqual(['asd', 'qwe', 'zxc']); }); }); @@ -182,13 +184,13 @@ describe('parseCallee', () => { const node = parse('Ember.computed.or("asd", "qwe")'); const parsedCallee = utils.parseCallee(node); expect(parsedCallee).toHaveLength(3, 'it has 3 elements in array'); - expect(parsedCallee).toEqual(['Ember', 'computed', 'or']); + expect(parsedCallee).toStrictEqual(['Ember', 'computed', 'or']); }); it('should parse newExpression', () => { const node = parse('new Ember.A()'); const parsedCallee = utils.parseCallee(node); expect(parsedCallee).toHaveLength(2, 'it has 2 elements in array'); - expect(parsedCallee).toEqual(['Ember', 'A']); + expect(parsedCallee).toStrictEqual(['Ember', 'A']); }); }); diff --git a/tests/lib/utils/utils/get-source-module-name-for-identifier-test.js b/tests/lib/utils/utils/get-source-module-name-for-identifier-test.js index 1877aa97a4..6f7e06ad6e 100644 --- a/tests/lib/utils/utils/get-source-module-name-for-identifier-test.js +++ b/tests/lib/utils/utils/get-source-module-name-for-identifier-test.js @@ -2,99 +2,103 @@ const { getSourceModuleNameForIdentifier } = require('../../../../lib/utils/impo const { FauxContext } = require('../../../helpers/faux-context'); const babelEslint = require('babel-eslint'); -test('when the identifier is not imported', () => { - const context = new FauxContext(` - Foo; - `); +describe('getSourceModuleNameForIdentifier', () => { + describe('when the identifier is not imported', () => { + it('returns undefined', () => { + const context = new FauxContext(` + Foo; + `); - const node = { name: 'Foo', type: 'Identifier' }; + const node = { name: 'Foo', type: 'Identifier' }; - expect(getSourceModuleNameForIdentifier(context, node)).toEqual(undefined); -}); + expect(getSourceModuleNameForIdentifier(context, node)).toBeUndefined(); + }); + }); -describe('when the identifier is imported', () => { - test('as a default export', () => { - const context = new FauxContext(` - import Foo from 'bar'; + describe('when the identifier is imported', () => { + it('as a default export', () => { + const context = new FauxContext(` + import Foo from 'bar'; - Foo; - `); + Foo; + `); - const node = { name: 'Foo', type: 'Identifier' }; + const node = { name: 'Foo', type: 'Identifier' }; - expect(getSourceModuleNameForIdentifier(context, node)).toEqual('bar'); - }); + expect(getSourceModuleNameForIdentifier(context, node)).toStrictEqual('bar'); + }); - test('as a named export', () => { - const context = new FauxContext(` - import { Foo } from 'bar'; + it('as a named export', () => { + const context = new FauxContext(` + import { Foo } from 'bar'; - Foo; - `); + Foo; + `); - const node = { name: 'Foo', type: 'Identifier' }; + const node = { name: 'Foo', type: 'Identifier' }; - expect(getSourceModuleNameForIdentifier(context, node)).toEqual('bar'); - }); + expect(getSourceModuleNameForIdentifier(context, node)).toStrictEqual('bar'); + }); - test('when aliasing a named export', () => { - const context = new FauxContext(` - import { SomeOtherThing as Foo } from 'bar'; + it('when aliasing a named export', () => { + const context = new FauxContext(` + import { SomeOtherThing as Foo } from 'bar'; - Foo; - `); + Foo; + `); - const node = { name: 'Foo', type: 'Identifier' }; + const node = { name: 'Foo', type: 'Identifier' }; - expect(getSourceModuleNameForIdentifier(context, node)).toEqual('bar'); - }); + expect(getSourceModuleNameForIdentifier(context, node)).toStrictEqual('bar'); + }); - test('Model.extend', () => { - const context = new FauxContext(` - import Model from '@ember-data/model'; + it('model.extend', () => { + const context = new FauxContext(` + import Model from '@ember-data/model'; - Model.extend(); - `); + Model.extend(); + `); - const node = babelEslint.parse('Model.extend({})').body[0].expression.callee; + const node = babelEslint.parse('Model.extend({})').body[0].expression.callee; - expect(getSourceModuleNameForIdentifier(context, node)).toEqual('@ember-data/model'); - }); + expect(getSourceModuleNameForIdentifier(context, node)).toStrictEqual('@ember-data/model'); + }); - test('DS.Model.extend', () => { - const context = new FauxContext(` - import DS from 'ember-data'; + it('dS.Model.extend', () => { + const context = new FauxContext(` + import DS from 'ember-data'; - DS.Model.extend(); - `); + DS.Model.extend(); + `); - const node = babelEslint.parse('DS.Model.extend({})').body[0].expression.callee; + const node = babelEslint.parse('DS.Model.extend({})').body[0].expression.callee; - expect(getSourceModuleNameForIdentifier(context, node)).toEqual('ember-data'); - }); + expect(getSourceModuleNameForIdentifier(context, node)).toStrictEqual('ember-data'); + }); - test('Some.Long.Chained.Path.extend', () => { - const context = new FauxContext(` - import Some from 'some-path'; + it('some.Long.Chained.Path.extend', () => { + const context = new FauxContext(` + import Some from 'some-path'; - Some.Long.Chained.Path.extend(); - `); + Some.Long.Chained.Path.extend(); + `); - const node = babelEslint.parse('Some.Long.Chained.Path.extend({})').body[0].expression.callee; + const node = babelEslint.parse('Some.Long.Chained.Path.extend({})').body[0].expression.callee; - expect(getSourceModuleNameForIdentifier(context, node)).toEqual('some-path'); - }); + expect(getSourceModuleNameForIdentifier(context, node)).toStrictEqual('some-path'); + }); - test('Model.extend(Mixin)', () => { - const context = new FauxContext(` - import Mixin from './my-mixin'; - import Model from '@ember-data/model'; + it('model.extend(Mixin)', () => { + const context = new FauxContext(` + import Mixin from './my-mixin'; + import Model from '@ember-data/model'; - export default class SomeClass extends Model.extend(Mixin) {} - `); + export default class SomeClass extends Model.extend(Mixin) {} + `); - const node = babelEslint.parse('Model.extend(Mixin)').body[0].expression; + const node = babelEslint.parse('Model.extend(Mixin)').body[0].expression; - expect(getSourceModuleNameForIdentifier(context, node)).toEqual('@ember-data/model'); + expect(getSourceModuleNameForIdentifier(context, node)).toStrictEqual('@ember-data/model'); + }); }); }); diff --git a/tests/plugin-exports.js b/tests/plugin-exports.js index a86be30bcd..c6610a934d 100644 --- a/tests/plugin-exports.js +++ b/tests/plugin-exports.js @@ -1,6 +1,5 @@ 'use strict'; -const assert = require('assert'); const plugin = require('../lib'); const ember = require('../lib/utils/ember'); const utils = require('../lib/utils/utils'); @@ -11,13 +10,13 @@ const octane = require('../lib/config/octane.js'); describe('plugin exports', () => { describe('utils', () => { it('has the right util functions', () => { - assert.deepStrictEqual(plugin.utils, { ember, utils }); + expect(plugin.utils).toStrictEqual({ ember, utils }); }); }); describe('configs', () => { it('has the right configurations', () => { - assert.deepStrictEqual(plugin.configs, { base, recommended, octane }); + expect(plugin.configs).toStrictEqual({ base, recommended, octane }); }); }); }); diff --git a/tests/recommended.js b/tests/recommended.js index e646c9b162..b2117cedcc 100644 --- a/tests/recommended.js +++ b/tests/recommended.js @@ -2,14 +2,16 @@ const rules = require('../lib').rules; -test('recommended rules', () => { - const errors = []; +describe('recommended rules', () => { + it('has the right list', () => { + const errors = []; - Object.keys(rules).forEach(name => { - if (rules[name].meta.docs.recommended) { - errors.push(name); - } - }); + Object.keys(rules).forEach(name => { + if (rules[name].meta.docs.recommended) { + errors.push(name); + } + }); - expect(errors).toMatchSnapshot(); + expect(errors).toMatchSnapshot(); + }); }); diff --git a/tests/rule-setup.js b/tests/rule-setup.js index a180f53775..b37ae5fcc9 100644 --- a/tests/rule-setup.js +++ b/tests/rule-setup.js @@ -2,7 +2,6 @@ const { readdirSync, readFileSync } = require('fs'); const { join } = require('path'); -const assert = require('assert'); const rules = require('../lib').rules; const recommendedRules = require('../lib/recommended-rules.js'); const octaneRules = require('../lib/octane-rules.js'); @@ -15,24 +14,21 @@ describe('rules setup is correct', function() { const path = join(__dirname, '../lib/rules'); const files = readdirSync(path); - // eslint-disable-next-line node/no-deprecated-api - assert.deepEqual( - RULE_NAMES, + // eslint-disable-next-line jest/prefer-strict-equal + expect(RULE_NAMES).toEqual( files.filter(file => !file.startsWith('.')).map(file => file.replace('.js', '')) ); }); it('should list all rules in the recommended rules file', function() { - assert.deepStrictEqual( - RULE_NAMES, + expect(RULE_NAMES).toStrictEqual( Object.keys(recommendedRules).map(file => file.replace('ember/', '')) ); }); it('should list all rules in the octane rules file', function() { const octaneRuleNames = Object.keys(rules).filter(key => rules[key].meta.docs.octane); - assert.deepStrictEqual( - OCTANE_RULE_NAMES.map(file => file.replace('ember/', '')), + expect(OCTANE_RULE_NAMES.map(file => file.replace('ember/', ''))).toStrictEqual( octaneRuleNames ); }); @@ -41,9 +37,8 @@ describe('rules setup is correct', function() { const path = join(__dirname, '../tests/lib/rules'); const files = readdirSync(path); - // eslint-disable-next-line node/no-deprecated-api - assert.deepEqual( - RULE_NAMES, + // eslint-disable-next-line jest/prefer-strict-equal + expect(RULE_NAMES).toEqual( files.filter(file => !file.startsWith('.')).map(file => file.replace('.js', '')) ); }); @@ -52,9 +47,8 @@ describe('rules setup is correct', function() { const path = join(__dirname, '../docs/rules'); const files = readdirSync(path); - // eslint-disable-next-line node/no-deprecated-api - assert.deepEqual( - RULE_NAMES, + // eslint-disable-next-line jest/prefer-strict-equal + expect(RULE_NAMES).toEqual( files .filter(file => !file.startsWith('.') && file !== '_TEMPLATE_.md') .map(file => file.replace('.md', '')) @@ -63,8 +57,8 @@ describe('rules setup is correct', function() { it('should mention all rules in the README', function() { const path = join(__dirname, '../README.md'); - const file = readFileSync(path); + const file = readFileSync(path, 'utf8'); - RULE_NAMES.forEach(ruleName => assert.ok(file.includes(ruleName))); + RULE_NAMES.forEach(ruleName => expect(file).toContain(ruleName)); }); }); diff --git a/yarn.lock b/yarn.lock index d8a805e443..6a06a9ea55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -361,6 +361,11 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/json-schema@^7.0.3": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" + integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== + "@types/node@*": version "10.12.7" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.7.tgz#195808b2d4b2e7c33e75e7d9b24aeee88f94660d" @@ -386,6 +391,28 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/experimental-utils@^2.5.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.11.0.tgz#cef18e6b122706c65248a5d8984a9779ed1e52ac" + integrity sha512-YxcA/y0ZJaCc/fB/MClhcDxHI0nOBB7v2/WxBju2cOTanX7jO9ttQq6Fy4yW9UaY5bPd9xL3cun3lDVqk67sPQ== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.11.0" + eslint-scope "^5.0.0" + +"@typescript-eslint/typescript-estree@2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.11.0.tgz#21ada6504274cd1644855926312c798fc697e9fb" + integrity sha512-HGY4+d4MagO6cKMcKfIKaTMxcAv7dEVnji2Zi+vi5VV8uWAM631KjAB5GxFcexMYrwKT0EekRiiGK1/Sd7VFGA== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash.unescape "4.0.1" + semver "^6.3.0" + tsutils "^3.17.1" + abab@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -1362,6 +1389,13 @@ eslint-plugin-import@^2.19.1: read-pkg-up "^2.0.0" resolve "^1.12.0" +eslint-plugin-jest@^23.1.1: + version "23.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.1.1.tgz#1220ab53d5a4bf5c3c4cd07c0dabc6199d4064dd" + integrity sha512-2oPxHKNh4j1zmJ6GaCBuGcb8FVZU7YjFUOJzGOPnl9ic7VA/MGAskArLJiRIlnFUmi1EUxY+UiATAy8dv8s5JA== + dependencies: + "@typescript-eslint/experimental-utils" "^2.5.0" + eslint-plugin-node@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz#fd1adbc7a300cf7eb6ac55cf4b0b6fc6e577f5a6" @@ -1869,7 +1903,7 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.4: +glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -3003,6 +3037,11 @@ lodash.topairs@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.topairs/-/lodash.topairs-4.3.0.tgz#3b6deaa37d60fb116713c46c5f17ea190ec48d64" integrity sha1-O23qo31g+xFnE8RsXxfqGQ7EjWQ= +lodash.unescape@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" + integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= + lodash.upperfirst@4.3.1, lodash.upperfirst@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" @@ -4610,11 +4649,18 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" -tslib@^1.10.0, tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"