From 66d444aa40703d401b5f13790eabd2259f136e3f Mon Sep 17 00:00:00 2001 From: Paul Melnikow <github@paulmelnikow.com> Date: Sun, 12 Aug 2018 20:45:43 -0400 Subject: [PATCH] Clean up our callback style and enforce no exclusive tests and remove an exclusive test (#1900) We use arrow functions in most places; this enforces it. Passing arrow functions to Mocha is discouraged: https://mochajs.org/#arrow-functions This was a mix of autofixes and hand adjustments. --- .eslintrc-preferred.yml | 3 ++ .eslintrc.yml | 6 +++ frontend/components/search-results.js | 15 ++---- lib/analytics.js | 2 +- lib/github-auth.js | 69 +++++++++++++------------- lib/github-provider.js | 4 +- lib/licenses.spec.js | 2 +- lib/load-logos.js | 2 +- lib/load-simple-icons.js | 2 +- lib/log.js | 2 +- lib/log.spec.js | 18 +++---- lib/luarocks-version.js | 2 +- lib/make-badge.js | 8 +-- lib/make-badge.spec.js | 44 ++++++++-------- lib/nuget-provider.js | 34 ++++++------- lib/pypi-helpers.js | 2 +- lib/pypi-helpers.spec.js | 4 +- lib/request-handler.js | 1 + lib/suggest.js | 10 ++-- lib/svg-badge-parser.js | 2 +- lib/sys/monitor.js | 4 +- lib/teamcity-badge-helpers.js | 54 ++++++++++---------- lib/text-formatters.js | 4 +- lib/text-measurer.spec.js | 8 +-- lib/version.js | 28 ++++------- package-lock.json | 9 ++++ package.json | 1 + services/base-json.spec.js | 2 +- services/base.spec.js | 10 ++-- services/gem/gem-downloads.service.js | 16 ++---- services/gemnasium/gemnasium.tester.js | 2 +- services/github/auth/admin.js | 2 +- services/json/json.tester.js | 2 +- services/service-tester.js | 1 + services/xml/xml.tester.js | 2 +- 35 files changed, 185 insertions(+), 192 deletions(-) diff --git a/.eslintrc-preferred.yml b/.eslintrc-preferred.yml index 23766a71a8..f08d828810 100644 --- a/.eslintrc-preferred.yml +++ b/.eslintrc-preferred.yml @@ -20,7 +20,10 @@ rules: no-var: "error" prefer-const: "error" strict: "error" + arrow-body-style: ["error", "as-needed"] # Chai friendly. no-unused-expressions: "off" chai-friendly/no-unused-expressions: "error" + + mocha/prefer-arrow-callback: "error" diff --git a/.eslintrc.yml b/.eslintrc.yml index 1d9b2c6e5f..6a09b28ea2 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -7,6 +7,9 @@ env: es6: true mocha: true +plugins: + - mocha + extends: # Enable a set of unopinionated, style-agnostic rules which cover many # likely errors. @@ -28,3 +31,6 @@ rules: eol-last: "error" object-curly-spacing: ["error", "always"] comma-dangle: ["error", "always-multiline"] + + mocha/no-exclusive-tests: "error" + mocha/no-mocha-arrows: "error" diff --git a/frontend/components/search-results.js b/frontend/components/search-results.js index 5343f39659..9436e61934 100644 --- a/frontend/components/search-results.js +++ b/frontend/components/search-results.js @@ -32,16 +32,11 @@ export default class SearchResults extends React.Component { } renderCategoryHeadings() { - return this.preparedExamples.map(function(category, i) { - return ( - <Link - to={'/examples/' + category.category.id} - key={category.category.id} - > - <h3 id={category.category.id}>{category.category.name}</h3> - </Link> - ) - }) + return this.preparedExamples.map((category, i) => ( + <Link to={'/examples/' + category.category.id} key={category.category.id}> + <h3 id={category.category.id}>{category.category.name}</h3> + </Link> + )) } render() { diff --git a/lib/analytics.js b/lib/analytics.js index 3f4c88c68f..94799f9311 100644 --- a/lib/analytics.js +++ b/lib/analytics.js @@ -62,7 +62,7 @@ function defaultAnalytics() { function load() { const defaultAnalyticsObject = defaultAnalytics() if (useRedis) { - redis.get(analyticsPath, function(err, value) { + redis.get(analyticsPath, (err, value) => { if (err == null && value != null) { // if/try/return trick: // if error, then the rest of the function is run. diff --git a/lib/github-auth.js b/lib/github-auth.js index 2c4b456c92..bde3076f4a 100644 --- a/lib/github-auth.js +++ b/lib/github-auth.js @@ -25,7 +25,7 @@ if (serverSecrets && serverSecrets.gh_token) { function setRoutes(server) { const baseUrl = process.env.BASE_URL || 'https://img.shields.io' - server.route(/^\/github-auth$/, function(data, match, end, ask) { + server.route(/^\/github-auth$/, (data, match, end, ask) => { if (!(serverSecrets && serverSecrets.gh_client_id)) { return end('This server is missing GitHub client secrets.') } @@ -41,7 +41,7 @@ function setRoutes(server) { end('') }) - server.route(/^\/github-auth\/done$/, function(data, match, end, ask) { + server.route(/^\/github-auth\/done$/, (data, match, end, ask) => { if ( !( serverSecrets && @@ -68,7 +68,7 @@ function setRoutes(server) { }), method: 'POST', } - request(options, function(err, res, body) { + request(options, (err, res, body) => { if (err != null) { return end('The connection to GitHub failed.') } @@ -96,16 +96,16 @@ function setRoutes(server) { '<p><a href="/">Back to the website</a></p>' ) - sendTokenToAllServers(token).catch(function(e) { + sendTokenToAllServers(token).catch(e => { console.error('GitHub user token transmission failed:', e) }) }) }) - server.route(/^\/github-auth\/add-token$/, function(data, match, end, ask) { + server.route(/^\/github-auth\/add-token$/, (data, match, end, ask) => { if (!secretIsValid(data.shieldsSecret)) { // An unknown entity tries to connect. Let the connection linger for 10s. - return setTimeout(function() { + return setTimeout(() => { end('Invalid secret.') }, 10000) } @@ -117,33 +117,34 @@ function setRoutes(server) { function sendTokenToAllServers(token) { const ips = serverSecrets.shieldsIps return Promise.all( - ips.map(function(ip) { - return new Promise(function(resolve, reject) { - const options = { - url: 'https://' + ip + '/github-auth/add-token', - method: 'POST', - form: { - shieldsSecret: serverSecrets.shieldsSecret, - token: token, - }, - // We target servers by IP, and we use HTTPS. Assuming that - // 1. Internet routers aren't hacked, and - // 2. We don't unknowingly lose our IP to someone else, - // we're not leaking people's and our information. - // (If we did, it would have no impact, as we only ask for a token, - // no GitHub scope. The malicious entity would only be able to use - // our rate limit pool.) - // FIXME: use letsencrypt. - strictSSL: false, - } - request(options, function(err, res, body) { - if (err != null) { - return reject(err) + ips.map( + ip => + new Promise((resolve, reject) => { + const options = { + url: 'https://' + ip + '/github-auth/add-token', + method: 'POST', + form: { + shieldsSecret: serverSecrets.shieldsSecret, + token: token, + }, + // We target servers by IP, and we use HTTPS. Assuming that + // 1. Internet routers aren't hacked, and + // 2. We don't unknowingly lose our IP to someone else, + // we're not leaking people's and our information. + // (If we did, it would have no impact, as we only ask for a token, + // no GitHub scope. The malicious entity would only be able to use + // our rate limit pool.) + // FIXME: use letsencrypt. + strictSSL: false, } - resolve() + request(options, (err, res, body) => { + if (err != null) { + return reject(err) + } + resolve() + }) }) - }) - }) + ) ) } @@ -179,9 +180,7 @@ function isTokenUsable(token, now) { // with a reasonable chance that the request will succeed. function usableTokens() { const now = utcEpochSeconds() - return githubUserTokens.filter(function(token) { - return isTokenUsable(token, now) - }) + return githubUserTokens.filter(token => isTokenUsable(token, now)) } // Retrieve a user token if there is one for which we believe there are requests @@ -308,7 +307,7 @@ function githubRequest(request, url, query, cb) { url += '?' + qs } - request(url, { headers: headers }, function(err, res, buffer) { + request(url, { headers: headers }, (err, res, buffer) => { if (globalToken !== null && githubToken !== null && err === null) { if (res.statusCode === 401) { // Unauthorized. diff --git a/lib/github-provider.js b/lib/github-provider.js index b077f797d0..28b106c0ed 100644 --- a/lib/github-provider.js +++ b/lib/github-provider.js @@ -14,7 +14,7 @@ const { age } = require('./color-formatters') function mapGithubCommitsSince({ camp, cache }, githubApiProvider) { camp.route( /^\/github\/commits-since\/([^/]+)\/([^/]+)\/([^/]+)\.(svg|png|gif|jpg|json)$/, - cache(function(data, match, sendBadge, request) { + cache((data, match, sendBadge, request) => { const user = match[1] // eg, SubtitleEdit const repo = match[2] // eg, subtitleedit const version = match[3] // eg, 3.4.7 or latest @@ -73,7 +73,7 @@ function mapGithubCommitsSince({ camp, cache }, githubApiProvider) { function mapGithubReleaseDate({ camp, cache }, githubApiProvider) { camp.route( /^\/github\/(release-date|release-date-pre)\/([^/]+)\/([^/]+)\.(svg|png|gif|jpg|json)$/, - cache(function(data, match, sendBadge, request) { + cache((data, match, sendBadge, request) => { const releaseType = match[1] // eg, release-date-pre / release-date const user = match[2] // eg, microsoft const repo = match[3] // eg, vscode diff --git a/lib/licenses.spec.js b/lib/licenses.spec.js index 8ac6910912..c176d76cb9 100644 --- a/lib/licenses.spec.js +++ b/lib/licenses.spec.js @@ -3,7 +3,7 @@ const { test, given } = require('sazerac') const { licenseToColor } = require('./licenses') -describe('license helpers', () => { +describe('license helpers', function() { test(licenseToColor, () => { given('MIT').expect('green') given('MPL-2.0').expect('orange') diff --git a/lib/load-logos.js b/lib/load-logos.js index e9c2ec049f..b44eb4c5f5 100644 --- a/lib/load-logos.js +++ b/lib/load-logos.js @@ -9,7 +9,7 @@ function loadLogos() { const logos = {} const logoDir = path.join(__dirname, '..', 'logo') const logoFiles = fs.readdirSync(logoDir) - logoFiles.forEach(function(filename) { + logoFiles.forEach(filename => { if (filename[0] === '.') { return } diff --git a/lib/load-simple-icons.js b/lib/load-simple-icons.js index f7f8d8f17d..02729d42c9 100644 --- a/lib/load-simple-icons.js +++ b/lib/load-simple-icons.js @@ -4,7 +4,7 @@ const simpleIcons = require('simple-icons') const { svg2base64 } = require('./logo-helper') function loadSimpleIcons() { - Object.keys(simpleIcons).forEach(function(key) { + Object.keys(simpleIcons).forEach(key => { const k = key.toLowerCase().replace(/ /g, '-') if (k !== key) { simpleIcons[k] = simpleIcons[key] diff --git a/lib/log.js b/lib/log.js index 2f0cd06981..46fa4ee5b3 100644 --- a/lib/log.js +++ b/lib/log.js @@ -37,7 +37,7 @@ const throttledConsoleError = throttle(console.error, 10000, { module.exports.error = function error(...msg) { const d = date() listeners.forEach(f => f(d, ...msg)) - Raven.captureException(msg, function(sendErr) { + Raven.captureException(msg, sendErr => { if (sendErr) { throttledConsoleError( 'Failed to send captured exception to Sentry', diff --git a/lib/log.spec.js b/lib/log.spec.js index a5804be0b0..0b4fc79589 100644 --- a/lib/log.spec.js +++ b/lib/log.spec.js @@ -12,27 +12,25 @@ function requireUncached(module) { return require(module) } -describe('log', () => { - describe('error', () => { - before(() => { +describe('log', function() { + describe('error', function() { + before(function() { this.clock = sinon.useFakeTimers() - sinon - .stub(Raven, 'captureException') - .callsFake(function fakeFn(e, callback) { - callback(new Error(`Cannot send message "${e}" to Sentry.`)) - }) + sinon.stub(Raven, 'captureException').callsFake((e, callback) => { + callback(new Error(`Cannot send message "${e}" to Sentry.`)) + }) // we have to create a spy before requiring 'error' function sinon.spy(console, 'error') this.error = requireUncached('./log').error }) - after(() => { + after(function() { this.clock.restore() console.error.restore() Raven.captureException.restore() }) - it('should throttle errors from Raven client', () => { + it('should throttle errors from Raven client', function() { this.error('test error 1') this.error('test error 2') this.error('test error 3') diff --git a/lib/luarocks-version.js b/lib/luarocks-version.js index d2b73d84d2..70df1ad2ac 100644 --- a/lib/luarocks-version.js +++ b/lib/luarocks-version.js @@ -30,7 +30,7 @@ exports.compareVersionLists = compareVersionLists function parseVersion(versionString) { versionString = versionString.toLowerCase().replace('-', '.') const versionList = [] - versionString.split('.').forEach(function(versionPart) { + versionString.split('.').forEach(versionPart => { const parsedPart = /(\d*)([a-z]*)(\d*)/.exec(versionPart) if (parsedPart[1]) { versionList.push(parseInt(parsedPart[1])) diff --git a/lib/make-badge.js b/lib/make-badge.js index 03ca3498f7..656b4341e0 100644 --- a/lib/make-badge.js +++ b/lib/make-badge.js @@ -14,7 +14,7 @@ const badgeKeyWidthCache = new LruCache(1000) const templates = {} const templateFiles = fs.readdirSync(path.join(__dirname, '..', 'templates')) dot.templateSettings.strip = false // Do not strip whitespace. -templateFiles.forEach(async function(filename) { +templateFiles.forEach(async filename => { if (filename[0] === '.') { return } @@ -29,7 +29,7 @@ templateFiles.forEach(async function(filename) { // Substitute dot code. const mapping = new Map() let mappingIndex = 1 - const untemplatedSvg = templateData.replace(/{{.*?}}/g, function(match) { + const untemplatedSvg = templateData.replace(/{{.*?}}/g, match => { // Weird substitution that currently works for all templates. const mapKey = '99999990' + mappingIndex + '.1' mappingIndex++ @@ -52,9 +52,9 @@ templateFiles.forEach(async function(filename) { // Substitute dot code back. let svg = data const unmappedKeys = [] - mapping.forEach(function(value, key) { + mapping.forEach((value, key) => { let keySubstituted = false - svg = svg.replace(RegExp(key, 'g'), function() { + svg = svg.replace(RegExp(key, 'g'), () => { keySubstituted = true return value }) diff --git a/lib/make-badge.spec.js b/lib/make-badge.spec.js index 658f0cb4a1..eaf4aacc01 100644 --- a/lib/make-badge.spec.js +++ b/lib/make-badge.spec.js @@ -21,12 +21,12 @@ function testColor(color = '') { ).colorB } -describe('The badge generator', () => { - beforeEach(() => { +describe('The badge generator', function() { + beforeEach(function() { _badgeKeyWidthCache.clear() }) - describe('color test', () => { + describe('color test', function() { test(testColor, () => { // valid hex given('#4c1').expect('#4c1') @@ -68,8 +68,8 @@ describe('The badge generator', () => { }) }) - describe('SVG', () => { - it('should produce SVG', () => { + describe('SVG', function() { + it('should produce SVG', function() { const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' }) expect(svg) .to.satisfy(isSvg) @@ -77,24 +77,24 @@ describe('The badge generator', () => { .and.to.include('grown') }) - it('should always produce the same SVG (unless we have changed something!)', () => { + it('should always produce the same SVG (unless we have changed something!)', function() { const svg = makeBadge({ text: ['cactus', 'grown'], format: 'svg' }) snapshot(svg) }) - it('should cache width of badge key', () => { + it('should cache width of badge key', function() { makeBadge({ text: ['cached', 'not-cached'], format: 'svg' }) expect(_badgeKeyWidthCache.cache).to.have.keys('cached') }) }) - describe('JSON', () => { - it('should always produce the same JSON (unless we have changed something!)', () => { + describe('JSON', function() { + it('should always produce the same JSON (unless we have changed something!)', function() { const json = makeBadge({ text: ['cactus', 'grown'], format: 'json' }) snapshot(json) }) - it('should replace unknown json template with "default"', () => { + it('should replace unknown json template with "default"', function() { const jsonBadgeWithUnknownStyle = makeBadge({ text: ['name', 'Bob'], format: 'json', @@ -112,7 +112,7 @@ describe('The badge generator', () => { }) }) - it('should replace unknown svg template with "flat"', () => { + it('should replace unknown svg template with "flat"', function() { const jsonBadgeWithUnknownStyle = makeBadge({ text: ['name', 'Bob'], format: 'svg', @@ -129,9 +129,9 @@ describe('The badge generator', () => { }) }) - describe('"for-the-badge" template badge generation', () => { + describe('"for-the-badge" template badge generation', function() { // https://github.com/badges/shields/issues/1280 - it('numbers should produce a string', () => { + it('numbers should produce a string', function() { const svg = makeBadge({ text: [1998, 1999], format: 'svg', @@ -142,7 +142,7 @@ describe('The badge generator', () => { .and.to.include('1999') }) - it('lowercase/mixedcase string should produce uppercase string', () => { + it('lowercase/mixedcase string should produce uppercase string', function() { const svg = makeBadge({ text: ['Label', '1 string'], format: 'svg', @@ -154,8 +154,8 @@ describe('The badge generator', () => { }) }) - describe('"social" template badge generation', () => { - it('should produce capitalized string for badge key', () => { + describe('"social" template badge generation', function() { + it('should produce capitalized string for badge key', function() { const svg = makeBadge({ text: ['some-key', 'some-value'], format: 'svg', @@ -167,7 +167,7 @@ describe('The badge generator', () => { }) // https://github.com/badges/shields/issues/1606 - it('should handle empty strings used as badge keys', () => { + it('should handle empty strings used as badge keys', function() { const svg = makeBadge({ text: ['', 'some-value'], format: 'json', @@ -178,8 +178,8 @@ describe('The badge generator', () => { .and.to.include('some-value') }) }) - describe('badges with logos should always produce the same badge', () => { - it('shields GitHub logo default color (#333333)', () => { + describe('badges with logos should always produce the same badge', function() { + it('shields GitHub logo default color (#333333)', function() { const svg = makeBadge({ text: ['label', 'message'], format: 'svg', @@ -188,7 +188,7 @@ describe('The badge generator', () => { snapshot(svg) }) - it('shields GitHub logo custom color (whitesmoke)', () => { + it('shields GitHub logo custom color (whitesmoke)', function() { const svg = makeBadge({ text: ['label', 'message'], format: 'svg', @@ -198,7 +198,7 @@ describe('The badge generator', () => { snapshot(svg) }) - it('simple-icons javascript logo default color (#F7DF1E)', () => { + it('simple-icons javascript logo default color (#F7DF1E)', function() { const svg = makeBadge({ text: ['label', 'message'], format: 'svg', @@ -207,7 +207,7 @@ describe('The badge generator', () => { snapshot(svg) }) - it('simple-icons javascript logo custom color (rgba(46,204,113,0.8))', () => { + it('simple-icons javascript logo custom color (rgba(46,204,113,0.8))', function() { const svg = makeBadge({ text: ['label', 'message'], format: 'svg', diff --git a/lib/nuget-provider.js b/lib/nuget-provider.js index 4879bd4d10..dd16bede54 100644 --- a/lib/nuget-provider.js +++ b/lib/nuget-provider.js @@ -24,7 +24,7 @@ function mapNugetFeedv2({ camp, cache }, pattern, offset, getInfo) { request( reqUrl, { headers: { Accept: 'application/atom+json,application/json' } }, - function(err, res, buffer) { + (err, res, buffer) => { if (err != null) { done(new Error('inaccessible')) return @@ -51,14 +51,14 @@ function mapNugetFeedv2({ camp, cache }, pattern, offset, getInfo) { camp.route( vRegex, - cache(function(data, match, sendBadge, request) { + cache((data, match, sendBadge, request) => { const info = getInfo(match) const site = info.site // eg, `Chocolatey`, or `YoloDev` const repo = match[offset + 1] // eg, `Nuget.Core`. const format = match[offset + 2] const apiUrl = info.feed const badgeData = getBadgeData(site, data) - getNugetPackage(apiUrl, repo, null, request, function(err, data) { + getNugetPackage(apiUrl, repo, null, request, (err, data) => { if (err != null) { badgeData.text[1] = err.message sendBadge(format, badgeData) @@ -80,14 +80,14 @@ function mapNugetFeedv2({ camp, cache }, pattern, offset, getInfo) { camp.route( vPreRegex, - cache(function(data, match, sendBadge, request) { + cache((data, match, sendBadge, request) => { const info = getInfo(match) const site = info.site // eg, `Chocolatey`, or `YoloDev` const repo = match[offset + 1] // eg, `Nuget.Core`. const format = match[offset + 2] const apiUrl = info.feed const badgeData = getBadgeData(site, data) - getNugetPackage(apiUrl, repo, true, request, function(err, data) { + getNugetPackage(apiUrl, repo, true, request, (err, data) => { if (err != null) { badgeData.text[1] = err.message sendBadge(format, badgeData) @@ -109,13 +109,13 @@ function mapNugetFeedv2({ camp, cache }, pattern, offset, getInfo) { camp.route( dtRegex, - cache(function(data, match, sendBadge, request) { + cache((data, match, sendBadge, request) => { const info = getInfo(match) const repo = match[offset + 1] // eg, `Nuget.Core`. const format = match[offset + 2] const apiUrl = info.feed const badgeData = getBadgeData('downloads', data) - getNugetPackage(apiUrl, repo, null, request, function(err, data) { + getNugetPackage(apiUrl, repo, null, request, (err, data) => { if (err != null) { badgeData.text[1] = err.message sendBadge(format, badgeData) @@ -206,7 +206,7 @@ function mapNugetFeed({ camp, cache }, pattern, offset, getInfo) { } function getNugetVersion(apiUrl, id, includePre, request, done) { - getNugetData(apiUrl, id, request, function(err, data) { + getNugetData(apiUrl, id, request, (err, data) => { if (err) { done(err) return @@ -214,9 +214,9 @@ function mapNugetFeed({ camp, cache }, pattern, offset, getInfo) { let versions = data.versions || [] if (!includePre) { // Remove prerelease versions. - const filteredVersions = versions.filter(function(version) { - return !/-/.test(version.version) - }) + const filteredVersions = versions.filter( + version => !/-/.test(version.version) + ) if (filteredVersions.length > 0) { versions = filteredVersions } @@ -228,14 +228,14 @@ function mapNugetFeed({ camp, cache }, pattern, offset, getInfo) { camp.route( vRegex, - cache(function(data, match, sendBadge, request) { + cache((data, match, sendBadge, request) => { const info = getInfo(match) const site = info.site // eg, `Chocolatey`, or `YoloDev` const repo = match[offset + 1] // eg, `Nuget.Core`. const format = match[offset + 2] const apiUrl = info.feed const badgeData = getBadgeData(site, data) - getNugetVersion(apiUrl, repo, false, request, function(err, version) { + getNugetVersion(apiUrl, repo, false, request, (err, version) => { if (err != null) { badgeData.text[1] = err.message sendBadge(format, badgeData) @@ -261,14 +261,14 @@ function mapNugetFeed({ camp, cache }, pattern, offset, getInfo) { camp.route( vPreRegex, - cache(function(data, match, sendBadge, request) { + cache((data, match, sendBadge, request) => { const info = getInfo(match) const site = info.site // eg, `Chocolatey`, or `YoloDev` const repo = match[offset + 1] // eg, `Nuget.Core`. const format = match[offset + 2] const apiUrl = info.feed const badgeData = getBadgeData(site, data) - getNugetVersion(apiUrl, repo, true, request, function(err, version) { + getNugetVersion(apiUrl, repo, true, request, (err, version) => { if (err != null) { badgeData.text[1] = err.message sendBadge(format, badgeData) @@ -294,13 +294,13 @@ function mapNugetFeed({ camp, cache }, pattern, offset, getInfo) { camp.route( dtRegex, - cache(function(data, match, sendBadge, request) { + cache((data, match, sendBadge, request) => { const info = getInfo(match) const repo = match[offset + 1] // eg, `Nuget.Core`. const format = match[offset + 2] const apiUrl = info.feed const badgeData = getBadgeData('downloads', data) - getNugetData(apiUrl, repo, request, function(err, nugetData) { + getNugetData(apiUrl, repo, request, (err, nugetData) => { if (err != null) { badgeData.text[1] = err.message sendBadge(format, badgeData) diff --git a/lib/pypi-helpers.js b/lib/pypi-helpers.js index b51d018883..c89f003142 100644 --- a/lib/pypi-helpers.js +++ b/lib/pypi-helpers.js @@ -23,7 +23,7 @@ const parseDjangoVersionString = function(str) { // sort an array of django versions low to high const sortDjangoVersions = function(versions) { - return versions.sort(function(a, b) { + return versions.sort((a, b) => { if ( parseDjangoVersionString(a).major === parseDjangoVersionString(b).major ) { diff --git a/lib/pypi-helpers.spec.js b/lib/pypi-helpers.spec.js index 1d62eeff97..acc19bd56d 100644 --- a/lib/pypi-helpers.spec.js +++ b/lib/pypi-helpers.spec.js @@ -53,9 +53,7 @@ describe('PyPI helpers', function() { // regex that matches everything given(classifiersFixture, /^([\S\s+]+)$/).expect( - classifiersFixture.info.classifiers.map(function(e) { - return e.toLowerCase() - }) + classifiersFixture.info.classifiers.map(e => e.toLowerCase()) ) // regex that matches nothing diff --git a/lib/request-handler.js b/lib/request-handler.js index bde110f2ae..48d99ed5c9 100644 --- a/lib/request-handler.js +++ b/lib/request-handler.js @@ -211,6 +211,7 @@ function handleRequest(makeBadge, handlerOptions) { const result = handlerOptions.handler( filteredQueryParams, match, + // eslint-disable-next-line mocha/prefer-arrow-callback function sendBadge(format, badgeData) { if (serverUnresponsive) { return diff --git a/lib/suggest.js b/lib/suggest.js index 937a156acc..c262c02e4b 100644 --- a/lib/suggest.js +++ b/lib/suggest.js @@ -51,15 +51,13 @@ function findSuggestions(githubApiProvider, url, cb) { } promises.push(twitterPage(url)) Promise.all(promises) - .then(function(badges) { + .then(badges => { // eslint-disable-next-line standard/no-callback-literal cb({ - badges: badges.filter(function(b) { - return b != null - }), + badges: badges.filter(b => b != null), }) }) - .catch(function(err) { + .catch(err => { // eslint-disable-next-line standard/no-callback-literal cb({ badges: [], err: err }) }) @@ -117,7 +115,7 @@ function githubStars(user, repo) { function githubLicense(githubApiProvider, user, repo) { return new Promise(resolve => { const apiUrl = `/repos/${user}/${repo}/license` - githubApiProvider.request(request, apiUrl, {}, function(err, res, buffer) { + githubApiProvider.request(request, apiUrl, {}, (err, res, buffer) => { if (err !== null) { resolve(null) return diff --git a/lib/svg-badge-parser.js b/lib/svg-badge-parser.js index bd26d9f229..144d52e4c9 100644 --- a/lib/svg-badge-parser.js +++ b/lib/svg-badge-parser.js @@ -21,7 +21,7 @@ function valueFromSvgBadge(svg) { // Get data from a svg-style badge. // cb: function(err, string) function fetchFromSvg(request, url, cb) { - request(url, function(err, res, buffer) { + request(url, (err, res, buffer) => { if (err !== null) { cb(err) } else { diff --git a/lib/sys/monitor.js b/lib/sys/monitor.js index 0ff815e17e..0f0050991c 100644 --- a/lib/sys/monitor.js +++ b/lib/sys/monitor.js @@ -9,7 +9,7 @@ const log = require('../log') function secretInvalid(req, res) { if (!secretIsValid(req.password)) { // An unknown entity tries to connect. Let the connection linger for a minute. - setTimeout(function() { + setTimeout(() => { res.json({ errors: [{ code: 'invalid_secrets' }] }) }, 10000) return true @@ -27,7 +27,7 @@ function setRoutes(server) { whitelist: /^https?:\/\/shields\.io\/$/, }) - server.handle(function monitorHandler(req, res, next) { + server.handle((req, res, next) => { if (req.url.startsWith('/sys/')) { if (secretInvalid(req, res)) { return diff --git a/lib/teamcity-badge-helpers.js b/lib/teamcity-badge-helpers.js index 3ee3407730..24ace473fe 100644 --- a/lib/teamcity-badge-helpers.js +++ b/lib/teamcity-badge-helpers.js @@ -13,33 +13,37 @@ function teamcityBadge( ) { const apiUrl = url + '/app/rest/builds/buildType:(id:' + buildId + ')?guest=1' const badgeData = getBadgeData('build', data) - request(apiUrl, { headers: { Accept: 'application/json' } }, function( - err, - res, - buffer - ) { - if (err != null) { - badgeData.text[1] = 'inaccessible' - sendBadge(format, badgeData) - return - } - try { - const data = JSON.parse(buffer) - if (advanced) - badgeData.text[1] = (data.statusText || data.status || '').toLowerCase() - else badgeData.text[1] = (data.status || '').toLowerCase() - if (data.status === 'SUCCESS') { - badgeData.colorscheme = 'brightgreen' - badgeData.text[1] = 'passing' - } else { - badgeData.colorscheme = 'red' + request( + apiUrl, + { headers: { Accept: 'application/json' } }, + (err, res, buffer) => { + if (err != null) { + badgeData.text[1] = 'inaccessible' + sendBadge(format, badgeData) + return + } + try { + const data = JSON.parse(buffer) + if (advanced) + badgeData.text[1] = ( + data.statusText || + data.status || + '' + ).toLowerCase() + else badgeData.text[1] = (data.status || '').toLowerCase() + if (data.status === 'SUCCESS') { + badgeData.colorscheme = 'brightgreen' + badgeData.text[1] = 'passing' + } else { + badgeData.colorscheme = 'red' + } + sendBadge(format, badgeData) + } catch (e) { + badgeData.text[1] = 'invalid' + sendBadge(format, badgeData) } - sendBadge(format, badgeData) - } catch (e) { - badgeData.text[1] = 'invalid' - sendBadge(format, badgeData) } - }) + ) } module.exports = { diff --git a/lib/text-formatters.js b/lib/text-formatters.js index e38f71bf91..dff54b3a22 100644 --- a/lib/text-formatters.js +++ b/lib/text-formatters.js @@ -50,9 +50,7 @@ function ordinalNumber(n) { // Given a number, string with appropriate unit in the metric system, SI. // Note: numbers beyond the peta- cannot be represented as integers in JS. const metricPrefix = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] -const metricPower = metricPrefix.map(function(a, i) { - return Math.pow(1000, i + 1) -}) +const metricPower = metricPrefix.map((a, i) => Math.pow(1000, i + 1)) function metric(n) { for (let i = metricPrefix.length - 1; i >= 0; i--) { const limit = metricPower[i] diff --git a/lib/text-measurer.spec.js b/lib/text-measurer.spec.js index 1ea58ea228..2ea684aef9 100644 --- a/lib/text-measurer.spec.js +++ b/lib/text-measurer.spec.js @@ -63,7 +63,7 @@ function registerTests(fontPath, skip) { '[prismic "1.1"]', ] - strings.forEach(function(str) { + strings.forEach(str => { it(`should measure '${str}' in parity with PDFKit`, function() { if (skip) { this.skip() @@ -75,7 +75,7 @@ function registerTests(fontPath, skip) { }) }) - strings.forEach(function(str) { + strings.forEach(str => { it(`should measure '${str}' without invoking PDFKit`, function() { if (skip) { this.skip() @@ -122,7 +122,7 @@ function registerTests(fontPath, skip) { context('when given non-ASCII strings', function() { const strings = [starRating(3.5), '\u2026'] - strings.forEach(function(str) { + strings.forEach(str => { it(`should measure '${str}' in parity with PDFKit`, function() { if (skip) { this.skip() @@ -134,7 +134,7 @@ function registerTests(fontPath, skip) { }) }) - strings.forEach(function(str) { + strings.forEach(str => { it(`should invoke the base when measuring '${str}'`, function() { if (skip) { this.skip() diff --git a/lib/version.js b/lib/version.js index 65f303b27f..3f993c311a 100644 --- a/lib/version.js +++ b/lib/version.js @@ -15,30 +15,24 @@ function latest(versions, { pre = false } = {}) { let version = '' let origVersions = versions // return all results that are likely semver compatible versions - versions = origVersions.filter(function(version) { - return /\d+\.\d+/.test(version) - }) + versions = origVersions.filter(version => /\d+\.\d+/.test(version)) // If no semver versions then look for single numbered versions if (!versions.length) { - versions = origVersions.filter(function(version) { - return /\d+/.test(version) - }) + versions = origVersions.filter(version => /\d+/.test(version)) } if (!pre) { // remove pre-releases from array - versions = versions.filter(function(version) { - return !/\d+-\w+/.test(version) - }) + versions = versions.filter(version => !/\d+-\w+/.test(version)) } try { - version = versions.sort((a, b) => { - // coerce to string then lowercase otherwise alpha > RC - return semver.rcompare( + // coerce to string then lowercase otherwise alpha > RC + version = versions.sort((a, b) => + semver.rcompare( ('' + a).toLowerCase(), ('' + b).toLowerCase(), /* loose */ true ) - })[0] + )[0] } catch (e) { version = latestDottedVersion(versions) } @@ -90,12 +84,8 @@ function compareDottedVersion(v1, v2) { const numbers2 = parts2[1] const distinguisher1 = parts1[2] const distinguisher2 = parts2[2] - const numlist1 = numbers1.split('.').map(function(e) { - return +e - }) - const numlist2 = numbers2.split('.').map(function(e) { - return +e - }) + const numlist1 = numbers1.split('.').map(e => +e) + const numlist2 = numbers2.split('.').map(e => +e) const cmp = listCompare(numlist1, numlist2) if (cmp !== 0) { return cmp diff --git a/package-lock.json b/package-lock.json index 8cfefb7e1b..edcaeb52cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4979,6 +4979,15 @@ } } }, + "eslint-plugin-mocha": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-5.1.0.tgz", + "integrity": "sha512-fkmup5IRzCWaH+IVYymVKs3P8SO6Pf9oiuodwrM25YCuodi4UtLgc6z6j5vZeBwJMKj7F7gszqBPoILBP/pf+g==", + "dev": true, + "requires": { + "ramda": "^0.25.0" + } + }, "eslint-plugin-node": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz", diff --git a/package.json b/package.json index b4fdd18536..a3795e3e83 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "eslint-config-standard-react": "^6.0.0", "eslint-plugin-chai-friendly": "^0.4.1", "eslint-plugin-import": "^2.8.0", + "eslint-plugin-mocha": "^5.1.0", "eslint-plugin-node": "^7.0.0", "eslint-plugin-promise": "^3.6.0", "eslint-plugin-react": "^7.6.1", diff --git a/services/base-json.spec.js b/services/base-json.spec.js index 5ad73a12d1..fdbe7111b9 100644 --- a/services/base-json.spec.js +++ b/services/base-json.spec.js @@ -26,7 +26,7 @@ class DummyJsonService extends BaseJsonService { } } -describe('BaseJsonService', () => { +describe('BaseJsonService', function() { it('handles unparseable json responses', async function() { const sendAndCacheRequest = async () => ({ buffer: invalidJSON, diff --git a/services/base.spec.js b/services/base.spec.js index 0b7e8ef6dc..cdf75850ee 100644 --- a/services/base.spec.js +++ b/services/base.spec.js @@ -38,7 +38,7 @@ class DummyService extends BaseService { } } -describe('BaseService', () => { +describe('BaseService', function() { const defaultConfig = { handleInternalErrors: false } describe('URL pattern matching', function() { @@ -131,7 +131,7 @@ describe('BaseService', () => { }) }) - describe.only('Error handling', function() { + describe('Error handling', function() { it('Handles internal errors', async function() { const serviceInstance = new DummyService( {}, @@ -265,7 +265,7 @@ describe('BaseService', () => { let mockCamp let mockHandleRequest - beforeEach(() => { + beforeEach(function() { mockCamp = { route: sinon.spy(), } @@ -273,12 +273,12 @@ describe('BaseService', () => { DummyService.register(mockCamp, mockHandleRequest, defaultConfig) }) - it('registers the service', () => { + it('registers the service', function() { expect(mockCamp.route).to.have.been.calledOnce expect(mockCamp.route).to.have.been.calledWith(expectedRouteRegex) }) - it('handles the request', async () => { + it('handles the request', async function() { expect(mockHandleRequest).to.have.been.calledOnce const { handler: requestHandler } = mockHandleRequest.getCall(0).args[0] diff --git a/services/gem/gem-downloads.service.js b/services/gem/gem-downloads.service.js index d8f5b4c6aa..2c64a15262 100644 --- a/services/gem/gem-downloads.service.js +++ b/services/gem/gem-downloads.service.js @@ -77,22 +77,14 @@ module.exports = class GemDownloads extends BaseJsonService { let versionData if (version !== null && version === 'stable') { const versions = json - .filter(function(ver) { - return ver.prerelease === false - }) - .map(function(ver) { - return ver.number - }) + .filter(ver => ver.prerelease === false) + .map(ver => ver.number) // Found latest stable version. const stableVersion = latestVersion(versions) - versionData = json.filter(function(ver) { - return ver.number === stableVersion - })[0] + versionData = json.filter(ver => ver.number === stableVersion)[0] downloads = versionData.downloads_count } else if (version !== null) { - versionData = json.filter(function(ver) { - return ver.number === version - })[0] + versionData = json.filter(ver => ver.number === version)[0] downloads = versionData.downloads_count } else { diff --git a/services/gemnasium/gemnasium.tester.js b/services/gemnasium/gemnasium.tester.js index 6f23ffa235..197627a759 100644 --- a/services/gemnasium/gemnasium.tester.js +++ b/services/gemnasium/gemnasium.tester.js @@ -10,7 +10,7 @@ module.exports = t t.create('no longer available (previously dependencies)') .get('/mathiasbynens/he.json') - .afterJSON(function(badge) { + .afterJSON(badge => { if (isDeprecated('gemnasium')) { expect(badge.name).to.equal('gemnasium') expect(badge.value).to.equal('no longer available') diff --git a/services/github/auth/admin.js b/services/github/auth/admin.js index 8ffbda32e5..de13bc09f7 100644 --- a/services/github/auth/admin.js +++ b/services/github/auth/admin.js @@ -19,7 +19,7 @@ function setRoutes(server) { server.ajax.on('github-auth/tokens', (json, end, ask) => { if (!secretIsValid(ask.password)) { // An unknown entity tries to connect. Let the connection linger for a minute. - return setTimeout(function() { + return setTimeout(() => { end('Invalid secret.') }, 10000) } diff --git a/services/json/json.tester.js b/services/json/json.tester.js index ad9378bb63..e6c39a87a3 100644 --- a/services/json/json.tester.js +++ b/services/json/json.tester.js @@ -158,6 +158,6 @@ t.create('JSON from url | request should set Accept header') }) ) .expectJSON({ name: 'custom badge', value: 'test' }) - .after(function() { + .after(() => { expect(headers).to.have.property('accept', 'application/json') }) diff --git a/services/service-tester.js b/services/service-tester.js index f17d197042..db591535a1 100644 --- a/services/service-tester.js +++ b/services/service-tester.js @@ -69,6 +69,7 @@ class ServiceTester { const specs = this.specs const fn = this._only ? describe.only : describe + // eslint-disable-next-line mocha/prefer-arrow-callback fn(this.title, function() { specs.forEach(spec => { spec.toss() diff --git a/services/xml/xml.tester.js b/services/xml/xml.tester.js index 9d00ea8ada..b3996f437d 100644 --- a/services/xml/xml.tester.js +++ b/services/xml/xml.tester.js @@ -182,6 +182,6 @@ t.create('XML from url | request should set Accept header') }) ) .expectJSON({ name: 'custom badge', value: 'dynamic xml' }) - .after(function() { + .after(() => { expect(headers).to.have.property('accept', 'application/xml, text/xml') }) -- GitLab