Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1505758 - Fix/enable several more ESLint rules #4245

Merged
merged 13 commits into from Nov 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 0 additions & 13 deletions .eslintrc.js
Expand Up @@ -17,7 +17,6 @@ module.exports = {
'class-methods-use-this': 'off',
'consistent-return': 'off',
'default-case': 'off',
'func-names': 'off',
'function-paren-newline': 'off',
'implicit-arrow-linebreak': 'off',
// Indentation is disabled pending a switch from 4 to 2 space for JS.
Expand All @@ -31,26 +30,15 @@ module.exports = {
'max-len': 'off',
'no-alert': 'off',
'no-continue': 'off',
'no-else-return': 'off',
'no-mixed-operators': 'off',
'no-nested-ternary': 'off',
'no-param-reassign': 'off',
'no-plusplus': 'off',
'no-prototype-builtins': 'off',
'no-restricted-globals': 'off',
'no-restricted-syntax': 'off',
'no-shadow': 'off',
'no-underscore-dangle': 'off',
'no-useless-escape': 'off',
'object-curly-newline': 'off',
'object-shorthand': 'off',
'operator-linebreak': 'off',
'padded-blocks': 'off',
'prefer-arrow-callback': 'off',
'prefer-destructuring': 'off',
'prefer-promise-reject-errors': 'off',
'prefer-template': 'off',
radix: 'off',
'react/button-has-type': 'off',
'react/default-props-match-prop-types': 'off',
'react/destructuring-assignment': 'off',
Expand All @@ -59,6 +47,5 @@ module.exports = {
'react/jsx-one-expression-per-line': 'off',
'react/jsx-wrap-multilines': 'off',
'react/no-access-state-in-setstate': 'off',
'react/no-multi-comp': 'off',
},
};
16 changes: 8 additions & 8 deletions tests/ui/unit/models/filter.tests.js
@@ -1,16 +1,16 @@
import FilterModel from '../../../../ui/models/filter';

describe('FilterModel', () => {
const oldHash = location.hash;
const oldHash = window.location.hash;

afterEach(() => {
location.hash = oldHash;
window.location.hash = oldHash;
});

describe('parsing an old url', () => {

it('should parse the repo with defaults', () => {
location.hash = '?repo=mozilla-inbound';
window.location.hash = '?repo=mozilla-inbound';
const urlParams = FilterModel.getUrlParamsWithDefaults();

expect(urlParams).toEqual({
Expand All @@ -22,7 +22,7 @@ describe('FilterModel', () => {
});

it('should parse resultStatus params', () => {
location.hash = '?repo=mozilla-inbound&filter-resultStatus=testfailed&' +
window.location.hash = '?repo=mozilla-inbound&filter-resultStatus=testfailed&' +
'filter-resultStatus=busted&filter-resultStatus=exception&' +
'filter-resultStatus=success&filter-resultStatus=retry' +
'&filter-resultStatus=runnable';
Expand All @@ -37,7 +37,7 @@ describe('FilterModel', () => {
});

it('should parse searchStr params with tier and groupState intact', () => {
location.hash = '?repo=mozilla-inbound&filter-searchStr=Linux%20x64%20debug%20build-linux64-base-toolchains%2Fdebug%20(Bb)&filter-tier=1&group_state=expanded';
window.location.hash = '?repo=mozilla-inbound&filter-searchStr=Linux%20x64%20debug%20build-linux64-base-toolchains%2Fdebug%20(Bb)&filter-tier=1&group_state=expanded';
const urlParams = FilterModel.getUrlParamsWithDefaults();

expect(urlParams).toEqual({
Expand All @@ -51,7 +51,7 @@ describe('FilterModel', () => {
});

it('should parse job field filters', () => {
location.hash = '?repo=mozilla-inbound&filter-job_type_name=mochi';
window.location.hash = '?repo=mozilla-inbound&filter-job_type_name=mochi';
const urlParams = FilterModel.getUrlParamsWithDefaults();

expect(urlParams).toEqual({
Expand All @@ -66,7 +66,7 @@ describe('FilterModel', () => {

describe('parsing a new url', () => {
it('should parse resultStatus and searchStr', () => {
location.hash = '?repo=mozilla-inbound&resultStatus=testfailed,busted,exception,success,retry,runnable&' +
window.location.hash = '?repo=mozilla-inbound&resultStatus=testfailed,busted,exception,success,retry,runnable&' +
'searchStr=linux,x64,debug,build-linux64-base-toolchains%2Fdebug,(bb)';
const urlParams = FilterModel.getUrlParamsWithDefaults();

Expand All @@ -80,7 +80,7 @@ describe('FilterModel', () => {
});

it('should preserve the case in email addresses', () => {
location.hash = '?repo=mozilla-inbound&author=VYV03354@nifty.ne.jp';
window.location.hash = '?repo=mozilla-inbound&author=VYV03354@nifty.ne.jp';
const urlParams = FilterModel.getUrlParamsWithDefaults();

expect(urlParams).toEqual({
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/unit/react/bugfiler.tests.jsx
Expand Up @@ -88,7 +88,7 @@ describe('BugFiler', () => {
it('parses a crash suggestion', () => {
const summary = 'PROCESS-CRASH | browser/components/search/test/browser_searchbar_smallpanel_keyboard_navigation.js | application crashed [@ js::GCMarker::eagerlyMarkChildren]';
const bugFiler = getBugFilerForSummary(summary);
const parsedSummary = bugFiler.state().parsedSummary;
const { parsedSummary } = bugFiler.state();
expect(parsedSummary[0][0]).toEqual('browser/components/search/test/browser_searchbar_smallpanel_keyboard_navigation.js');
});

Expand Down Expand Up @@ -225,7 +225,7 @@ describe('BugFiler', () => {
/>,
);

const thisFailure = bugFiler.state().thisFailure;
const { thisFailure } = bugFiler.state();
expect(thisFailure).toBe('browser/extensions/pdfjs/test/browser_pdfjs_views.js | Test timed out -\n' +
'browser/extensions/pdfjs/test/browser_pdfjs_views.js | Found a tab after previous test timed out: about:blank -\n' +
'TEST-UNEXPECTED-PASS | flee | floo');
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/unit/react/revisions.tests.jsx
Expand Up @@ -187,9 +187,9 @@ describe('More revisions link component', () => {
});
});

describe('initials filter', function () {
describe('initials filter', () => {
const email = 'foo@bar.baz';
it('initializes a one-word name', function () {
it('initializes a one-word name', () => {
const name = 'Starscream';
const initials = mount(
<Initials
Expand All @@ -199,7 +199,7 @@ describe('initials filter', function () {
expect(initials.html()).toEqual('<span title="Starscream: foo@bar.baz"><span class="user-push-icon"><i class="fa fa-user-o" aria-hidden="true" data-job-clear-on-click="true"></i></span><div class="icon-superscript user-push-initials" data-job-clear-on-click="true">S</div></span>');
});

it('initializes a two-word name', function () {
it('initializes a two-word name', () => {
const name = 'Optimus Prime';
const initials = mount(
<Initials
Expand All @@ -210,7 +210,7 @@ describe('initials filter', function () {
expect(userPushInitials.html()).toEqual('<div class="icon-superscript user-push-initials" data-job-clear-on-click="true">OP</div>');
});

it('initializes a three-word name', function () {
it('initializes a three-word name', () => {
const name = 'Some Other Transformer';
const initials = mount(
<Initials
Expand Down
2 changes: 1 addition & 1 deletion ui/helpers/auth.js
Expand Up @@ -8,7 +8,7 @@ export const webAuth = new WebAuth({
domain: 'auth.mozilla.auth0.com',
responseType: 'id_token token',
audience: 'login.taskcluster.net',
redirectUri: `${location.protocol}//${location.host}${loginCallbackUrl}`,
redirectUri: `${window.location.protocol}//${window.location.host}${loginCallbackUrl}`,
scope: 'taskcluster-credentials openid profile email',
});

Expand Down
29 changes: 10 additions & 19 deletions ui/helpers/autoclassify.jsx
@@ -1,39 +1,30 @@
import countBy from 'lodash/countBy';
import React from 'react';

export const stringOverlap = function (str1, str2) {
export const stringOverlap = function stringOverlap(str1, str2) {
// Get a measure of the similarity of two strings by a simple process
// of tokenizing and then computing the ratio of the tokens in common to
// the total tokens

const tokens = [str1, str2]
.map(function (str) {
.map(str =>
// Replace paths like /foo/bar/baz.html with just the filename baz.html
return str.replace(/[^\s]+\/([^\s]+)\s/,
function (m, p1) {
return ' ' + p1 + ' ';
});
})
.map(function (str) {
str.replace(/[^\s]+\/([^\s]+)\s/, (m, p1) => ` ${p1} `),
)
.map(str =>
// Split into tokens on whitespace / , and |
return str.split(/[\s\/\,|]+/).filter(function (x) {
return x !== '';
});
});
str.split(/[\s/,|]+/).filter(x => x !== ''),
);

if (tokens[0].length === 0 || tokens[1].length === 0) {
return 0;
}

const tokenCounts = tokens.map(function (tokens) {
return countBy(tokens, function (x) {
return x;
});
});
const tokenCounts = tokens.map(tokens => countBy(tokens, x => x));

const overlap = Object.keys(tokenCounts[0])
.reduce(function (overlap, x) {
if (tokenCounts[1].hasOwnProperty(x)) {
.reduce((overlap, x) => {
if (Object.prototype.hasOwnProperty.call(tokenCounts[1], x)) {
overlap += 2 * Math.min(tokenCounts[0][x], tokenCounts[1][x]);
}
return overlap;
Expand Down
2 changes: 1 addition & 1 deletion ui/helpers/errorMessage.js
Expand Up @@ -21,7 +21,7 @@ export const formatModelError = function formatModelError(e, message) {
}

// If there is nothing in the server message use the HTTP response status.
const errorMessage = `${e.data && e.data.detail || e.status} ${e.statusText}`;
const errorMessage = `${(e.data && e.data.detail) || e.status} ${e.statusText}`;
return `${message}: ${errorMessage}`;

};
Expand Down
4 changes: 2 additions & 2 deletions ui/helpers/location.js
Expand Up @@ -2,7 +2,7 @@ import { thDefaultRepo } from './constants';
import { createQueryParams } from './url';

export const getQueryString = function getQueryString() {
return location.hash.split('?')[1];
return window.location.hash.split('?')[1];
};

export const getAllUrlParams = function getAllUrlParams() {
Expand All @@ -18,7 +18,7 @@ export const getRepo = function getRepo() {
};

export const setLocation = function setLocation(params, hashPrefix = '/jobs') {
location.hash = `#${hashPrefix}${createQueryParams(params)}`;
window.location.hash = `#${hashPrefix}${createQueryParams(params)}`;
};

export const setUrlParam = function setUrlParam(field, value, hashPrefix = '/jobs') {
Expand Down
2 changes: 1 addition & 1 deletion ui/helpers/object.js
Expand Up @@ -3,7 +3,7 @@ export const extendProperties = function extendProperties(dest, src) {
/* Version of _.extend that works with property descriptors */
if (dest !== src) {
for (const key in src) {
if (!src.hasOwnProperty(key)) {
if (!Object.prototype.hasOwnProperty.call(src, key)) {
continue;
}
const descriptor = Object.getOwnPropertyDescriptor(src, key);
Expand Down
5 changes: 3 additions & 2 deletions ui/helpers/revision.js
Expand Up @@ -19,14 +19,15 @@ export const getRevisionTitle = function getRevisionTitle(revisions) {
* Strip out unwanted things like additional lines, trychooser
* syntax, request flags, mq cruft, whitespace, and punctuation
*/
// eslint-disable-next-line prefer-destructuring
title = title.split('\n')[0];
title = title.replace(/\btry: .*/, '');
title = title.replace(/\b(r|sr|f|a)=.*/, '');
title = title.replace(/(imported patch|\[mq\]:) /, '');
title = title.replace(/[;,\-\. ]+$/, '').trim();
title = title.replace(/[;,\-. ]+$/, '').trim();
if (title) {
if (title.length > thTitleSuffixLimit) {
title = title.substr(0, thTitleSuffixLimit - 3) + '...';
title = `${title.substr(0, thTitleSuffixLimit - 3)}...`;
}
break;
}
Expand Down
2 changes: 1 addition & 1 deletion ui/intermittent-failures/DateRangePicker.jsx
Expand Up @@ -30,7 +30,7 @@ export default class DateRangePicker extends React.Component {
}

showFromMonth() {
const from = this.state.from;
const { from } = this.state;
if (!from) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion ui/intermittent-failures/helpers.js
Expand Up @@ -113,7 +113,7 @@ export const validateQueryParams = function validateQueryParams(params, bugRequi
if (!params.endday || params.endday.search(dateFormat) === -1) {
messages.push(prettyErrorMessages.endday);
}
if (bugRequired && (!params.bug || isNaN(params.bug))) {
if (bugRequired && (!params.bug || Number.isNaN(params.bug))) {
messages.push(prettyErrorMessages.bug_ui);
}
return messages;
Expand Down
2 changes: 1 addition & 1 deletion ui/job-view/App.jsx
Expand Up @@ -29,7 +29,7 @@ const HIDDEN_URL_PARAMS = [
'repo', 'classifiedState', 'resultStatus', 'selectedJob', 'searchStr',
];

const getWindowHeight = function () {
const getWindowHeight = function getWindowHeight() {
const windowHeight = window.innerHeight;
const navBar = document.getElementById('th-global-navbar');
const navBarHeight = navBar ? navBar.clientHeight : 0;
Expand Down
8 changes: 4 additions & 4 deletions ui/job-view/context/Pushes.jsx
Expand Up @@ -191,7 +191,7 @@ export class PushesClass extends React.Component {
const decisionTask = this.getGeckoDecisionJob(pushId);
if (decisionTask) {
return JobModel.get(repoName, decisionTask.id).then(
function (job) {
(job) => {
// this failure case is unlikely, but I guess you
// never know
if (!job.taskcluster_metadata) {
Expand All @@ -207,7 +207,7 @@ export class PushesClass extends React.Component {

getLastModifiedJobTime() {
const { jobMap } = this.state;
const latest = max(Object.values(jobMap).map(job => new Date(job.last_modified + 'Z'))) || new Date();
const latest = max(Object.values(jobMap).map(job => new Date(`${job.last_modified}Z`))) || new Date();

latest.setSeconds(latest.getSeconds() - 3);
return latest;
Expand Down Expand Up @@ -268,7 +268,7 @@ export class PushesClass extends React.Component {
if (!defaulting && cachedReloadTriggerParams &&
!isEqual(newReloadTriggerParams, cachedReloadTriggerParams) &&
!this.skipNextPageReload) {
location.reload();
window.location.reload();
} else {
this.setState({ cachedReloadTriggerParams: newReloadTriggerParams });
}
Expand Down Expand Up @@ -346,7 +346,7 @@ export class PushesClass extends React.Component {
// updated version of that selected job, then send that with the event.
const selectedJobId = getUrlParam('selectedJob');
const updatedSelectedJob = selectedJobId ?
jobList.find(job => job.id === parseInt(selectedJobId)) : null;
jobList.find(job => job.id === parseInt(selectedJobId, 10)) : null;

window.dispatchEvent(new CustomEvent(
thEvents.applyNewJobs,
Expand Down
2 changes: 1 addition & 1 deletion ui/job-view/context/SelectedJob.jsx
Expand Up @@ -84,7 +84,7 @@ class SelectedJobClass extends React.Component {
const { notify, jobMap } = this.props;
const { repoName, selectedJob } = this.state;
const selectedJobIdStr = getUrlParam('selectedJob');
const selectedJobId = parseInt(selectedJobIdStr);
const selectedJobId = parseInt(selectedJobIdStr, 10);

if (selectedJobIdStr && (!selectedJob || selectedJob.id !== selectedJobId)) {
const selectedJob = jobMap[selectedJobIdStr];
Expand Down
11 changes: 7 additions & 4 deletions ui/job-view/details/BugFiler.jsx
Expand Up @@ -22,6 +22,7 @@ const omittedLeads = ['TEST-UNEXPECTED-FAIL', 'PROCESS-CRASH', 'TEST-UNEXPECTED-
*/
const findFilename = (summary) => {
// Take left side of any reftest comparisons, as the right side is the reference file
// eslint-disable-next-line prefer-destructuring
summary = summary.split('==')[0];
// Take the leaf node of unix paths
summary = summary.split('/').pop();
Expand All @@ -30,6 +31,7 @@ const findFilename = (summary) => {
// Remove leading/trailing whitespace
summary = summary.trim();
// If there's a space in what's remaining, take the first word
// eslint-disable-next-line prefer-destructuring
summary = summary.split(' ')[0];
return summary;
};
Expand Down Expand Up @@ -202,18 +204,19 @@ export class BugFilerClass extends React.Component {

// If the "TEST-UNEXPECTED-foo" isn't one of the omitted ones, use the next piece in the summary
if (failurePath.includes('TEST-UNEXPECTED-')) {
// eslint-disable-next-line prefer-destructuring
failurePath = parsedSummary[0][1];
possibleFilename = findFilename(failurePath);
}

const lowerJobGroupName = jobGroupName.toLowerCase();
// Try to fix up file paths for some job types.
if (lowerJobGroupName.includes('spidermonkey')) {
failurePath = 'js/src/tests/' + failurePath;
failurePath = `js/src/tests/${failurePath}`;
}
if (lowerJobGroupName.includes('videopuppeteer ')) {
failurePath = failurePath.replace('FAIL ', '');
failurePath = 'dom/media/test/external/external_media_tests/' + failurePath;
failurePath = `dom/media/test/external/external_media_tests/${failurePath}`;
}
if (lowerJobGroupName.includes('web platform')) {
failurePath = failurePath.startsWith('mozilla/tests') ?
Expand All @@ -236,7 +239,7 @@ export class BugFilerClass extends React.Component {
// Bug 1358328 - We need to override headers here until DXR returns JSON with the default Accept header
fetch(dxrlink, { headers: { Accept: 'application/json' } })
.then((secondRequest) => {
const results = secondRequest.data.results;
const { results } = secondRequest.data;
let resultsCount = results.length;
// If the search returns too many results, this probably isn't a good search term, so bail
if (resultsCount === 0) {
Expand Down Expand Up @@ -361,7 +364,7 @@ export class BugFilerClass extends React.Component {

let failureString = `${source} returned status ${status}(${statusText})`;
if (data && data.failure) {
failureString += '\n\n' + data.failure;
failureString += `\n\n${data.failure}`;
}
if (status === 403) {
failureString += '\n\nAuthentication failed. Has your Treeherder session expired?';
Expand Down