From d7b76b8490a56ffaa1d58c7522b273061fdecf1f Mon Sep 17 00:00:00 2001 From: Kumar McMillan Date: Thu, 18 Aug 2016 11:27:15 -0500 Subject: [PATCH 1/3] Use eslint to catch import mistakes and style nits --- .eslintrc | 62 ++++++++++++++++++- bin/.eslintrc | 8 +++ bin/build-checks.js | 1 - bin/server.js | 1 - bin/webpack-dev-server.js | 5 +- karma.conf.js | 12 ++-- package.json | 10 +-- src/amo/client.js | 5 +- src/amo/components/AddonMeta.js | 4 +- src/amo/components/LikeButton.js | 4 +- src/amo/components/ScreenShots.js | 4 +- src/amo/components/SearchBox.js | 4 +- src/amo/containers/App.js | 4 +- src/amo/containers/DetailPage.js | 4 +- src/amo/store.js | 2 +- src/core/api/index.js | 5 +- src/core/client/base.js | 7 +-- src/core/components/InstallButton/index.js | 6 +- src/core/components/NotFound.js | 1 + src/core/containers/HandleLogin/index.js | 2 +- src/core/containers/LoginRequired/index.js | 5 +- src/core/i18n/utils.js | 1 + src/core/middleware.js | 3 +- src/core/purify.js | 1 + src/core/server/base.js | 19 +++--- .../server/webpack-isomorphic-tools-config.js | 5 +- src/core/tracking.js | 2 +- src/disco/addonManager.js | 1 - src/disco/client.js | 5 +- src/disco/components/Addon.js | 9 ++- src/disco/components/InfoDialog.js | 6 +- src/disco/containers/App.js | 4 +- src/disco/containers/DiscoPane.js | 21 +++---- src/disco/store.js | 2 +- src/search/client.js | 1 + src/search/components/SearchForm.js | 4 +- src/search/components/SearchPage.js | 3 +- src/search/containers/AddonPage/index.js | 1 + src/search/containers/CurrentSearchPage.js | 3 +- src/search/containers/UserPage/index.js | 4 +- src/search/routes.js | 5 +- test-runner.js | 4 +- tests/.eslintrc | 8 +++ .../client/amo/components/TestAddonDetail.js | 2 +- tests/client/amo/containers/TestApp.js | 2 +- tests/client/amo/containers/TestDetail.js | 2 +- tests/client/core/api/test_api.js | 3 +- tests/client/core/client/test_logger.js | 1 + .../core/components/TestInstallButton.js | 7 ++- tests/client/core/components/TestNotFound.js | 1 + tests/client/core/components/TestPaginate.js | 1 + .../client/core/containers/TestHandleLogin.js | 1 + .../core/containers/TestLoginRequired.js | 14 +++-- .../client/core/containers/TestServerHtml.js | 2 +- tests/client/core/i18n/TestI18nProvider.js | 9 +-- tests/client/core/i18n/test_utils.js | 3 +- tests/client/core/test_utils.js | 2 +- tests/client/disco/TestAddonManager.js | 3 +- tests/client/disco/components/TestAddon.js | 12 ++-- .../client/disco/components/TestInfoDialog.js | 4 +- tests/client/disco/containers/TestApp.js | 4 +- .../client/disco/containers/TestDiscoPane.js | 18 +++--- tests/client/helpers.js | 3 +- .../client/search/components/TestJsonData.js | 1 + .../search/components/TestSearchForm.js | 8 ++- .../search/components/TestSearchPage.js | 3 +- .../search/components/TestSearchResult.js | 1 + .../client/search/containers/TestAddonPage.js | 1 + tests/client/search/containers/TestApp.js | 3 +- .../search/{ => containers}/TestUserPage.js | 5 +- tests/server/TestConfig.js | 5 +- tests/server/TestLocalesConfig.js | 6 +- tests/server/amo/TestViews.js | 5 +- tests/server/disco/TestViews.js | 5 +- tests/server/search/TestViews.js | 5 +- webpack.dev.config.babel.js | 10 +-- webpack.l10n.config.babel.js | 5 +- webpack.prod.config.babel.js | 14 ++--- 78 files changed, 274 insertions(+), 165 deletions(-) create mode 100644 bin/.eslintrc rename webpack-isomorphic-tools-config.js => src/core/server/webpack-isomorphic-tools-config.js (95%) create mode 100644 tests/.eslintrc rename tests/client/search/{ => containers}/TestUserPage.js (93%) diff --git a/.eslintrc b/.eslintrc index 92b6ca376ed..fe117fc3d78 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,12 +13,72 @@ "parser": "babel-eslint", "rules": { "arrow-parens": ["error", "always"], - "import/no-unresolved": "off", + // This makes sure imported modules exist. + "import/no-unresolved": ["error"], + // This makes sure imported names exist. + "import/named": ["error"], + // This will catch accidental default imports when no default is defined. + "import/default": ["error"], + // This makes sure `*' imports are dereferenced to real exports. + "import/namespace": ["error"], + // This catches any export mistakes. + "import/export": ["error"], + // This catches default names that conflict with actual exported names. + // For example, this was probably a typo: + // import foo from 'bar'; + // that should be corrected as: + // import { foo } from 'bar'; + "import/no-named-as-default": ["error"], + // This catches possible typos like trying to access a real export on a + // default import. + "import/no-named-as-default-member": ["error"], + // This prevents exporting a mutable variable. + "import/no-mutable-exports": ["error"], + // This makes sure package.json defines dev vs. prod dependencies correctly. + "import/no-extraneous-dependencies": ["error", { + // The following are not allowed to be imported. See .eslintrc in other + // directories (like ./test) for where this gets overidden. + "devDependencies": false, "optionalDependencies": false, "peerDependencies": false + }], + // This ensures imports are at the top of the file. + "import/imports-first": ["error"], + // This catches duplicate exports. + "import/no-duplicates": ["error"], + // This ensures import statements never provide a file extension in the path. + "import/extensions": ["error", "never"], + // This ensures imports are organized by type and that groups are separated + // by a new line. + "import/order": ["error", { + "groups": [ + "builtin", "external", "internal", ["parent", "sibling"], "index" + ], + "newlines-between": "always" + }], + // This ensures a new line after all import statements. + "import/newline-after-import": ["error"], "no-underscore-dangle": "off", "space-before-function-paren": ["error", "never"], "react/prefer-stateless-function": "off", "react/jsx-indent-props": "off", "react/jsx-closing-bracket-location": "off", "react/jsx-first-prop-new-line": "off" + }, + "settings": { + "import/ignore": [ + // Because of CommonJS incompatibility, we can't + // check for bad imports in node_modules. + "node_modules", + // Ignore non-JS imports. + "\\.scss$", + "\\.jpg$", + "\\.mp4$", + "\\.webm$" + ], + "import/resolver": { + "node": { + // This adds ./src for relative imports. + "moduleDirectory": ["node_modules", "src"] + } + } } } diff --git a/bin/.eslintrc b/bin/.eslintrc new file mode 100644 index 00000000000..0b3f7a7b4e3 --- /dev/null +++ b/bin/.eslintrc @@ -0,0 +1,8 @@ +{ + "rules": { + "import/no-extraneous-dependencies": ["error", { + // Allow dev-dependencies in this directory. + "devDependencies": true + }], + } +} diff --git a/bin/build-checks.js b/bin/build-checks.js index 0541da3f5a1..8a26b4dcfce 100755 --- a/bin/build-checks.js +++ b/bin/build-checks.js @@ -2,7 +2,6 @@ /* eslint-disable global-require, no-console */ const chalk = require('chalk'); - require('babel-register'); const config = require('config'); diff --git a/bin/server.js b/bin/server.js index 95c08a8a46a..50bef031e05 100644 --- a/bin/server.js +++ b/bin/server.js @@ -2,7 +2,6 @@ /* eslint-disable global-require, no-console */ const chalk = require('chalk'); - require('babel-register'); const config = require('config'); diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index 338158b08c7..c0bb11fb9e0 100644 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -3,14 +3,13 @@ /* eslint-disable strict, no-console */ require('babel-register'); - const Express = require('express'); +const config = require('config'); const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); const webpackHotMiddleware = require('webpack-hot-middleware'); -const webpackDevConfig = require('webpack.dev.config.babel').default; -const config = require('config'); +const webpackDevConfig = require('../webpack.dev.config.babel').default; const host = config.get('webpackServerHost'); const port = config.get('webpackServerPort'); diff --git a/karma.conf.js b/karma.conf.js index b8073460032..6c9e1a77618 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,18 +1,20 @@ // Karma configuration -/* eslint-disable max-len, no-console, strict */ +/* eslint-disable max-len, no-console, strict, import/no-extraneous-dependencies */ 'use strict'; require('babel-register'); const fs = require('fs'); -const babelrc = fs.readFileSync('./.babelrc'); -const babelQuery = JSON.parse(babelrc); const webpack = require('webpack'); -const webpackConfigProd = require('./webpack.prod.config.babel').default; const config = require('config'); -const getClientConfig = require('src/core/utils').getClientConfig; + +const getClientConfig = require('./src/core/utils').getClientConfig; +const webpackConfigProd = require('./webpack.prod.config.babel').default; + const clientConfig = getClientConfig(config); +const babelrc = fs.readFileSync('./.babelrc'); +const babelQuery = JSON.parse(babelrc); const coverageReporters = [{ type: 'text-summary', diff --git a/package.json b/package.json index a7780df68d5..c2199dc6dac 100644 --- a/package.json +++ b/package.json @@ -138,6 +138,7 @@ "homepage": "https://github.com/mozillla/addons-frontend#readme", "dependencies": { "babel-plugin-dedent": "2.0.0", + "babel-polyfill": "6.13.0", "better-npm-run": "0.0.11", "bunyan": "1.8.1", "camelcase": "3.0.0", @@ -156,6 +157,7 @@ "react": "15.3.0", "react-addons-css-transition-group": "15.3.1", "react-cookie": "0.4.8", + "react-dom": "15.3.1", "react-helmet": "3.1.0", "react-onclickoutside": "5.3.3", "react-redux": "4.4.5", @@ -165,7 +167,8 @@ "redux-logger": "2.6.1", "serialize-javascript": "1.3.0", "url": "0.11.0", - "url-loader": "0.5.7" + "url-loader": "0.5.7", + "webpack-isomorphic-tools": "2.5.7" }, "devDependencies": { "autoprefixer": "6.4.0", @@ -178,7 +181,6 @@ "babel-plugin-transform-class-properties": "6.11.5", "babel-plugin-transform-decorators-legacy": "1.3.4", "babel-plugin-transform-object-rest-spread": "6.8.0", - "babel-polyfill": "6.13.0", "babel-preset-es2015": "6.13.2", "babel-preset-react": "6.11.1", "babel-preset-stage-2": "6.13.0", @@ -213,7 +215,6 @@ "po2json": "0.4.2", "postcss-loader": "0.10.1", "react-addons-test-utils": "15.3.1", - "react-dom": "15.3.1", "react-hot-loader": "1.3.0", "react-transform-hmr": "1.0.4", "redux-devtools": "3.3.1", @@ -233,7 +234,6 @@ "webpack": "1.13.2", "webpack-dev-middleware": "1.6.1", "webpack-dev-server": "1.14.1", - "webpack-hot-middleware": "2.12.2", - "webpack-isomorphic-tools": "2.5.7" + "webpack-hot-middleware": "2.12.2" } } diff --git a/src/amo/client.js b/src/amo/client.js index 671ebdddb17..033ba841a8d 100644 --- a/src/amo/client.js +++ b/src/amo/client.js @@ -1,8 +1,9 @@ import makeClient from 'core/client/base'; -import routes from './routes'; -import createStore from './store'; // Initialize the tracking. import 'core/tracking'; +import routes from './routes'; +import createStore from './store'; + makeClient(routes, createStore); diff --git a/src/amo/components/AddonMeta.js b/src/amo/components/AddonMeta.js index dab33fd798e..303708ac3af 100644 --- a/src/amo/components/AddonMeta.js +++ b/src/amo/components/AddonMeta.js @@ -4,7 +4,7 @@ import translate from 'core/i18n/translate'; import 'amo/css/AddonMeta.scss'; -export class AddonMeta extends React.Component { +export class AddonMetaBase extends React.Component { static propTypes = { i18n: PropTypes.object, } @@ -34,4 +34,4 @@ export class AddonMeta extends React.Component { } } -export default translate({ withRef: true })(AddonMeta); +export default translate({ withRef: true })(AddonMetaBase); diff --git a/src/amo/components/LikeButton.js b/src/amo/components/LikeButton.js index 9583b390c5e..fb87dd096ea 100644 --- a/src/amo/components/LikeButton.js +++ b/src/amo/components/LikeButton.js @@ -4,7 +4,7 @@ import translate from 'core/i18n/translate'; import 'amo/css/LikeButton.scss'; -export class LikeButton extends React.Component { +export class LikeButtonBase extends React.Component { static propTypes = { i18n: PropTypes.object, } @@ -21,4 +21,4 @@ export class LikeButton extends React.Component { } } -export default translate({ withRef: true })(LikeButton); +export default translate({ withRef: true })(LikeButtonBase); diff --git a/src/amo/components/ScreenShots.js b/src/amo/components/ScreenShots.js index cf8090ecf42..5f800c9efb1 100644 --- a/src/amo/components/ScreenShots.js +++ b/src/amo/components/ScreenShots.js @@ -5,7 +5,7 @@ import translate from 'core/i18n/translate'; import 'amo/css/ScreenShots.scss'; -export class ScreenShots extends React.Component { +export class ScreenShotsBase extends React.Component { static propTypes = { i18n: PropTypes.object, } @@ -36,4 +36,4 @@ export class ScreenShots extends React.Component { } } -export default translate({ withRef: true })(ScreenShots); +export default translate({ withRef: true })(ScreenShotsBase); diff --git a/src/amo/components/SearchBox.js b/src/amo/components/SearchBox.js index c63c4c9c0b9..9342d629f02 100644 --- a/src/amo/components/SearchBox.js +++ b/src/amo/components/SearchBox.js @@ -5,7 +5,7 @@ import translate from 'core/i18n/translate'; import 'amo/css/SearchBox.scss'; -export class SearchBox extends React.Component { +export class SearchBoxBase extends React.Component { static propTypes = { i18n: PropTypes.object, } @@ -22,4 +22,4 @@ export class SearchBox extends React.Component { } } -export default translate({ withRef: true })(SearchBox); +export default translate({ withRef: true })(SearchBoxBase); diff --git a/src/amo/containers/App.js b/src/amo/containers/App.js index 8d5aa6f9f8c..58f83169fd3 100644 --- a/src/amo/containers/App.js +++ b/src/amo/containers/App.js @@ -6,7 +6,7 @@ import 'amo/css/App.scss'; import translate from 'core/i18n/translate'; -export class App extends React.Component { +export class AppBase extends React.Component { static propTypes = { children: PropTypes.node, i18n: PropTypes.object.isRequired, @@ -25,4 +25,4 @@ export class App extends React.Component { } } -export default translate({ withRef: true })(App); +export default translate({ withRef: true })(AppBase); diff --git a/src/amo/containers/DetailPage.js b/src/amo/containers/DetailPage.js index 2a958a4def1..33c1165356a 100644 --- a/src/amo/containers/DetailPage.js +++ b/src/amo/containers/DetailPage.js @@ -7,7 +7,7 @@ import AddonDetail from 'amo/components/AddonDetail'; import translate from 'core/i18n/translate'; import { loadAddonIfNeeded } from 'core/utils'; -export class DetailPage extends React.Component { +export class DetailPageBase extends React.Component { static propTypes = { addon: PropTypes.object, } @@ -36,4 +36,4 @@ export default compose( }]), connect(mapStateToProps), translate({ withRef: true }), -)(DetailPage); +)(DetailPageBase); diff --git a/src/amo/store.js b/src/amo/store.js index ddc901b3f93..33454e1d312 100644 --- a/src/amo/store.js +++ b/src/amo/store.js @@ -1,7 +1,7 @@ import { createStore as _createStore, combineReducers } from 'redux'; import { reducer as reduxAsyncConnect } from 'redux-async-connect'; -import { middleware } from 'core/store'; +import { middleware } from 'core/store'; import addons from 'core/reducers/addons'; import api from 'core/reducers/api'; diff --git a/src/core/api/index.js b/src/core/api/index.js index 5eac47671c3..2ab2a499468 100644 --- a/src/core/api/index.js +++ b/src/core/api/index.js @@ -1,9 +1,8 @@ -import { Schema, arrayOf, normalize } from 'normalizr'; import url from 'url'; -import config from 'config'; - import 'isomorphic-fetch'; +import { Schema, arrayOf, normalize } from 'normalizr'; +import config from 'config'; const API_BASE = `${config.get('apiHost')}${config.get('apiPath')}`; diff --git a/src/core/client/base.js b/src/core/client/base.js index 4107f719809..7019e32ff5b 100644 --- a/src/core/client/base.js +++ b/src/core/client/base.js @@ -1,15 +1,14 @@ import 'babel-polyfill'; -import React from 'react'; - import config from 'config'; +import Jed from 'jed'; +import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; import { Router, browserHistory } from 'react-router'; import { ReduxAsyncConnect } from 'redux-async-connect'; + import { langToLocale, sanitizeLanguage } from 'core/i18n/utils'; import I18nProvider from 'core/i18n/Provider'; -import Jed from 'jed'; - import log from 'core/logger'; diff --git a/src/core/components/InstallButton/index.js b/src/core/components/InstallButton/index.js index 4645793f01f..40e26a8155d 100644 --- a/src/core/components/InstallButton/index.js +++ b/src/core/components/InstallButton/index.js @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react'; -import translate from 'core/i18n/translate'; +import translate from 'core/i18n/translate'; import { DOWNLOADING, DISABLED, @@ -19,7 +19,7 @@ import { getThemeData } from 'disco/themePreview'; import './InstallButton.scss'; -export class InstallButton extends React.Component { +export class InstallButtonBase extends React.Component { static propTypes = { downloadProgress: PropTypes.number, enable: PropTypes.func, @@ -122,4 +122,4 @@ export class InstallButton extends React.Component { } } -export default translate()(InstallButton); +export default translate()(InstallButtonBase); diff --git a/src/core/components/NotFound.js b/src/core/components/NotFound.js index 81599425569..5bd0e804112 100644 --- a/src/core/components/NotFound.js +++ b/src/core/components/NotFound.js @@ -1,4 +1,5 @@ import React from 'react'; + import { gettext as _ } from 'core/utils'; export default class NotFound extends React.Component { diff --git a/src/core/containers/HandleLogin/index.js b/src/core/containers/HandleLogin/index.js index 50b17522bd4..16c958d6112 100644 --- a/src/core/containers/HandleLogin/index.js +++ b/src/core/containers/HandleLogin/index.js @@ -1,8 +1,8 @@ import React, { PropTypes } from 'react'; import cookie from 'react-cookie'; import { connect } from 'react-redux'; - import config from 'config'; + import { setJWT } from 'core/actions'; import { login } from 'core/api'; import LoginPage from 'core/components/LoginPage'; diff --git a/src/core/containers/LoginRequired/index.js b/src/core/containers/LoginRequired/index.js index 0f7769922bc..e9fd3be92d9 100644 --- a/src/core/containers/LoginRequired/index.js +++ b/src/core/containers/LoginRequired/index.js @@ -1,5 +1,6 @@ import React, { PropTypes } from 'react'; import { connect } from 'react-redux'; + import LoginPage from 'core/components/LoginPage'; export function mapStateToProps(state) { @@ -9,7 +10,7 @@ export function mapStateToProps(state) { } // This class is exported for testing outside of redux. -export class LoginRequired extends React.Component { +export class LoginRequiredBase extends React.Component { static propTypes = { authenticated: PropTypes.bool.isRequired, children: PropTypes.node, @@ -24,4 +25,4 @@ export class LoginRequired extends React.Component { } } -export default connect(mapStateToProps)(LoginRequired); +export default connect(mapStateToProps)(LoginRequiredBase); diff --git a/src/core/i18n/utils.js b/src/core/i18n/utils.js index 0c9f6ffb9e6..b616ec3f653 100644 --- a/src/core/i18n/utils.js +++ b/src/core/i18n/utils.js @@ -1,4 +1,5 @@ import config from 'config'; + import log from 'core/logger'; const defaultLang = config.get('defaultLang'); diff --git a/src/core/middleware.js b/src/core/middleware.js index 30f1b7c465d..57f62e0ec47 100644 --- a/src/core/middleware.js +++ b/src/core/middleware.js @@ -1,6 +1,7 @@ +import config from 'config'; + import { getClientApp, isValidClientApp } from 'core/utils'; import { getLanguage, isValidLang } from 'core/i18n/utils'; -import config from 'config'; import log from 'core/logger'; diff --git a/src/core/purify.js b/src/core/purify.js index 3c4f56b6f44..5422f07b6f0 100644 --- a/src/core/purify.js +++ b/src/core/purify.js @@ -1,4 +1,5 @@ import createDOMPurify from 'dompurify'; + import universalWindow from 'core/window'; const purify = createDOMPurify(universalWindow); diff --git a/src/core/server/base.js b/src/core/server/base.js index 7da6b4d5116..8e7abb9809b 100644 --- a/src/core/server/base.js +++ b/src/core/server/base.js @@ -1,29 +1,28 @@ -import 'babel-polyfill'; - import fs from 'fs'; +import path from 'path'; + +import 'babel-polyfill'; +import config from 'config'; import Express from 'express'; import helmet from 'helmet'; -import path from 'path'; +import Jed from 'jed'; import cookie from 'react-cookie'; import React from 'react'; import ReactDOM from 'react-dom/server'; - import { Provider } from 'react-redux'; import { match } from 'react-router'; import { ReduxAsyncConnect, loadOnServer } from 'redux-async-connect'; -import { prefixMiddleWare } from 'core/middleware'; - import WebpackIsomorphicTools from 'webpack-isomorphic-tools'; -import WebpackIsomorphicToolsConfig from 'webpack-isomorphic-tools-config'; -import ServerHtml from 'core/containers/ServerHtml'; -import config from 'config'; +import ServerHtml from 'core/containers/ServerHtml'; +import { prefixMiddleWare } from 'core/middleware'; import { convertBoolean } from 'core/utils'; import { setLang, setJWT } from 'core/actions'; import log from 'core/logger'; import { getDirection, isValidLang, langToLocale } from 'core/i18n/utils'; import I18nProvider from 'core/i18n/Provider'; -import Jed from 'jed'; + +import WebpackIsomorphicToolsConfig from './webpack-isomorphic-tools-config'; const env = config.util.getEnv('NODE_ENV'); diff --git a/webpack-isomorphic-tools-config.js b/src/core/server/webpack-isomorphic-tools-config.js similarity index 95% rename from webpack-isomorphic-tools-config.js rename to src/core/server/webpack-isomorphic-tools-config.js index 10d48185d0f..d0b766cd3e5 100644 --- a/webpack-isomorphic-tools-config.js +++ b/src/core/server/webpack-isomorphic-tools-config.js @@ -1,8 +1,7 @@ /* eslint-disable no-else-return */ +import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin'; -const WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin'); - -module.exports = { +export default { debug: false, assets: { images: { diff --git a/src/core/tracking.js b/src/core/tracking.js index 91f12876c24..fa752feaafd 100644 --- a/src/core/tracking.js +++ b/src/core/tracking.js @@ -1,6 +1,6 @@ /* eslint-disable no-underscore-dangle */ - import config from 'config'; + import { convertBoolean } from 'core/utils'; import log from 'core/logger'; diff --git a/src/disco/addonManager.js b/src/disco/addonManager.js index 7bb4c200c32..2c192063011 100644 --- a/src/disco/addonManager.js +++ b/src/disco/addonManager.js @@ -1,5 +1,4 @@ import log from 'core/logger'; - import { globalEvents, globalEventStatusMap, diff --git a/src/disco/client.js b/src/disco/client.js index 671ebdddb17..033ba841a8d 100644 --- a/src/disco/client.js +++ b/src/disco/client.js @@ -1,8 +1,9 @@ import makeClient from 'core/client/base'; -import routes from './routes'; -import createStore from './store'; // Initialize the tracking. import 'core/tracking'; +import routes from './routes'; +import createStore from './store'; + makeClient(routes, createStore); diff --git a/src/disco/components/Addon.js b/src/disco/components/Addon.js index f8b14ed1672..be364bd1e72 100644 --- a/src/disco/components/Addon.js +++ b/src/disco/components/Addon.js @@ -3,15 +3,14 @@ import { sprintf } from 'jed'; import React, { PropTypes } from 'react'; import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; import { connect } from 'react-redux'; -import translate from 'core/i18n/translate'; +import config from 'config'; +import translate from 'core/i18n/translate'; import { sanitizeHTML } from 'core/utils'; -import config from 'config'; import themeAction, { getThemeData } from 'disco/themePreview'; import tracking from 'core/tracking'; import * as addonManager from 'disco/addonManager'; import log from 'core/logger'; - import InstallButton from 'core/components/InstallButton'; import { DISABLED, @@ -46,7 +45,7 @@ import { import 'disco/css/Addon.scss'; -export class Addon extends React.Component { +export class AddonBase extends React.Component { static propTypes = { accentcolor: PropTypes.string, description: PropTypes.string, @@ -402,4 +401,4 @@ export function mapDispatchToProps(dispatch, { _tracking = tracking, export default translate({ withRef: true })(connect( mapStateToProps, mapDispatchToProps, undefined, { withRef: true } -)(Addon)); +)(AddonBase)); diff --git a/src/disco/components/InfoDialog.js b/src/disco/components/InfoDialog.js index c2737a13bf0..0d38632874d 100644 --- a/src/disco/components/InfoDialog.js +++ b/src/disco/components/InfoDialog.js @@ -1,10 +1,10 @@ import React, { PropTypes } from 'react'; -import translate from 'core/i18n/translate'; import onClickOutside from 'react-onclickoutside'; +import translate from 'core/i18n/translate'; import 'disco/css/InfoDialog.scss'; -export class InfoDialog extends React.Component { +export class InfoDialogBase extends React.Component { static propTypes = { addonName: PropTypes.string.isRequired, closeAction: PropTypes.func.isRequired, @@ -39,4 +39,4 @@ export class InfoDialog extends React.Component { } } -export default translate()(onClickOutside(InfoDialog)); +export default translate()(onClickOutside(InfoDialogBase)); diff --git a/src/disco/containers/App.js b/src/disco/containers/App.js index 469daf0851a..3522952fcb1 100644 --- a/src/disco/containers/App.js +++ b/src/disco/containers/App.js @@ -5,7 +5,7 @@ import 'disco/css/App.scss'; import translate from 'core/i18n/translate'; -export class App extends React.Component { +export class AppBase extends React.Component { static propTypes = { children: PropTypes.node, i18n: PropTypes.object.isRequired, @@ -27,4 +27,4 @@ export class App extends React.Component { } } -export default translate({ withRef: true })(App); +export default translate({ withRef: true })(AppBase); diff --git a/src/disco/containers/DiscoPane.js b/src/disco/containers/DiscoPane.js index 9eb84b8a520..a56548dba76 100644 --- a/src/disco/containers/DiscoPane.js +++ b/src/disco/containers/DiscoPane.js @@ -1,32 +1,29 @@ /* eslint-disable max-len */ - import React, { PropTypes } from 'react'; import { connect } from 'react-redux'; import { asyncConnect } from 'redux-async-connect'; -import { camelCaseProps } from 'core/utils'; - import config from 'config'; -import { getDiscoveryAddons } from 'disco/api'; -import { discoResults } from 'disco/actions'; + +import { camelCaseProps } from 'core/utils'; import { loadEntities } from 'core/actions'; +import translate from 'core/i18n/translate'; +import tracking from 'core/tracking'; +import { INSTALL_STATE } from 'core/constants'; import { addChangeListeners } from 'disco/addonManager'; import { NAVIGATION_CATEGORY, VIDEO_CATEGORY, } from 'disco/constants'; -import { INSTALL_STATE } from 'core/constants'; - +import { getDiscoveryAddons } from 'disco/api'; +import { discoResults } from 'disco/actions'; import Addon from 'disco/components/Addon'; import InfoDialog from 'disco/components/InfoDialog'; -import translate from 'core/i18n/translate'; -import tracking from 'core/tracking'; - import videoPoster from 'disco/img/AddOnsPoster.jpg'; import videoMp4 from 'disco/video/AddOns.mp4'; import videoWebm from 'disco/video/AddOns.webm'; -export class DiscoPane extends React.Component { +export class DiscoPaneBase extends React.Component { static propTypes = { AddonComponent: PropTypes.func.isRequred, handleGlobalEvent: PropTypes.func.isRequired, @@ -170,4 +167,4 @@ export function mapDispatchToProps(dispatch, { _config = config } = {}) { export default asyncConnect([{ deferred: true, promise: loadDataIfNeeded, -}])(connect(mapStateToProps, mapDispatchToProps)(translate()(DiscoPane))); +}])(connect(mapStateToProps, mapDispatchToProps)(translate()(DiscoPaneBase))); diff --git a/src/disco/store.js b/src/disco/store.js index 5805650a6c1..7575f3b65ad 100644 --- a/src/disco/store.js +++ b/src/disco/store.js @@ -1,7 +1,7 @@ import { createStore as _createStore, combineReducers } from 'redux'; import { reducer as reduxAsyncConnect } from 'redux-async-connect'; -import { middleware } from 'core/store'; +import { middleware } from 'core/store'; import addons from 'core/reducers/addons'; import api from 'core/reducers/api'; import discoResults from 'disco/reducers/discoResults'; diff --git a/src/search/client.js b/src/search/client.js index 3a48ed62b04..7e11addba08 100644 --- a/src/search/client.js +++ b/src/search/client.js @@ -1,4 +1,5 @@ import makeClient from 'core/client/base'; + import routes from './routes'; import createStore from './store'; diff --git a/src/search/components/SearchForm.js b/src/search/components/SearchForm.js index 59f8f1c57bc..aebb1ba427e 100644 --- a/src/search/components/SearchForm.js +++ b/src/search/components/SearchForm.js @@ -8,7 +8,7 @@ import { gettext as _ } from 'core/utils'; import 'search/css/SearchForm.scss'; import 'search/css/lib/buttons.scss'; -export class SearchForm extends React.Component { +export class SearchFormBase extends React.Component { static propTypes = { api: PropTypes.object.isRequired, loadAddon: PropTypes.func.isRequired, @@ -69,4 +69,4 @@ export function mapDispatchToProps(dispatch) { }; } -export default connect(mapStateToProps, mapDispatchToProps)(SearchForm); +export default connect(mapStateToProps, mapDispatchToProps)(SearchFormBase); diff --git a/src/search/components/SearchPage.js b/src/search/components/SearchPage.js index 30fc2d4bc99..39a5813571e 100644 --- a/src/search/components/SearchPage.js +++ b/src/search/components/SearchPage.js @@ -1,9 +1,10 @@ import React, { PropTypes } from 'react'; import Paginate from 'core/components/Paginate'; +import { gettext as _ } from 'core/utils'; + import SearchForm from './SearchForm'; import SearchResults from './SearchResults'; -import { gettext as _ } from 'core/utils'; export default class SearchPage extends React.Component { static propTypes = { diff --git a/src/search/containers/AddonPage/index.js b/src/search/containers/AddonPage/index.js index da21305132b..a8dd72e11e0 100644 --- a/src/search/containers/AddonPage/index.js +++ b/src/search/containers/AddonPage/index.js @@ -1,6 +1,7 @@ import React, { PropTypes } from 'react'; import { connect } from 'react-redux'; import { asyncConnect } from 'redux-async-connect'; + import { gettext as _, loadAddonIfNeeded } from 'core/utils'; import NotFound from 'core/components/NotFound'; import JsonData from 'search/components/JsonData'; diff --git a/src/search/containers/CurrentSearchPage.js b/src/search/containers/CurrentSearchPage.js index 78cf30a1164..b9131fa2bb4 100644 --- a/src/search/containers/CurrentSearchPage.js +++ b/src/search/containers/CurrentSearchPage.js @@ -1,8 +1,9 @@ import { connect } from 'react-redux'; import { asyncConnect } from 'redux-async-connect'; + +import { search } from 'core/api'; import SearchPage from 'search/components/SearchPage'; import { searchStart, searchLoad, searchFail } from 'search/actions'; -import { search } from 'core/api'; export function mapStateToProps(state) { return state.search; diff --git a/src/search/containers/UserPage/index.js b/src/search/containers/UserPage/index.js index 8ad8039231f..b39c5d87475 100644 --- a/src/search/containers/UserPage/index.js +++ b/src/search/containers/UserPage/index.js @@ -7,7 +7,7 @@ import { fetchProfile } from 'core/api'; import './styles.scss'; -export class UserPage extends React.Component { +export class UserPageBase extends React.Component { static propTypes = { email: PropTypes.string.isRequired, username: PropTypes.string.isRequired, @@ -51,4 +51,4 @@ export function loadProfileIfNeeded({ store: { getState, dispatch } }) { export default asyncConnect([{ deferred: true, promise: loadProfileIfNeeded, -}])(connect(mapStateToProps)(UserPage)); +}])(connect(mapStateToProps)(UserPageBase)); diff --git a/src/search/routes.js b/src/search/routes.js index 21301a9f724..f40065561ce 100644 --- a/src/search/routes.js +++ b/src/search/routes.js @@ -1,12 +1,13 @@ import React from 'react'; import { IndexRoute, Route } from 'react-router'; +import LoginRequired from 'core/containers/LoginRequired'; +import HandleLogin from 'core/containers/HandleLogin'; + import App from './containers/App'; import CurrentSearchPage from './containers/CurrentSearchPage'; import AddonPage from './containers/AddonPage'; import UserPage from './containers/UserPage'; -import LoginRequired from 'core/containers/LoginRequired'; -import HandleLogin from 'core/containers/HandleLogin'; export default ( diff --git a/test-runner.js b/test-runner.js index 8a54abc433d..1159fb72cc8 100644 --- a/test-runner.js +++ b/test-runner.js @@ -1,5 +1,7 @@ +/* eslint-disable import/no-extraneous-dependencies */ require('babel-polyfill'); -require('tests/client/init'); + +require('./tests/client/init'); const testsContext = require.context('./tests/client/', true, /\.js$/); const componentsContext = require.context( diff --git a/tests/.eslintrc b/tests/.eslintrc new file mode 100644 index 00000000000..0b3f7a7b4e3 --- /dev/null +++ b/tests/.eslintrc @@ -0,0 +1,8 @@ +{ + "rules": { + "import/no-extraneous-dependencies": ["error", { + // Allow dev-dependencies in this directory. + "devDependencies": true + }], + } +} diff --git a/tests/client/amo/components/TestAddonDetail.js b/tests/client/amo/components/TestAddonDetail.js index 7457c14e5df..91ebe0accfb 100644 --- a/tests/client/amo/components/TestAddonDetail.js +++ b/tests/client/amo/components/TestAddonDetail.js @@ -10,7 +10,7 @@ import AddonDetail, { allowedDescriptionTags } import I18nProvider from 'core/i18n/Provider'; import InstallButton from 'core/components/InstallButton'; -import { getFakeI18nInst } from 'tests/client/helpers'; +import { getFakeI18nInst } from '../../helpers'; export const fakeAddon = { diff --git a/tests/client/amo/containers/TestApp.js b/tests/client/amo/containers/TestApp.js index 0a091813417..4f392424460 100644 --- a/tests/client/amo/containers/TestApp.js +++ b/tests/client/amo/containers/TestApp.js @@ -8,7 +8,7 @@ import { import App from 'amo/containers/App'; import I18nProvider from 'core/i18n/Provider'; -import { getFakeI18nInst } from 'tests/client/helpers'; +import { getFakeI18nInst } from '../../helpers'; describe('App', () => { diff --git a/tests/client/amo/containers/TestDetail.js b/tests/client/amo/containers/TestDetail.js index 5cc3eb1ed2b..aa3635559aa 100644 --- a/tests/client/amo/containers/TestDetail.js +++ b/tests/client/amo/containers/TestDetail.js @@ -7,10 +7,10 @@ import { import { Provider } from 'react-redux'; import createStore from 'amo/store'; -import { getFakeI18nInst } from 'tests/client/helpers'; import DetailPage from 'amo/containers/DetailPage'; import I18nProvider from 'core/i18n/Provider'; +import { getFakeI18nInst } from '../../helpers'; import { fakeAddon } from '../components/TestAddonDetail'; function render( diff --git a/tests/client/core/api/test_api.js b/tests/client/core/api/test_api.js index aa97f8be948..49cf4ff99de 100644 --- a/tests/client/core/api/test_api.js +++ b/tests/client/core/api/test_api.js @@ -1,5 +1,6 @@ import * as api from 'core/api'; -import { unexpectedSuccess } from 'tests/client/helpers'; + +import { unexpectedSuccess } from '../../helpers'; describe('api', () => { let mockWindow; diff --git a/tests/client/core/client/test_logger.js b/tests/client/core/client/test_logger.js index 00fc08de1c4..fbf0251b030 100644 --- a/tests/client/core/client/test_logger.js +++ b/tests/client/core/client/test_logger.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line import/named import { bindConsoleMethod } from 'core/logger'; describe('logger.bindConsoleMethod()', () => { diff --git a/tests/client/core/components/TestInstallButton.js b/tests/client/core/components/TestInstallButton.js index fe1d41fefb8..a0bc09be0d9 100644 --- a/tests/client/core/components/TestInstallButton.js +++ b/tests/client/core/components/TestInstallButton.js @@ -3,7 +3,7 @@ import { Simulate, renderIntoDocument } from 'react-addons-test-utils'; import { findDOMNode } from 'react-dom'; import { - InstallButton, + InstallButtonBase, } from 'core/components/InstallButton'; import { DISABLED, @@ -18,7 +18,8 @@ import { UNINSTALLING, UNKNOWN, } from 'core/constants'; -import { getFakeI18nInst } from 'tests/client/helpers'; + +import { getFakeI18nInst } from '../../helpers'; describe('', () => { @@ -36,7 +37,7 @@ describe('', () => { }; return renderIntoDocument( - ); + ); } it('should be disabled if isDisabled status is UNKNOWN', () => { diff --git a/tests/client/core/components/TestNotFound.js b/tests/client/core/components/TestNotFound.js index 3b04a6efbdd..66c81990fde 100644 --- a/tests/client/core/components/TestNotFound.js +++ b/tests/client/core/components/TestNotFound.js @@ -1,5 +1,6 @@ import React from 'react'; import { renderIntoDocument } from 'react-addons-test-utils'; + import NotFound from 'core/components/NotFound'; describe('', () => { diff --git a/tests/client/core/components/TestPaginate.js b/tests/client/core/components/TestPaginate.js index 973dc88aff3..e3a234f074d 100644 --- a/tests/client/core/components/TestPaginate.js +++ b/tests/client/core/components/TestPaginate.js @@ -2,6 +2,7 @@ import React from 'react'; import { render } from 'react-dom'; import { renderIntoDocument } from 'react-addons-test-utils'; import { Route, Router, createMemoryHistory } from 'react-router'; + import Paginate from 'core/components/Paginate'; describe('', () => { diff --git a/tests/client/core/containers/TestHandleLogin.js b/tests/client/core/containers/TestHandleLogin.js index cbf8bc501e7..4135cf805d8 100644 --- a/tests/client/core/containers/TestHandleLogin.js +++ b/tests/client/core/containers/TestHandleLogin.js @@ -4,6 +4,7 @@ import { findDOMNode } from 'react-dom'; import { Provider } from 'react-redux'; import cookie from 'react-cookie'; import { createStore } from 'redux'; + import HandleLogin, { mapDispatchToProps } from 'core/containers/HandleLogin'; import * as api from 'core/api'; diff --git a/tests/client/core/containers/TestLoginRequired.js b/tests/client/core/containers/TestLoginRequired.js index e44f86c6a75..88ec446d240 100644 --- a/tests/client/core/containers/TestLoginRequired.js +++ b/tests/client/core/containers/TestLoginRequired.js @@ -1,9 +1,11 @@ import React from 'react'; -import { shallowRender } from 'tests/client/helpers'; -import { mapStateToProps, LoginRequired } from 'core/containers/LoginRequired'; +import { mapStateToProps, LoginRequiredBase } + from 'core/containers/LoginRequired'; import LoginPage from 'core/components/LoginPage'; +import { shallowRender } from '../../helpers'; + describe('', () => { class MyComponent extends React.Component { render() { @@ -13,18 +15,18 @@ describe('', () => { it('renders when unauthenticated', () => { const root = shallowRender( - + - + ); assert.equal(root.type, LoginPage); }); it('renders the children when authenticated', () => { const root = shallowRender( - + - + ); assert.equal(root.type, MyComponent); }); diff --git a/tests/client/core/containers/TestServerHtml.js b/tests/client/core/containers/TestServerHtml.js index ccf14e40c82..799ec493846 100644 --- a/tests/client/core/containers/TestServerHtml.js +++ b/tests/client/core/containers/TestServerHtml.js @@ -1,7 +1,7 @@ import Helmet from 'react-helmet'; import React, { PropTypes } from 'react'; - import { findRenderedDOMComponentWithTag, renderIntoDocument } from 'react-addons-test-utils'; + import ServerHtml from 'core/containers/ServerHtml'; describe('', () => { diff --git a/tests/client/core/i18n/TestI18nProvider.js b/tests/client/core/i18n/TestI18nProvider.js index c3af54ca224..ecfccc1787d 100644 --- a/tests/client/core/i18n/TestI18nProvider.js +++ b/tests/client/core/i18n/TestI18nProvider.js @@ -1,14 +1,15 @@ /* eslint-disable react/no-multi-comp */ import React, { Component, PropTypes } from 'react'; - -import I18nProvider from 'core/i18n/Provider'; -import translate from 'core/i18n/translate'; -import { getFakeI18nInst } from 'tests/client/helpers'; import { renderIntoDocument, findRenderedComponentWithType, } from 'react-addons-test-utils'; +import I18nProvider from 'core/i18n/Provider'; +import translate from 'core/i18n/translate'; + +import { getFakeI18nInst } from '../../helpers'; + class OuterComponent extends Component { static propTypes = { diff --git a/tests/client/core/i18n/test_utils.js b/tests/client/core/i18n/test_utils.js index 18e2cff2789..4b971c8436a 100644 --- a/tests/client/core/i18n/test_utils.js +++ b/tests/client/core/i18n/test_utils.js @@ -1,6 +1,7 @@ -import * as utils from 'core/i18n/utils'; import config from 'config'; +import * as utils from 'core/i18n/utils'; + const defaultLang = config.get('defaultLang'); diff --git a/tests/client/core/test_utils.js b/tests/client/core/test_utils.js index ae0ca20190f..837a8c5b711 100644 --- a/tests/client/core/test_utils.js +++ b/tests/client/core/test_utils.js @@ -11,7 +11,7 @@ import { nl2br, } from 'core/utils'; -import { unexpectedSuccess } from 'tests/client/helpers'; +import { unexpectedSuccess } from '../helpers'; describe('camelCaseProps', () => { const input = { diff --git a/tests/client/disco/TestAddonManager.js b/tests/client/disco/TestAddonManager.js index 689329c11ab..2b45ce3596a 100644 --- a/tests/client/disco/TestAddonManager.js +++ b/tests/client/disco/TestAddonManager.js @@ -1,11 +1,12 @@ import * as addonManager from 'disco/addonManager'; -import { unexpectedSuccess } from 'tests/client/helpers'; import { installEventList } from 'core/constants'; import { globalEventStatusMap, SET_ENABLE_NOT_AVAILABLE, } from 'disco/constants'; +import { unexpectedSuccess } from '../helpers'; + describe('addonManager', () => { let fakeAddon; diff --git a/tests/client/disco/components/TestAddon.js b/tests/client/disco/components/TestAddon.js index b33e9ee82c0..5efe19a0514 100644 --- a/tests/client/disco/components/TestAddon.js +++ b/tests/client/disco/components/TestAddon.js @@ -6,8 +6,11 @@ import { } from 'react-addons-test-utils'; import { findDOMNode } from 'react-dom'; import config from 'config'; + +import I18nProvider from 'core/i18n/Provider'; +import translate from 'core/i18n/translate'; import { - Addon, + AddonBase, makeProgressHandler, mapDispatchToProps, mapStateToProps, @@ -40,9 +43,8 @@ import { SHOW_INFO, UNINSTALL_CATEGORY, } from 'disco/constants'; -import { getFakeAddonManagerWrapper, getFakeI18nInst } from 'tests/client/helpers'; -import I18nProvider from 'core/i18n/Provider'; -import translate from 'core/i18n/translate'; + +import { getFakeAddonManagerWrapper, getFakeI18nInst } from '../../helpers'; const result = { id: 'test-id', @@ -53,7 +55,7 @@ const result = { }; function renderAddon({ setCurrentStatus = sinon.stub(), ...props }) { - const MyAddon = translate({ withRef: true })(Addon); + const MyAddon = translate({ withRef: true })(AddonBase); return findRenderedComponentWithType(renderIntoDocument( diff --git a/tests/client/disco/components/TestInfoDialog.js b/tests/client/disco/components/TestInfoDialog.js index cbfa47d4915..061d5f545ca 100644 --- a/tests/client/disco/components/TestInfoDialog.js +++ b/tests/client/disco/components/TestInfoDialog.js @@ -2,10 +2,10 @@ import React from 'react'; import { Simulate, renderIntoDocument } from 'react-addons-test-utils'; import ReactDOM, { findDOMNode } from 'react-dom'; -import InfoDialog from 'disco/components/InfoDialog'; import I18nProvider from 'core/i18n/Provider'; +import InfoDialog from 'disco/components/InfoDialog'; -import { getFakeI18nInst } from 'tests/client/helpers'; +import { getFakeI18nInst } from '../../helpers'; let closeAction; diff --git a/tests/client/disco/containers/TestApp.js b/tests/client/disco/containers/TestApp.js index f1ba31beb56..dcd19faa186 100644 --- a/tests/client/disco/containers/TestApp.js +++ b/tests/client/disco/containers/TestApp.js @@ -5,10 +5,10 @@ import { renderIntoDocument, } from 'react-addons-test-utils'; -import App from 'disco/containers/App'; import I18nProvider from 'core/i18n/Provider'; +import App from 'disco/containers/App'; -import { getFakeI18nInst } from 'tests/client/helpers'; +import { getFakeI18nInst } from '../../helpers'; describe('App', () => { diff --git a/tests/client/disco/containers/TestDiscoPane.js b/tests/client/disco/containers/TestDiscoPane.js index 727d09955ef..2b9451e6b18 100644 --- a/tests/client/disco/containers/TestDiscoPane.js +++ b/tests/client/disco/containers/TestDiscoPane.js @@ -2,26 +2,28 @@ import React from 'react'; import { Simulate, renderIntoDocument } from 'react-addons-test-utils'; import { findDOMNode } from 'react-dom'; import { Provider } from 'react-redux'; -import { discoResults } from 'disco/actions'; -import * as discoApi from 'disco/api'; -import createStore from 'disco/store'; + +import { loadEntities } from 'core/actions'; +import I18nProvider from 'core/i18n/Provider'; import { EXTENSION_TYPE, INSTALL_STATE, } from 'core/constants'; +import { discoResults } from 'disco/actions'; +import * as discoApi from 'disco/api'; +import createStore from 'disco/store'; import { NAVIGATION_CATEGORY, VIDEO_CATEGORY, globalEvents, } from 'disco/constants'; import * as helpers from 'disco/containers/DiscoPane'; -import { getFakeI18nInst, MockedSubComponent } from 'tests/client/helpers'; -import { loadEntities } from 'core/actions'; -import I18nProvider from 'core/i18n/Provider'; + +import { getFakeI18nInst, MockedSubComponent } from '../../helpers'; // Use DiscoPane that isn't wrapped in asyncConnect. -const { DiscoPane } = helpers; +const { DiscoPaneBase } = helpers; describe('AddonPage', () => { @@ -37,7 +39,7 @@ describe('AddonPage', () => { return findDOMNode(renderIntoDocument( - diff --git a/tests/client/helpers.js b/tests/client/helpers.js index 6077734243e..b9a7a47f624 100644 --- a/tests/client/helpers.js +++ b/tests/client/helpers.js @@ -1,7 +1,8 @@ +import { sprintf } from 'jed'; import React from 'react'; import { createRenderer } from 'react-addons-test-utils'; + import { EXTENSION_TYPE } from 'core/constants'; -import { sprintf } from 'jed'; export function shallowRender(stuff) { const renderer = createRenderer(); diff --git a/tests/client/search/components/TestJsonData.js b/tests/client/search/components/TestJsonData.js index 31f5f4d01c9..7c25f0ff32e 100644 --- a/tests/client/search/components/TestJsonData.js +++ b/tests/client/search/components/TestJsonData.js @@ -1,6 +1,7 @@ import React from 'react'; import { renderIntoDocument, Simulate } from 'react-addons-test-utils'; import { findDOMNode } from 'react-dom'; + import JsonData from 'search/components/JsonData'; describe('', () => { diff --git a/tests/client/search/components/TestSearchForm.js b/tests/client/search/components/TestSearchForm.js index e0456f26e7e..c875ec4d908 100644 --- a/tests/client/search/components/TestSearchForm.js +++ b/tests/client/search/components/TestSearchForm.js @@ -3,7 +3,8 @@ import { Simulate, renderIntoDocument } from 'react-addons-test-utils'; import * as actions from 'core/actions'; import * as coreApi from 'core/api'; -import { SearchForm, mapDispatchToProps, mapStateToProps } from 'search/components/SearchForm'; +import { SearchFormBase, mapDispatchToProps, mapStateToProps } + from 'search/components/SearchForm'; const wait = (time) => new Promise((resolve) => setTimeout(resolve, time)); @@ -26,7 +27,10 @@ describe('', () => { } render() { - return ; + return (); } } diff --git a/tests/client/search/components/TestSearchPage.js b/tests/client/search/components/TestSearchPage.js index bcf789cacc3..92cff3ebcb9 100644 --- a/tests/client/search/components/TestSearchPage.js +++ b/tests/client/search/components/TestSearchPage.js @@ -4,7 +4,8 @@ import SearchPage from 'search/components/SearchPage'; import SearchResults from 'search/components/SearchResults'; import SearchForm from 'search/components/SearchForm'; import Paginate from 'core/components/Paginate'; -import { findAllByTag, findByTag, shallowRender } from 'tests/client/helpers'; + +import { findAllByTag, findByTag, shallowRender } from '../../helpers'; describe('', () => { let props; diff --git a/tests/client/search/components/TestSearchResult.js b/tests/client/search/components/TestSearchResult.js index ab64b9b4fd9..d0fdfabbe56 100644 --- a/tests/client/search/components/TestSearchResult.js +++ b/tests/client/search/components/TestSearchResult.js @@ -1,5 +1,6 @@ import React from 'react'; import { renderIntoDocument } from 'react-addons-test-utils'; + import SearchResult from 'search/components/SearchResult'; describe('', () => { diff --git a/tests/client/search/containers/TestAddonPage.js b/tests/client/search/containers/TestAddonPage.js index fac1f5609ba..94bf476ee49 100644 --- a/tests/client/search/containers/TestAddonPage.js +++ b/tests/client/search/containers/TestAddonPage.js @@ -2,6 +2,7 @@ import React from 'react'; import { renderIntoDocument } from 'react-addons-test-utils'; import { findDOMNode } from 'react-dom'; import { Provider } from 'react-redux'; + import AddonPage from 'search/containers/AddonPage'; import createStore from 'search/store'; diff --git a/tests/client/search/containers/TestApp.js b/tests/client/search/containers/TestApp.js index 8371999a9bb..a0faaa8f087 100644 --- a/tests/client/search/containers/TestApp.js +++ b/tests/client/search/containers/TestApp.js @@ -1,7 +1,8 @@ import React from 'react'; import App from 'search/containers/App'; -import { shallowRender } from 'tests/client/helpers'; + +import { shallowRender } from '../../helpers'; describe('App', () => { it('renders its children', () => { diff --git a/tests/client/search/TestUserPage.js b/tests/client/search/containers/TestUserPage.js similarity index 93% rename from tests/client/search/TestUserPage.js rename to tests/client/search/containers/TestUserPage.js index 3d370cea805..e5091fe09d2 100644 --- a/tests/client/search/TestUserPage.js +++ b/tests/client/search/containers/TestUserPage.js @@ -4,12 +4,13 @@ import { findDOMNode } from 'react-dom'; import { loadEntities, setCurrentUser } from 'core/actions'; import * as api from 'core/api'; -import { UserPage, mapStateToProps, loadProfileIfNeeded } from 'search/containers/UserPage'; +import { UserPageBase, mapStateToProps, loadProfileIfNeeded } + from 'search/containers/UserPage'; describe('', () => { it('renders the username and email', () => { const root = findDOMNode(renderIntoDocument( - )); + )); assert.deepEqual( Array.from(root.querySelectorAll('li')).map((li) => li.textContent), ['username: my-username', 'email: me@example.com']); diff --git a/tests/server/TestConfig.js b/tests/server/TestConfig.js index b22a1ef67a5..11f90f9ee51 100644 --- a/tests/server/TestConfig.js +++ b/tests/server/TestConfig.js @@ -1,7 +1,8 @@ -import { getClientConfig } from 'core/utils'; import { assert } from 'chai'; -import requireUncached from 'require-uncached'; import config from 'config'; +import requireUncached from 'require-uncached'; + +import { getClientConfig } from 'core/utils'; const appsList = config.get('validAppNames'); diff --git a/tests/server/TestLocalesConfig.js b/tests/server/TestLocalesConfig.js index 1614a533db9..43f56373fe0 100644 --- a/tests/server/TestLocalesConfig.js +++ b/tests/server/TestLocalesConfig.js @@ -1,10 +1,12 @@ import fs from 'fs'; -import { assert } from 'chai'; import path from 'path'; + +import { assert } from 'chai'; import config from 'config'; -import { langToLocale, localeToLang } from 'core/i18n/utils'; import glob from 'glob'; +import { langToLocale, localeToLang } from 'core/i18n/utils'; + const langs = config.get('langs'); const basePath = config.get('basePath'); diff --git a/tests/server/amo/TestViews.js b/tests/server/amo/TestViews.js index b0059e49543..0b5fc42553d 100644 --- a/tests/server/amo/TestViews.js +++ b/tests/server/amo/TestViews.js @@ -1,10 +1,9 @@ /* eslint-disable no-loop-func */ - -import request from 'supertest-as-promised'; import { assert } from 'chai'; +import Policy from 'csp-parse'; +import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; -import Policy from 'csp-parse'; import { checkSRI } from '../helpers'; diff --git a/tests/server/disco/TestViews.js b/tests/server/disco/TestViews.js index b53078b695a..0574563996c 100644 --- a/tests/server/disco/TestViews.js +++ b/tests/server/disco/TestViews.js @@ -1,10 +1,9 @@ /* eslint-disable no-loop-func */ - -import request from 'supertest-as-promised'; import { assert } from 'chai'; +import Policy from 'csp-parse'; +import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; -import Policy from 'csp-parse'; import { checkSRI } from '../helpers'; diff --git a/tests/server/search/TestViews.js b/tests/server/search/TestViews.js index fcf2a599622..87686820941 100644 --- a/tests/server/search/TestViews.js +++ b/tests/server/search/TestViews.js @@ -1,10 +1,9 @@ /* eslint-disable no-loop-func */ - -import request from 'supertest-as-promised'; import { assert } from 'chai'; +import Policy from 'csp-parse'; +import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; -import Policy from 'csp-parse'; import { checkSRI } from '../helpers'; diff --git a/webpack.dev.config.babel.js b/webpack.dev.config.babel.js index 03aac633994..9203edb012a 100644 --- a/webpack.dev.config.babel.js +++ b/webpack.dev.config.babel.js @@ -1,15 +1,17 @@ -/* eslint-disable max-len, no-console */ +/* eslint-disable max-len, no-console, import/no-extraneous-dependencies */ import fs from 'fs'; import path from 'path'; + +import config from 'config'; import webpack from 'webpack'; +import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin'; import { getClientConfig } from 'core/utils'; -import config from 'config'; import webpackConfig from './webpack.prod.config.babel'; -import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin'; -import webpackIsomorphicToolsConfig from './webpack-isomorphic-tools-config'; +import webpackIsomorphicToolsConfig + from './src/core/server/webpack-isomorphic-tools-config'; const clientConfig = getClientConfig(config); const localDevelopment = config.util.getEnv('NODE_ENV') === 'development'; diff --git a/webpack.l10n.config.babel.js b/webpack.l10n.config.babel.js index 8bc3f00981a..b25de7204b4 100644 --- a/webpack.l10n.config.babel.js +++ b/webpack.l10n.config.babel.js @@ -1,7 +1,8 @@ -/* eslint-disable no-console */ +/* eslint-disable no-console, import/no-extraneous-dependencies */ import fs from 'fs'; -import config from 'config'; + import chalk from 'chalk'; +import config from 'config'; import webpackConfig from './webpack.prod.config.babel'; diff --git a/webpack.prod.config.babel.js b/webpack.prod.config.babel.js index 7168af2baf2..197ab3558bd 100644 --- a/webpack.prod.config.babel.js +++ b/webpack.prod.config.babel.js @@ -1,18 +1,18 @@ -/* eslint-disable max-len */ - -import autoprefixer from 'autoprefixer'; +/* eslint-disable max-len, import/no-extraneous-dependencies */ import path from 'path'; +import autoprefixer from 'autoprefixer'; import config from 'config'; import ExtractTextPlugin from 'extract-text-webpack-plugin'; -import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin'; -import webpackIsomorphicToolsConfig from './webpack-isomorphic-tools-config'; -import webpack from 'webpack'; - import SriStatsPlugin from 'sri-stats-webpack-plugin'; +import webpack from 'webpack'; +import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin'; import { getClientConfig } from 'core/utils'; +import webpackIsomorphicToolsConfig + from './src/core/server/webpack-isomorphic-tools-config'; + const clientConfig = getClientConfig(config); const appName = config.get('appName'); From 1d2e1671498ff6d909692bd26b8071c36ec29cfa Mon Sep 17 00:00:00 2001 From: Kumar McMillan Date: Fri, 19 Aug 2016 16:45:31 -0500 Subject: [PATCH 2/3] use relative imports in tests again --- tests/.eslintrc | 8 ++++++++ tests/client/amo/components/TestAddonDetail.js | 3 +-- tests/client/amo/containers/TestApp.js | 3 +-- tests/client/amo/containers/TestDetail.js | 2 +- tests/client/core/api/test_api.js | 3 +-- tests/client/core/components/TestInstallButton.js | 3 +-- tests/client/core/containers/TestLoginRequired.js | 3 +-- tests/client/core/i18n/TestI18nProvider.js | 3 +-- tests/client/core/test_utils.js | 3 +-- tests/client/disco/TestAddonManager.js | 3 +-- tests/client/disco/components/TestAddon.js | 4 ++-- tests/client/disco/components/TestInfoDialog.js | 3 +-- tests/client/disco/containers/TestApp.js | 3 +-- tests/client/disco/containers/TestDiscoPane.js | 3 +-- tests/client/search/components/TestSearchPage.js | 3 +-- tests/client/search/containers/TestApp.js | 3 +-- tests/server/amo/TestViews.js | 3 +-- tests/server/disco/TestViews.js | 3 +-- tests/server/search/TestViews.js | 3 +-- 19 files changed, 27 insertions(+), 35 deletions(-) diff --git a/tests/.eslintrc b/tests/.eslintrc index 0b3f7a7b4e3..a2fff35f95e 100644 --- a/tests/.eslintrc +++ b/tests/.eslintrc @@ -4,5 +4,13 @@ // Allow dev-dependencies in this directory. "devDependencies": true }], + }, + "settings": { + "import/resolver": { + "node": { + // This adds ./src and `cwd` for relative imports. + "moduleDirectory": ["node_modules", "src", ""] + } + } } } diff --git a/tests/client/amo/components/TestAddonDetail.js b/tests/client/amo/components/TestAddonDetail.js index 91ebe0accfb..e8bb0e558de 100644 --- a/tests/client/amo/components/TestAddonDetail.js +++ b/tests/client/amo/components/TestAddonDetail.js @@ -9,8 +9,7 @@ import AddonDetail, { allowedDescriptionTags } from 'amo/components/AddonDetail'; import I18nProvider from 'core/i18n/Provider'; import InstallButton from 'core/components/InstallButton'; - -import { getFakeI18nInst } from '../../helpers'; +import { getFakeI18nInst } from 'tests/client/helpers'; export const fakeAddon = { diff --git a/tests/client/amo/containers/TestApp.js b/tests/client/amo/containers/TestApp.js index 4f392424460..a2c57d267f8 100644 --- a/tests/client/amo/containers/TestApp.js +++ b/tests/client/amo/containers/TestApp.js @@ -7,8 +7,7 @@ import { import App from 'amo/containers/App'; import I18nProvider from 'core/i18n/Provider'; - -import { getFakeI18nInst } from '../../helpers'; +import { getFakeI18nInst } from 'tests/client/helpers'; describe('App', () => { diff --git a/tests/client/amo/containers/TestDetail.js b/tests/client/amo/containers/TestDetail.js index aa3635559aa..ca4535f0942 100644 --- a/tests/client/amo/containers/TestDetail.js +++ b/tests/client/amo/containers/TestDetail.js @@ -9,8 +9,8 @@ import { Provider } from 'react-redux'; import createStore from 'amo/store'; import DetailPage from 'amo/containers/DetailPage'; import I18nProvider from 'core/i18n/Provider'; +import { getFakeI18nInst } from 'tests/client/helpers'; -import { getFakeI18nInst } from '../../helpers'; import { fakeAddon } from '../components/TestAddonDetail'; function render( diff --git a/tests/client/core/api/test_api.js b/tests/client/core/api/test_api.js index 49cf4ff99de..aa97f8be948 100644 --- a/tests/client/core/api/test_api.js +++ b/tests/client/core/api/test_api.js @@ -1,6 +1,5 @@ import * as api from 'core/api'; - -import { unexpectedSuccess } from '../../helpers'; +import { unexpectedSuccess } from 'tests/client/helpers'; describe('api', () => { let mockWindow; diff --git a/tests/client/core/components/TestInstallButton.js b/tests/client/core/components/TestInstallButton.js index a0bc09be0d9..5c78d3e9fe4 100644 --- a/tests/client/core/components/TestInstallButton.js +++ b/tests/client/core/components/TestInstallButton.js @@ -18,8 +18,7 @@ import { UNINSTALLING, UNKNOWN, } from 'core/constants'; - -import { getFakeI18nInst } from '../../helpers'; +import { getFakeI18nInst } from 'tests/client/helpers'; describe('', () => { diff --git a/tests/client/core/containers/TestLoginRequired.js b/tests/client/core/containers/TestLoginRequired.js index 88ec446d240..77496291594 100644 --- a/tests/client/core/containers/TestLoginRequired.js +++ b/tests/client/core/containers/TestLoginRequired.js @@ -3,8 +3,7 @@ import React from 'react'; import { mapStateToProps, LoginRequiredBase } from 'core/containers/LoginRequired'; import LoginPage from 'core/components/LoginPage'; - -import { shallowRender } from '../../helpers'; +import { shallowRender } from 'tests/client/helpers'; describe('', () => { class MyComponent extends React.Component { diff --git a/tests/client/core/i18n/TestI18nProvider.js b/tests/client/core/i18n/TestI18nProvider.js index ecfccc1787d..5ddf2c1e8ab 100644 --- a/tests/client/core/i18n/TestI18nProvider.js +++ b/tests/client/core/i18n/TestI18nProvider.js @@ -7,8 +7,7 @@ import { import I18nProvider from 'core/i18n/Provider'; import translate from 'core/i18n/translate'; - -import { getFakeI18nInst } from '../../helpers'; +import { getFakeI18nInst } from 'tests/client/helpers'; class OuterComponent extends Component { diff --git a/tests/client/core/test_utils.js b/tests/client/core/test_utils.js index 837a8c5b711..bc0eb2f1633 100644 --- a/tests/client/core/test_utils.js +++ b/tests/client/core/test_utils.js @@ -10,8 +10,7 @@ import { loadAddonIfNeeded, nl2br, } from 'core/utils'; - -import { unexpectedSuccess } from '../helpers'; +import { unexpectedSuccess } from 'tests/client/helpers'; describe('camelCaseProps', () => { const input = { diff --git a/tests/client/disco/TestAddonManager.js b/tests/client/disco/TestAddonManager.js index 2b45ce3596a..7548fc9fee9 100644 --- a/tests/client/disco/TestAddonManager.js +++ b/tests/client/disco/TestAddonManager.js @@ -4,8 +4,7 @@ import { globalEventStatusMap, SET_ENABLE_NOT_AVAILABLE, } from 'disco/constants'; - -import { unexpectedSuccess } from '../helpers'; +import { unexpectedSuccess } from 'tests/client/helpers'; describe('addonManager', () => { diff --git a/tests/client/disco/components/TestAddon.js b/tests/client/disco/components/TestAddon.js index 5efe19a0514..edccdd950aa 100644 --- a/tests/client/disco/components/TestAddon.js +++ b/tests/client/disco/components/TestAddon.js @@ -43,8 +43,8 @@ import { SHOW_INFO, UNINSTALL_CATEGORY, } from 'disco/constants'; - -import { getFakeAddonManagerWrapper, getFakeI18nInst } from '../../helpers'; +import { getFakeAddonManagerWrapper, getFakeI18nInst } + from 'tests/client/helpers'; const result = { id: 'test-id', diff --git a/tests/client/disco/components/TestInfoDialog.js b/tests/client/disco/components/TestInfoDialog.js index 061d5f545ca..f963bd2dc93 100644 --- a/tests/client/disco/components/TestInfoDialog.js +++ b/tests/client/disco/components/TestInfoDialog.js @@ -4,8 +4,7 @@ import ReactDOM, { findDOMNode } from 'react-dom'; import I18nProvider from 'core/i18n/Provider'; import InfoDialog from 'disco/components/InfoDialog'; - -import { getFakeI18nInst } from '../../helpers'; +import { getFakeI18nInst } from 'tests/client/helpers'; let closeAction; diff --git a/tests/client/disco/containers/TestApp.js b/tests/client/disco/containers/TestApp.js index dcd19faa186..c304e0c84b7 100644 --- a/tests/client/disco/containers/TestApp.js +++ b/tests/client/disco/containers/TestApp.js @@ -7,8 +7,7 @@ import { import I18nProvider from 'core/i18n/Provider'; import App from 'disco/containers/App'; - -import { getFakeI18nInst } from '../../helpers'; +import { getFakeI18nInst } from 'tests/client/helpers'; describe('App', () => { diff --git a/tests/client/disco/containers/TestDiscoPane.js b/tests/client/disco/containers/TestDiscoPane.js index 2b9451e6b18..28308a6ae8a 100644 --- a/tests/client/disco/containers/TestDiscoPane.js +++ b/tests/client/disco/containers/TestDiscoPane.js @@ -18,8 +18,7 @@ import { globalEvents, } from 'disco/constants'; import * as helpers from 'disco/containers/DiscoPane'; - -import { getFakeI18nInst, MockedSubComponent } from '../../helpers'; +import { getFakeI18nInst, MockedSubComponent } from 'tests/client/helpers'; // Use DiscoPane that isn't wrapped in asyncConnect. diff --git a/tests/client/search/components/TestSearchPage.js b/tests/client/search/components/TestSearchPage.js index 92cff3ebcb9..bcf789cacc3 100644 --- a/tests/client/search/components/TestSearchPage.js +++ b/tests/client/search/components/TestSearchPage.js @@ -4,8 +4,7 @@ import SearchPage from 'search/components/SearchPage'; import SearchResults from 'search/components/SearchResults'; import SearchForm from 'search/components/SearchForm'; import Paginate from 'core/components/Paginate'; - -import { findAllByTag, findByTag, shallowRender } from '../../helpers'; +import { findAllByTag, findByTag, shallowRender } from 'tests/client/helpers'; describe('', () => { let props; diff --git a/tests/client/search/containers/TestApp.js b/tests/client/search/containers/TestApp.js index a0faaa8f087..8371999a9bb 100644 --- a/tests/client/search/containers/TestApp.js +++ b/tests/client/search/containers/TestApp.js @@ -1,8 +1,7 @@ import React from 'react'; import App from 'search/containers/App'; - -import { shallowRender } from '../../helpers'; +import { shallowRender } from 'tests/client/helpers'; describe('App', () => { it('renders its children', () => { diff --git a/tests/server/amo/TestViews.js b/tests/server/amo/TestViews.js index 0b5fc42553d..93a5acf9e3d 100644 --- a/tests/server/amo/TestViews.js +++ b/tests/server/amo/TestViews.js @@ -4,8 +4,7 @@ import Policy from 'csp-parse'; import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; - -import { checkSRI } from '../helpers'; +import { checkSRI } from 'tests/server/helpers'; const defaultURL = '/en-US/firefox/'; diff --git a/tests/server/disco/TestViews.js b/tests/server/disco/TestViews.js index 0574563996c..df16f650ebd 100644 --- a/tests/server/disco/TestViews.js +++ b/tests/server/disco/TestViews.js @@ -4,8 +4,7 @@ import Policy from 'csp-parse'; import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; - -import { checkSRI } from '../helpers'; +import { checkSRI } from 'tests/server/helpers'; const defaultURL = '/en-US/firefox/discovery/pane/48.0/Darwin/normal'; diff --git a/tests/server/search/TestViews.js b/tests/server/search/TestViews.js index 87686820941..0466bf8fe88 100644 --- a/tests/server/search/TestViews.js +++ b/tests/server/search/TestViews.js @@ -4,8 +4,7 @@ import Policy from 'csp-parse'; import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; - -import { checkSRI } from '../helpers'; +import { checkSRI } from 'tests/server/helpers'; describe('Search App GET requests', () => { let app; From 798bf1dab027451f4f1e98c6f9482a31c9f1e16b Mon Sep 17 00:00:00 2001 From: Kumar McMillan Date: Fri, 19 Aug 2016 17:03:50 -0500 Subject: [PATCH 3/3] put back some relative test imports --- tests/server/amo/TestViews.js | 3 ++- tests/server/disco/TestViews.js | 3 ++- tests/server/search/TestViews.js | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/server/amo/TestViews.js b/tests/server/amo/TestViews.js index 93a5acf9e3d..0b5fc42553d 100644 --- a/tests/server/amo/TestViews.js +++ b/tests/server/amo/TestViews.js @@ -4,7 +4,8 @@ import Policy from 'csp-parse'; import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; -import { checkSRI } from 'tests/server/helpers'; + +import { checkSRI } from '../helpers'; const defaultURL = '/en-US/firefox/'; diff --git a/tests/server/disco/TestViews.js b/tests/server/disco/TestViews.js index df16f650ebd..0574563996c 100644 --- a/tests/server/disco/TestViews.js +++ b/tests/server/disco/TestViews.js @@ -4,7 +4,8 @@ import Policy from 'csp-parse'; import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; -import { checkSRI } from 'tests/server/helpers'; + +import { checkSRI } from '../helpers'; const defaultURL = '/en-US/firefox/discovery/pane/48.0/Darwin/normal'; diff --git a/tests/server/search/TestViews.js b/tests/server/search/TestViews.js index 0466bf8fe88..87686820941 100644 --- a/tests/server/search/TestViews.js +++ b/tests/server/search/TestViews.js @@ -4,7 +4,8 @@ import Policy from 'csp-parse'; import request from 'supertest-as-promised'; import { runServer } from 'core/server/base'; -import { checkSRI } from 'tests/server/helpers'; + +import { checkSRI } from '../helpers'; describe('Search App GET requests', () => { let app;