diff --git a/.eslintrc-preferred.yml b/.eslintrc-preferred.yml index 23766a71a83633c958ccbd3d3160f49b116de4b1..f08d82881046fe5e37e86723f8ed0786d98bf153 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 1d9b2c6e5f6a71f3a89b7d940fe45e080719bc93..6a09b28ea259fdba4870d753ca538238c3745815 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 5343f39659c35c835908642f37b8ffdba19537a1..9436e619346171ab2ee8b0dea78e6313e845acb0 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 3f4c88c68f4883f1785a1e7c74a54c5b6d0991c2..94799f93119f130c4a894f322c6b345e804e2d53 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 2c4b456c92c4b966fcfff792d371f44a8af0c68a..bde3076f4a4fa6ae0841c2cef49a2ca6b581139a 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 b077f797d0ead8257c620629c4523881f0232caa..28b106c0ed026dc310f657c3a5f463716d152666 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 8ac6910912257f650af1730cef4cd92a95c91245..c176d76cb9c1592135910c4795e46741ac2b82c5 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 e9c2ec049ff392c0006fbd5ea45621a3f21f7dfc..b44eb4c5f543eb8bd0b84424a58bfa422d97415a 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 f7f8d8f17df4ca0a118f154c617381fb3d920047..02729d42c92dac276cd3deffcfded225f750c2cc 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 2f0cd06981fa144b36562fcda276cc31223d87e8..46fa4ee5b38bf37976c77ea4c68b6f5a92a6dde4 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 a5804be0b0353fc6ea8aa295bbf43786141d0787..0b4fc79589e3a603c6485dc8fd4c89527e6a0f52 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 d2b73d84d2d42309136ad06cda448e74dc2671d9..70df1ad2aca0cf55caf27bc68ad1e46e369027e0 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 03ca3498f784b0cc032247c96cc603a2f33200b4..656b4341e0e9a22c4894ffb9917f28e45dc7705b 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 658f0cb4a14d537de83242eab5d189f40a02e0ac..eaf4aacc0120c57363723f65a7d6e0a636e3dfc7 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 4879bd4d10e48db5802e7fcb2cab752a05a7918c..dd16bede54a08335dfdc03efaec4a631edd051c6 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 b51d018883315a58fb21bb56f9fb270687976348..c89f003142db545ac5f2b9a264e06048212bec66 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 1d62eeff972d6dc185cd48fd957473903690ad25..acc19bd56d6e4eca7cc5a52d1e17601d2a6ed56d 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 bde110f2aedcdf038e335a2bc116f779e875d7c5..48d99ed5c95c63d435b148aca349f4be820de8f9 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 937a156acc27be688db6dbe6defba96089827563..c262c02e4b6a1bbfe0be5e693031690f7ba003a9 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 bd26d9f2293513afe04aeea2069c68f3f83bfe69..144d52e4c953e8639029348ba5a8efb293741fd7 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 0ff815e17eb53a6daf3406bdac52944f1973ec16..0f0050991c231bea94c88f93e02834fec7227079 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 3ee34077302c1935c3ab0fa2751ae1db4f5e3358..24ace473fe4cd313228feb331bd5494ba8c2ffc7 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 e38f71bf918d9c975fee9721086f6f773be77af8..dff54b3a22da0bdabe42a32dc062329113d7a0da 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 1ea58ea22868abc977090eeddca2756e7685a61c..2ea684aef9d727f2694f59d52f22af6c50927758 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 65f303b27f97792c6eceb72cadbe3fe7e0a13a67..3f993c311afad1e11716510cdfeb87e9f02f9dd9 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 8cfefb7e1baaa37b77ab289946d2494cb84b4809..edcaeb52cb141e8ea3a70b69e631d03d3308e980 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 b4fdd1853608b271a81849852f34efaa81c35b3c..a3795e3e833a3a7a3f25cc75e84a2a066b762bdc 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 5ad73a12d117a7f4b91b19c08eda04ab70815db8..fdbe7111b9805243ae6c09094401e23782912eda 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 0b7e8ef6dc808af5f639e6184374399b67d2e961..cdf75850ee80e411bc2cba304c075839dd320cf8 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 d8f5b4c6aa20a393f345e27dbf264591c77121ce..2c64a15262f9e21d6fd8d9d0b8a5b499bee1e37c 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 6f23ffa235e5d96460f191028151b9aaa2f9fb29..197627a759e748bff0e2ad4f557cb05029f4d7fc 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 8ffbda32e5775dcf18638bd912bf23d13858e451..de13bc09f754563eff23ada7ff3d89f0995ad48b 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 ad9378bb636b070a21837911c92ca4ba7fc50630..e6c39a87a3c7004c18a5060d50ec5ab75627e712 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 f17d1970420657b6a00846f4c28f8b4fd546f975..db591535a1cab9da5b524315ef8de40d00ffbbd6 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 9d00ea8ada56c37741713fa239149b8cb8290cdd..b3996f437d0b3a53860e9eb3426babba4ea46e0d 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') })