Compare commits

..

1 Commits

Author SHA1 Message Date
chris48s
57036a34b0 migrate integration tests to GH actions 2022-09-22 20:44:43 +01:00
53 changed files with 2157 additions and 2764 deletions

View File

@@ -9,23 +9,23 @@
"version": "0.0.0",
"license": "CC0",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1"
"@actions/core": "^1.9.1",
"@actions/github": "^5.0.3"
}
},
"node_modules/@actions/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"node_modules/@actions/github": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz",
"integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==",
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.3.tgz",
"integrity": "sha512-myjA/pdLQfhUGLtRZC/J4L1RXOG4o6aYdiEq+zr5wVVKljzbFld+xv10k1FX6IkIJtNxbAq44BdwSNpQ015P0A==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"@octokit/core": "^3.6.0",
@@ -235,18 +235,18 @@
},
"dependencies": {
"@actions/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
"requires": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"@actions/github": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz",
"integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==",
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.3.tgz",
"integrity": "sha512-myjA/pdLQfhUGLtRZC/J4L1RXOG4o6aYdiEq+zr5wVVKljzbFld+xv10k1FX6IkIJtNxbAq44BdwSNpQ015P0A==",
"requires": {
"@actions/http-client": "^2.0.1",
"@octokit/core": "^3.6.0",

View File

@@ -10,7 +10,7 @@
"author": "chris48s",
"license": "CC0",
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1"
"@actions/core": "^1.9.1",
"@actions/github": "^5.0.3"
}
}

View File

@@ -1,7 +1,5 @@
name: Auto close
on:
pull_request_target:
types: [opened]
on: pull_request_target
permissions:
pull-requests: write

View File

@@ -1,7 +1,5 @@
name: 'Dependency Review'
on:
pull_request:
types: [opened, edited, reopened, synchronize]
on: [pull_request]
jobs:
enforce-dependency-review:

View File

@@ -4,13 +4,10 @@ on:
push:
branches-ignore:
- 'gh-pages'
- 'dependabot/**'
jobs:
test-integration-17:
runs-on: ubuntu-latest
env:
PAT_EXISTS: ${{ secrets.GH_PAT != '' }}
services:
redis:
@@ -34,14 +31,7 @@ jobs:
env:
NPM_CONFIG_ENGINE_STRICT: 'false'
- name: Integration Tests (with PAT)
if: ${{ env.PAT_EXISTS == 'true' }}
uses: ./.github/actions/integration-tests
with:
github-token: '${{ secrets.GH_PAT }}'
- name: Integration Tests (with workflow token)
if: ${{ env.PAT_EXISTS == 'false' }}
- name: Integration Tests
uses: ./.github/actions/integration-tests
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'

View File

@@ -4,13 +4,10 @@ on:
push:
branches-ignore:
- 'gh-pages'
- 'dependabot/**'
jobs:
test-integration:
runs-on: ubuntu-latest
env:
PAT_EXISTS: ${{ secrets.GH_PAT != '' }}
services:
redis:
@@ -32,14 +29,7 @@ jobs:
with:
node-version: 16
- name: Integration Tests (with PAT)
if: ${{ env.PAT_EXISTS == 'true' }}
uses: ./.github/actions/integration-tests
with:
github-token: '${{ secrets.GH_PAT }}'
- name: Integration Tests (with workflow token)
if: ${{ env.PAT_EXISTS == 'false' }}
- name: Integration Tests
uses: ./.github/actions/integration-tests
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'

View File

@@ -4,7 +4,6 @@ on:
push:
branches-ignore:
- 'gh-pages'
- 'dependabot/**'
jobs:
test-lint:

View File

@@ -4,7 +4,6 @@ on:
push:
branches-ignore:
- 'gh-pages'
- 'dependabot/**'
jobs:
test-main-17:

View File

@@ -4,7 +4,6 @@ on:
push:
branches-ignore:
- 'gh-pages'
- 'dependabot/**'
jobs:
test-main:

View File

@@ -4,7 +4,6 @@ on:
push:
branches-ignore:
- 'gh-pages'
- 'dependabot/**'
# Smoke test (render a badge with the CLI) with only the package
# dependencies installed.

View File

@@ -4,7 +4,6 @@ on:
push:
branches-ignore:
- 'gh-pages'
- 'dependabot/**'
jobs:
test-package-lib:

View File

@@ -4,24 +4,6 @@ Note: this changelog is for the shields.io server. The changelog for the badge-m
---
## server-2022-10-08
- deprecate [criterion] service [#8501](https://github.com/badges/shields/issues/8501)
- fix formatRelativeDate error handling; run [date] [#8497](https://github.com/badges/shields/issues/8497)
- allow/validate bitbucket_username / bitbucket_password in private config schema [#8472](https://github.com/badges/shields/issues/8472)
- fix [pub] points badge test and example [#8498](https://github.com/badges/shields/issues/8498)
- feat: add [GitlabLanguageCount] service [#8377](https://github.com/badges/shields/issues/8377)
- [GitHubGistStars] add GitHub Gist Stars [#8471](https://github.com/badges/shields/issues/8471)
- fix display/search of CII badge examples [#8473](https://github.com/badges/shields/issues/8473)
- feat: add 2022 support to GitHub Hacktoberfest [#8468](https://github.com/badges/shields/issues/8468)
- fix [GitLabCoverage] subgroup bug [#8401](https://github.com/badges/shields/issues/8401)
- implement ruby gems-specific version sort/color functions [#8434](https://github.com/badges/shields/issues/8434)
- Add `rc` to pre-release identifiers [#8435](https://github.com/badges/shields/issues/8435)
- add [GitHub] Number of commits between branches/tags/commits [#8394](https://github.com/badges/shields/issues/8394)
- add [Packagist] dependency version [#8371](https://github.com/badges/shields/issues/8371)
- fix Docker build status invalid response data bug [#8392](https://github.com/badges/shields/issues/8392)
- Dependency updates
## server-2022-09-04
- fix frontend compile for users running on Windows [#8350](https://github.com/badges/shields/issues/8350)

View File

@@ -134,7 +134,7 @@ Prettier before a commit by default.
When adding or changing a service [please write tests][service-tests], and ensure the [title of your Pull Requests follows the required conventions](#running-service-tests-in-pull-requests) to ensure your tests are executed.
When changing other code, please add unit tests.
To run the integration tests, you must have Redis installed and in your PATH.
To run the integration tests, you must have redis installed and in your PATH.
Use `brew install redis`, `yum install redis`, etc. The test runner will
start the server automatically.

View File

@@ -169,8 +169,6 @@ const privateConfigSchema = Joi.object({
jenkins_pass: Joi.string(),
jira_user: Joi.string(),
jira_pass: Joi.string(),
bitbucket_username: Joi.string(),
bitbucket_password: Joi.string(),
bitbucket_server_username: Joi.string(),
bitbucket_server_password: Joi.string(),
librariesio_tokens: Joi.arrayFromString().items(Joi.string()),

3915
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -21,16 +21,15 @@
"url": "https://github.com/badges/shields"
},
"dependencies": {
"@fontsource/lato": "^4.5.10",
"@fontsource/lekton": "^4.5.11",
"@fontsource/lato": "^4.5.9",
"@fontsource/lekton": "^4.5.10",
"@renovate/pep440": "^1.0.0",
"@renovatebot/ruby-semver": "^1.1.6",
"@sentry/node": "^7.15.0",
"@sentry/node": "^7.13.0",
"@shields_io/camp": "^18.1.1",
"badge-maker": "file:badge-maker",
"bytes": "^3.1.2",
"camelcase": "^7.0.0",
"chalk": "^5.1.2",
"chalk": "^5.0.1",
"check-node-version": "^4.2.1",
"cloudflare-middleware": "^1.0.4",
"config": "^3.3.8",
@@ -39,14 +38,14 @@
"decamelize": "^3.2.0",
"emojic": "^1.1.17",
"escape-string-regexp": "^4.0.0",
"fast-xml-parser": "^4.0.11",
"fast-xml-parser": "^4.0.10",
"glob": "^8.0.3",
"global-agent": "^3.0.0",
"got": "^12.5.2",
"got": "^12.4.1",
"graphql": "^15.6.1",
"graphql-tag": "^2.12.6",
"ioredis": "5.2.3",
"joi": "17.6.3",
"joi": "17.6.0",
"joi-extension-semver": "5.0.0",
"js-yaml": "^4.1.0",
"jsonpath": "~1.1.1",
@@ -61,8 +60,8 @@
"prom-client": "^14.1.0",
"qs": "^6.11.0",
"query-string": "^7.1.1",
"semver": "~7.3.8",
"simple-icons": "7.15.0",
"semver": "~7.3.7",
"simple-icons": "7.11.0",
"webextension-store-meta": "^1.0.5",
"xmldom": "~0.6.0",
"xpath": "~0.0.32"
@@ -142,7 +141,7 @@
]
},
"devDependencies": {
"@babel/core": "^7.19.3",
"@babel/core": "^7.19.1",
"@babel/polyfill": "^7.12.1",
"@babel/register": "7.18.9",
"@istanbuljs/schema": "^0.1.3",
@@ -156,7 +155,7 @@
"@types/react-modal": "^3.13.1",
"@types/react-select": "^4.0.17",
"@types/styled-components": "5.1.26",
"@typescript-eslint/eslint-plugin": "^5.40.0",
"@typescript-eslint/eslint-plugin": "^5.37.0",
"@typescript-eslint/parser": "^5.30.7",
"babel-plugin-inline-react-svg": "^2.0.1",
"babel-preset-gatsby": "^2.22.0",
@@ -169,9 +168,9 @@
"child-process-promise": "^2.2.1",
"clipboard-copy": "^4.0.1",
"concurrently": "^7.4.0",
"cypress": "^10.10.0",
"cypress-wait-for-stable-dom": "^0.0.4",
"danger": "^11.1.4",
"cypress": "^10.8.0",
"cypress-wait-for-stable-dom": "^0.0.3",
"danger": "^11.1.2",
"danger-plugin-no-test-shortcuts": "^2.0.0",
"deepmerge": "^4.2.2",
"eslint": "^7.32.0",
@@ -187,17 +186,17 @@
"eslint-plugin-no-extension-in-require": "^0.2.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.2.0",
"eslint-plugin-react": "^7.31.10",
"eslint-plugin-react": "^7.31.8",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-sort-class-members": "^1.15.2",
"fetch-ponyfill": "^7.1.0",
"form-data": "^4.0.0",
"gatsby": "4.23.1",
"gatsby": "4.23.0",
"gatsby-plugin-catch-links": "^4.19.0",
"gatsby-plugin-page-creator": "^4.24.0",
"gatsby-plugin-page-creator": "^4.22.0",
"gatsby-plugin-react-helmet": "^5.22.0",
"gatsby-plugin-remove-trailing-slashes": "^4.9.0",
"gatsby-plugin-styled-components": "^5.24.0",
"gatsby-plugin-styled-components": "^5.19.0",
"gatsby-plugin-typescript": "^4.22.0",
"humanize-string": "^2.1.0",
"icedfrisby": "4.0.0",
@@ -208,16 +207,16 @@
"lint-staged": "^13.0.3",
"lodash.debounce": "^4.0.8",
"lodash.difference": "^4.5.0",
"minimist": "^1.2.7",
"minimist": "^1.2.6",
"mocha": "^9.2.2",
"mocha-env-reporter": "^4.0.0",
"mocha-junit-reporter": "^2.1.0",
"mocha-junit-reporter": "^2.0.2",
"mocha-yaml-loader": "^1.0.3",
"nock": "13.2.9",
"node-mocks-http": "^1.11.0",
"nodemon": "^2.0.20",
"npm-run-all": "^4.1.5",
"open-cli": "^7.1.0",
"open-cli": "^7.0.1",
"portfinder": "^1.0.32",
"prettier": "2.7.1",
"react": "^17.0.2",
@@ -232,14 +231,14 @@
"rimraf": "^3.0.2",
"sazerac": "^2.0.0",
"simple-git-hooks": "^2.8.0",
"sinon": "^14.0.1",
"sinon": "^14.0.0",
"sinon-chai": "^3.7.0",
"snap-shot-it": "^7.9.6",
"start-server-and-test": "1.14.0",
"styled-components": "^5.3.6",
"styled-components": "^5.3.5",
"ts-mocha": "^10.0.0",
"tsd": "^0.24.1",
"typescript": "^4.8.4",
"typescript": "^4.8.3",
"url": "^0.11.0"
},
"engines": {

View File

@@ -20,7 +20,7 @@ t.create('pr-raw (not found)')
t.create('pr-raw (private repo)')
.get('/pr-raw/chris48s/example-private-repo.json')
.expectBadge({ label: 'pull requests', message: 'not found' })
.expectBadge({ label: 'pull requests', message: 'private repo' })
t.create('pr (valid)').get('/pr/atlassian/python-bitbucket.json').expectBadge({
label: 'pull requests',
@@ -33,7 +33,7 @@ t.create('pr (not found)')
t.create('pr (private repo)')
.get('/pr/chris48s/example-private-repo.json')
.expectBadge({ label: 'pull requests', message: 'not found' })
.expectBadge({ label: 'pull requests', message: 'private repo' })
t.create('pr (server)')
.get('/pr/project/repo.json?server=https://bitbucket.mydomain.net')

View File

@@ -35,7 +35,7 @@ export default class CIIBestPracticesService extends BaseJsonService {
pattern: ':metric(level|percentage|summary)/:projectId',
}
static examples = [
static exampless = [
{
title: 'CII Best Practices Level',
pattern: 'level/:projectId',

View File

@@ -23,7 +23,7 @@ function version(version) {
if (first === 'v') {
first = version[1]
}
if (first === '0' || /alpha|beta|snapshot|dev|pre|rc/i.test(version)) {
if (first === '0' || /alpha|beta|snapshot|dev|pre/i.test(version)) {
return 'orange'
} else {
return 'blue'

View File

@@ -88,7 +88,6 @@ describe('Color formatters', function () {
given('6.0-SNAPSHOT'),
given('1.0.1-dev'),
given('2.1.6-prerelease'),
given('2.1.6-RC1'),
]).expect('orange')
expect(() => version(null)).to.throw(

View File

@@ -1,11 +1,66 @@
import { deprecatedService } from '../index.js'
import Joi from 'joi'
import { BaseJsonService } from '../index.js'
import {
IMPROVED_STATUS,
NOT_FOUND_STATUS,
REGRESSED_STATUS,
NO_CHANGE_STATUS,
} from './constants.js'
export default deprecatedService({
category: 'analysis',
route: {
base: 'criterion',
pattern: ':various*',
},
label: 'criterion',
dateAdded: new Date('2022-10-07'),
})
const schema = Joi.string()
.allow(IMPROVED_STATUS, REGRESSED_STATUS, NO_CHANGE_STATUS)
.required()
/**
* Criterion Badge Service
*
* Support and Contact:
* - https://github.com/chmoder/api.criterion.dev
*
* API Documentation:
* - https://app.swaggerhub.com/apis-docs/chmoder/Criterion.dev
*/
export default class Criterion extends BaseJsonService {
static category = 'analysis'
static route = { base: 'criterion', pattern: ':user/:repo' }
static examples = [
{
title: 'Criterion',
namedParams: {
user: 'chmoder',
repo: 'data_vault',
},
staticPreview: this.render({ status: IMPROVED_STATUS }),
},
]
static defaultBadgeData = { label: 'criterion' }
static render({ status }) {
let statusColor = 'lightgrey'
if (status === IMPROVED_STATUS) {
statusColor = 'brightgreen'
} else if (status === NO_CHANGE_STATUS) {
statusColor = 'green'
} else if (statusColor === REGRESSED_STATUS) {
statusColor = 'red'
}
return {
message: `${status}`,
color: statusColor,
}
}
async handle({ user, repo }) {
const status = await this._requestJson({
url: `https://api.criterion.dev/v1/${user}/${repo}/status`,
errorMessages: { 404: NOT_FOUND_STATUS },
schema,
})
return this.constructor.render({ status })
}
}

View File

@@ -1,11 +1,21 @@
import { ServiceTester } from '../tester.js'
import Joi from 'joi'
import { createServiceTester } from '../tester.js'
import {
IMPROVED_STATUS,
REGRESSED_STATUS,
NO_CHANGE_STATUS,
NOT_FOUND_STATUS,
} from './constants.js'
export const t = await createServiceTester()
export const t = new ServiceTester({
id: 'criterion',
title: 'Criterion',
pathPrefix: '/criterion',
})
const isStatus = Joi.string()
.allow(IMPROVED_STATUS, REGRESSED_STATUS, NOT_FOUND_STATUS, NO_CHANGE_STATUS)
.required()
t.create('Criterion')
t.create('Criterion (valid repo)')
.get('/chmoder/credit_card.json')
.expectBadge({ label: 'criterion', message: 'no longer available' })
.expectBadge({ label: 'criterion', message: isStatus })
t.create('Criterion (not found)')
.get('/chmoder/not-a-repo.json')
.expectBadge({ label: 'criterion', message: NOT_FOUND_STATUS })

View File

@@ -4,10 +4,9 @@ import { BaseJsonService, InvalidResponse, NotFound } from '../index.js'
/**
* Validates that the schema response is what we're expecting.
* The username pattern should match the requirements in the freeCodeCamp
* repository.
* The username pattern should match the freeCodeCamp repository.
*
* @see https://github.com/freeCodeCamp/freeCodeCamp/blob/main/utils/validate.js
* @see https://github.com/freeCodeCamp/freeCodeCamp/blob/main/utils/validate.js#L14
*/
const schema = Joi.object({
entities: Joi.object({

View File

@@ -1,25 +0,0 @@
import { valid, maxSatisfying, prerelease } from '@renovatebot/ruby-semver'
function latest(versions) {
// latest Ruby Gems version, including pre-releases
return maxSatisfying(versions, '>0')
}
function versionColor(version) {
if (!valid(version)) {
return 'lightgrey'
}
version = `${version}`
let first = version[0]
if (first === 'v') {
first = version[1]
}
if (first === '0' || prerelease(version)) {
return 'orange'
}
return 'blue'
}
export { latest, versionColor }

View File

@@ -1,17 +0,0 @@
import { test, given } from 'sazerac'
import { latest, versionColor } from './gem-helpers.js'
describe('Gem helpers', function () {
test(latest, () => {
given(['2.0.0', '2.0.0.beta1']).expect('2.0.0')
given(['2.0.0.beta1', '1.9.0']).expect('2.0.0.beta1')
given(['0.0.1', '0.0.2']).expect('0.0.2')
})
test(versionColor, () => {
given('1.9.0').expect('blue')
given('2.0.0.beta1').expect('orange')
given('0.0.1').expect('orange')
given('v1').expect('lightgrey')
})
})

View File

@@ -1,7 +1,12 @@
import Joi from 'joi'
import { createServiceTester } from '../tester.js'
import { isOrdinalNumber, isOrdinalNumberDaily } from '../test-validators.js'
export const t = await createServiceTester()
const isOrdinalNumber = Joi.string().regex(/^[1-9][0-9]+(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ)$/)
const isOrdinalNumberDaily = Joi.string().regex(
/^[1-9][0-9]*(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ) daily$/
)
t.create('total rank (valid)').get('/rt/rspec-puppet-facts.json').expectBadge({
label: 'rank',
message: isOrdinalNumber,

View File

@@ -1,7 +1,6 @@
import Joi from 'joi'
import { renderVersionBadge } from '../version.js'
import { renderVersionBadge, latest } from '../version.js'
import { BaseJsonService } from '../index.js'
import { latest, versionColor } from './gem-helpers.js'
const schema = Joi.object({
// In most cases `version` will be a SemVer but the registry doesn't
@@ -46,7 +45,7 @@ export default class GemVersion extends BaseJsonService {
static defaultBadgeData = { label: 'gem' }
static render({ version }) {
return renderVersionBadge({ version, versionFormatter: versionColor })
return renderVersionBadge({ version })
}
async fetch({ gem }) {

View File

@@ -7,7 +7,7 @@ import { documentation, transformErrors } from './github-helpers.js'
const greenStates = ['SUCCESS']
const redStates = ['ERROR', 'FAILURE']
const blueStates = ['INACTIVE']
const otherStates = ['IN_PROGRESS', 'QUEUED', 'PENDING', 'NO_STATUS', 'WAITING']
const otherStates = ['IN_PROGRESS', 'QUEUED', 'PENDING', 'NO_STATUS']
const stateToMessageMappings = {
IN_PROGRESS: 'in progress',

View File

@@ -21,12 +21,6 @@ describe('GithubDeployments', function () {
message: 'in progress',
color: undefined,
})
given({
state: 'WAITING',
}).expect({
message: 'waiting',
color: undefined,
})
given({
state: 'NO_STATUS',
}).expect({

View File

@@ -1,113 +0,0 @@
import gql from 'graphql-tag'
import Joi from 'joi'
import { metric } from '../text-formatters.js'
import { NotFound } from '../index.js'
import { GithubAuthV4Service } from './github-auth-service.js'
import { documentation as commonDocumentation } from './github-helpers.js'
const schema = Joi.object({
data: Joi.object({
viewer: Joi.object({
gist: Joi.object({
stargazerCount: Joi.number().required(),
url: Joi.string().required(),
owner: Joi.object({
login: Joi.string().required(),
}).required(),
name: Joi.string().required(),
}).allow(null),
}).required(),
}).required(),
}).required()
const documentation = `${commonDocumentation}
<p>This badge shows the number of stargazers for a gist. Gist id is accepted as input and 'gist not found' is returned if the gist is not found for the given gist id.
</p>`
export default class GithubGistStars extends GithubAuthV4Service {
static category = 'social'
static route = {
base: 'github/stars/gists',
pattern: ':gistId',
}
static examples = [
{
title: 'Github Gist stars',
namedParams: { gistId: '47a4d00457a92aa426dbd48a18776322' },
staticPreview: {
label: this.defaultBadgeData.label,
message: metric(29),
style: 'social',
},
documentation,
},
]
static defaultBadgeData = {
label: 'Stars',
color: 'blue',
namedLogo: 'github',
}
static render({ stargazerCount, url, stargazers }) {
return { message: metric(stargazerCount), link: [url, stargazers] }
}
async fetch({ gistId }) {
const data = await this._requestGraphql({
query: gql`
query ($gistId: String!) {
viewer {
gist(name: $gistId) {
stargazerCount
url
name
owner {
login
}
}
}
}
`,
variables: {
gistId,
},
schema,
})
return data
}
static transform({ data }) {
const {
data: {
viewer: { gist },
},
} = data
if (!gist) {
throw new NotFound({ prettyMessage: 'gist not found' })
}
const {
stargazerCount,
url,
name,
owner: { login },
} = gist
const stargazers = `https://gist.github.com/${login}/${name}/stargazers`
return { stargazerCount, url, stargazers }
}
async handle({ gistId }) {
const data = await this.fetch({ gistId })
const { stargazerCount, url, stargazers } =
await this.constructor.transform({
data,
})
return this.constructor.render({ stargazerCount, url, stargazers })
}
}

View File

@@ -1,25 +0,0 @@
import { createServiceTester } from '../tester.js'
import { isMetric } from '../test-validators.js'
export const t = await createServiceTester()
t.create('Gist Total Stars')
.get('/47a4d00457a92aa426dbd48a18776322.json')
.expectBadge({
label: 'Stars',
message: isMetric,
color: 'blue',
link: [
'https://gist.github.com/47a4d00457a92aa426dbd48a18776322',
'https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322/stargazers',
],
})
t.create('Gist Total Stars (Not Found)')
.get('/invalid-gist-id.json')
.expectBadge({
label: 'Stars',
message: 'gist not found',
color: 'red',
link: [],
})

View File

@@ -60,7 +60,7 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi
static category = 'issue-tracking'
static route = {
base: 'github/hacktoberfest',
pattern: ':year(2019|2020|2021|2022)/:user/:repo',
pattern: ':year(2019|2020|2021)/:user/:repo',
queryParamSchema,
}
@@ -68,7 +68,7 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi
{
title: 'GitHub Hacktoberfest combined status',
namedParams: {
year: '2022',
year: '2021',
user: 'snyk',
repo: 'snyk',
},
@@ -82,7 +82,7 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi
{
title: 'GitHub Hacktoberfest combined status (suggestion label override)',
namedParams: {
year: '2022',
year: '2021',
user: 'tmrowco',
repo: 'tmrowapp-contrib',
},
@@ -90,7 +90,7 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi
suggestion_label: 'help wanted',
},
staticPreview: this.render({
year: '2022',
year: '2021',
suggestedIssueCount: 12,
contributionCount: 8,
daysLeft: 15,

View File

@@ -1,13 +0,0 @@
import { redirector } from '../index.js'
export default redirector({
category: 'coverage',
route: {
base: 'gitlab/coverage',
pattern: ':user/:repo/:branch',
},
transformPath: ({ user, repo }) =>
`/gitlab/pipeline-coverage/${user}/${repo}`,
transformQueryParams: ({ branch }) => ({ branch }),
dateAdded: new Date('2022-09-25'),
})

View File

@@ -1,22 +0,0 @@
import { createServiceTester } from '../tester.js'
export const t = await createServiceTester()
t.create('Coverage redirect (with branch)')
.get('/gitlab-org/gitlab-runner/master.json')
.expectRedirect(
'/gitlab/pipeline-coverage/gitlab-org/gitlab-runner.json?branch=master'
)
t.create('Coverage redirect (with branch and job_name)')
.get('/gitlab-org/gitlab-runner/master.json?job_name=test coverage report')
.expectRedirect(
'/gitlab/pipeline-coverage/gitlab-org/gitlab-runner.json?branch=master&job_name=test%20coverage%20report'
)
t.create('Coverage redirect (with branch and gitlab_url)')
.get(
'/gitlab-org/gitlab-runner/master.json?gitlab_url=https://gitlab.gnome.org'
)
.expectRedirect(
'/gitlab/pipeline-coverage/gitlab-org/gitlab-runner.json?branch=master&gitlab_url=https%3a%2f%2fgitlab.gnome.org'
)

View File

@@ -13,7 +13,6 @@ const schema = Joi.object({
const queryParamSchema = Joi.object({
gitlab_url: optionalUrl,
job_name: Joi.string(),
branch: Joi.string(),
}).required()
const moreDocs = `
@@ -38,44 +37,50 @@ Also make sure you have set up code covrage parsing as described <a href="https:
</p>
`
export default class GitlabPipelineCoverage extends BaseSvgScrapingService {
export default class GitlabCoverage extends BaseSvgScrapingService {
static category = 'coverage'
static route = {
base: 'gitlab/pipeline-coverage',
pattern: ':project+',
base: 'gitlab/coverage',
pattern: ':user/:repo/:branch',
queryParamSchema,
}
static examples = [
{
title: 'Gitlab code coverage',
namedParams: { project: 'gitlab-org/gitlab-runner' },
queryParams: { branch: 'master' },
namedParams: {
user: 'gitlab-org',
repo: 'gitlab-runner',
branch: 'master',
},
staticPreview: this.render({ coverage: 67 }),
documentation: documentation + moreDocs,
},
{
title: 'Gitlab code coverage (specific job)',
namedParams: { project: 'gitlab-org/gitlab-runner' },
queryParams: { job_name: 'test coverage report', branch: 'master' },
namedParams: {
user: 'gitlab-org',
repo: 'gitlab-runner',
branch: 'master',
},
queryParams: { job_name: 'test coverage report' },
staticPreview: this.render({ coverage: 96 }),
documentation: documentation + moreDocs,
},
{
title: 'Gitlab code coverage (self-managed)',
namedParams: { project: 'GNOME/at-spi2-core' },
queryParams: { gitlab_url: 'https://gitlab.gnome.org', branch: 'master' },
namedParams: { user: 'GNOME', repo: 'at-spi2-core', branch: 'master' },
queryParams: { gitlab_url: 'https://gitlab.gnome.org' },
staticPreview: this.render({ coverage: 93 }),
documentation: documentation + moreDocs,
},
{
title: 'Gitlab code coverage (self-managed, specific job)',
namedParams: { project: 'GNOME/libhandy' },
namedParams: { user: 'GNOME', repo: 'libhandy', branch: 'master' },
queryParams: {
gitlab_url: 'https://gitlab.gnome.org',
job_name: 'unit-test',
branch: 'master',
},
staticPreview: this.render({ coverage: 93 }),
documentation: documentation + moreDocs,
@@ -91,13 +96,11 @@ export default class GitlabPipelineCoverage extends BaseSvgScrapingService {
}
}
async fetch({ project, baseUrl = 'https://gitlab.com', jobName, branch }) {
async fetch({ user, repo, branch, baseUrl = 'https://gitlab.com', jobName }) {
// Since the URL doesn't return a usable value when an invalid job name is specified,
// it is recommended to not use the query param at all if not required
jobName = jobName ? `?job=${jobName}` : ''
const url = `${baseUrl}/${decodeURIComponent(
project
)}/badges/${branch}/coverage.svg${jobName}`
const url = `${baseUrl}/${user}/${repo}/badges/${branch}/coverage.svg${jobName}`
const errorMessages = errorMessagesFor('project not found')
return this._requestSvg({
schema,
@@ -114,11 +117,12 @@ export default class GitlabPipelineCoverage extends BaseSvgScrapingService {
}
async handle(
{ project },
{ gitlab_url: baseUrl, job_name: jobName, branch }
{ user, repo, branch },
{ gitlab_url: baseUrl, job_name: jobName }
) {
const { message: coverage } = await this.fetch({
project,
user,
repo,
branch,
baseUrl,
jobName,

View File

@@ -3,28 +3,28 @@ import { createServiceTester } from '../tester.js'
export const t = await createServiceTester()
t.create('Coverage (branch)')
.get('/gitlab-org/gitlab-runner.json?branch=12-0-stable')
.get('/gitlab-org/gitlab-runner/12-0-stable.json')
.expectBadge({
label: 'coverage',
message: isIntegerPercentage,
})
t.create('Coverage (existent branch but coverage not set up)')
.get('/gitlab-org/gitlab-git-http-server.json?branch=master')
.get('/gitlab-org/gitlab-git-http-server/master.json')
.expectBadge({
label: 'coverage',
message: 'not set up',
})
t.create('Coverage (nonexistent branch)')
.get('/gitlab-org/gitlab-runner.json?branch=nope-not-a-branch')
.get('/gitlab-org/gitlab-runner/nope-not-a-branch.json')
.expectBadge({
label: 'coverage',
message: 'not set up',
})
t.create('Coverage (nonexistent repo)')
.get('/this-repo/does-not-exist.json')
.get('/this-repo/does-not-exist/neither-branch.json')
.expectBadge({
label: 'coverage',
message: 'inaccessible',
@@ -32,7 +32,7 @@ t.create('Coverage (nonexistent repo)')
t.create('Coverage (custom job)')
.get(
'/gitlab-org/gitlab-runner.json?branch=12-0-stable&job_name=test coverage report'
'/gitlab-org/gitlab-runner/12-0-stable.json?job_name=test coverage report'
)
.expectBadge({
label: 'coverage',
@@ -40,18 +40,14 @@ t.create('Coverage (custom job)')
})
t.create('Coverage (custom invalid job)')
.get(
'/gitlab-org/gitlab-runner.json?branch=12-0-stable&job_name=i dont exist'
)
.get('/gitlab-org/gitlab-runner/12-0-stable.json?job_name=i dont exist')
.expectBadge({
label: 'coverage',
message: 'not set up',
})
t.create('Coverage (custom gitlab URL)')
.get(
'/GNOME/at-spi2-core.json?gitlab_url=https://gitlab.gnome.org&branch=master'
)
.get('/GNOME/at-spi2-core/master.json?gitlab_url=https://gitlab.gnome.org')
.expectBadge({
label: 'coverage',
message: isIntegerPercentage,
@@ -59,7 +55,7 @@ t.create('Coverage (custom gitlab URL)')
t.create('Coverage (custom gitlab URL and job)')
.get(
'/GNOME/libhandy.json?gitlab_url=https://gitlab.gnome.org&branch=master&job_name=unit-test'
'/GNOME/libhandy/master.json?gitlab_url=https://gitlab.gnome.org&job_name=unit-test'
)
.expectBadge({
label: 'coverage',

View File

@@ -1,68 +0,0 @@
import Joi from 'joi'
import { optionalUrl } from '../validators.js'
import { metric } from '../text-formatters.js'
import { documentation, errorMessagesFor } from './gitlab-helper.js'
import GitLabBase from './gitlab-base.js'
/*
We're expecting a response like { "Ruby": 67.13, "JavaScript": 19.66 }
The keys could be anything and {} is a valid response (e.g: for an empty project)
*/
const schema = Joi.object().pattern(/./, Joi.number().min(0).max(100))
const queryParamSchema = Joi.object({
gitlab_url: optionalUrl,
}).required()
export default class GitlabLanguageCount extends GitLabBase {
static category = 'analysis'
static route = {
base: 'gitlab/languages/count',
pattern: ':project+',
queryParamSchema,
}
static examples = [
{
title: 'GitLab language count',
namedParams: {
project: 'gitlab-org/gitlab',
},
queryParams: { gitlab_url: 'https://gitlab.com' },
staticPreview: {
label: 'languages',
message: '5',
},
documentation,
},
]
static defaultBadgeData = { label: 'languages' }
static render({ languagesCount }) {
return {
message: metric(languagesCount),
color: 'blue',
}
}
async fetch({ project, baseUrl }) {
// https://docs.gitlab.com/ee/api/projects.html#languages
return super.fetch({
schema,
url: `${baseUrl}/api/v4/projects/${encodeURIComponent(
project
)}/languages`,
errorMessages: errorMessagesFor('project not found'),
})
}
async handle({ project }, { gitlab_url: baseUrl = 'https://gitlab.com' }) {
const data = await this.fetch({
project,
baseUrl,
})
return this.constructor.render({ languagesCount: Object.keys(data).length })
}
}

View File

@@ -1,25 +0,0 @@
import { isMetric } from '../test-validators.js'
import { createServiceTester } from '../tester.js'
export const t = await createServiceTester()
t.create('language count').get('/gitlab-org/gitlab.json').expectBadge({
label: 'languages',
message: isMetric,
color: 'blue',
})
t.create('language count (self-managed)')
.get('/gitlab-cn/gitlab.json?gitlab_url=https://jihulab.com')
.expectBadge({
label: 'languages',
message: isMetric,
color: 'blue',
})
t.create('language count (project not found)')
.get('/open/guoxudong.io/shields-test/do-not-exist.json')
.expectBadge({
label: 'languages',
message: 'project not found',
})

View File

@@ -23,9 +23,9 @@ t.create('version installs | valid: numeric version')
})
t.create('version installs | valid: alphanumeric version')
.get('/build-failure-analyzer/1.17.2-DRE3.21.json')
.get('/build-failure-analyzer/1.17.2-DRE3.14.json')
.expectBadge({
label: 'installs@1.17.2-DRE3.21',
label: 'installs@1.17.2-DRE3.14',
message: isMetric,
})

View File

@@ -27,7 +27,7 @@ t.create('total downloads (valid)')
})
t.create('total downloads (tenant)')
.get('/vs-devcore.myget/vs-devcore/dt/MicroBuild.json')
.get('/cefsharp.myget/cefsharp/dt/CefSharp.Common.json')
.expectBadge({
label: 'downloads',
message: isMetric,

View File

@@ -1,11 +1,83 @@
import { deprecatedService } from '../index.js'
import Joi from 'joi'
import { starRating, metric } from '../text-formatters.js'
import { colorScale } from '../color-formatters.js'
import { nonNegativeInteger } from '../validators.js'
import { BaseJsonService } from '../index.js'
export default deprecatedService({
category: 'rating',
route: {
const pkgReviewColor = colorScale([2, 3, 4])
const schema = Joi.object({
rating: Joi.number().min(0).max(1).precision(1).required().allow(null),
reviewsCount: nonNegativeInteger,
}).required()
// Repository for this service is: https://github.com/iqubex-technologies/pkgreview.dev
// Internally the service leverages the npms.io API (https://api.npms.io/v2)
export default class PkgreviewRating extends BaseJsonService {
static category = 'rating'
static route = {
base: 'pkgreview',
pattern: ':various*',
},
label: 'pkgreview',
dateAdded: new Date('2022-10-07'),
})
pattern: ':format(rating|stars)/:pkgManager(npm)/:pkgSlug+',
}
static examples = [
{
title: 'pkgreview.dev Package Ratings',
pattern: 'rating/:pkgManager/:pkgSlug+',
namedParams: { pkgManager: 'npm', pkgSlug: 'react' },
staticPreview: this.render({
format: 'rating',
rating: 3.5,
reviewsCount: 237,
}),
},
{
title: 'pkgreview.dev Star Ratings',
pattern: 'stars/:pkgManager/:pkgSlug+',
namedParams: { pkgManager: 'npm', pkgSlug: 'react' },
staticPreview: this.render({
format: 'stars',
rating: 1.5,
reviewsCount: 200,
}),
},
]
static render({ rating, reviewsCount, format }) {
const message =
format === 'rating'
? `${+parseFloat(rating).toFixed(1)}/5 (${metric(reviewsCount)})`
: starRating(rating)
return {
message,
label: format,
color: pkgReviewColor(rating),
}
}
async fetch({ pkgManager, pkgSlug }) {
return this._requestJson({
schema,
url: `https://pkgreview.now.sh/api/v1/${pkgManager}/${encodeURIComponent(
pkgSlug
)}`,
errorMessages: {
404: 'package not found',
},
})
}
async handle({ format, pkgManager, pkgSlug }) {
const { reviewsCount, rating } = await this.fetch({
pkgManager,
pkgSlug,
})
return this.constructor.render({
reviewsCount,
format,
rating: rating * 5,
})
}
}

View File

@@ -1,15 +1,23 @@
import { ServiceTester } from '../tester.js'
import { withRegex, isStarRating } from '../test-validators.js'
import { createServiceTester } from '../tester.js'
export const t = await createServiceTester()
export const t = new ServiceTester({
id: 'pkgreview',
title: 'PkgReview',
pathPrefix: '/pkgreview',
})
const isRatingWithReviews = withRegex(
/^(([0-4](.?([0-9]))?)|5)\/5?\s*\([0-9]*\)$/
)
t.create('Stars Badge')
t.create('Stars Badge renders')
.get('/stars/npm/react.json')
.expectBadge({ label: 'pkgreview', message: 'no longer available' })
.expectBadge({ label: 'stars', message: isStarRating })
t.create('Rating Badge')
t.create('Rating Badge renders')
.get('/rating/npm/react.json')
.expectBadge({ label: 'pkgreview', message: 'no longer available' })
.expectBadge({ label: 'rating', message: isRatingWithReviews })
t.create('nonexistent package')
.get('/rating/npm/ohlolweallknowthispackagewontexist.json')
.expectBadge({
label: 'rating',
message: 'package not found',
color: 'red',
})

View File

@@ -35,7 +35,7 @@ class PowershellGalleryPlatformSupport extends BaseXmlService {
static examples = [
{
title: 'PowerShell Gallery',
namedParams: { packageName: 'PackageManagement' },
namedParams: { packageName: 'DNS.1.1.1.1' },
staticPreview: this.render({
platforms: ['windows', 'macos', 'linux'],
}),

View File

@@ -47,7 +47,7 @@ t.create('version (legacy redirect: vpre)')
.get('/vpre/ACMESharp.svg')
.expectRedirect('/powershellgallery/v/ACMESharp.svg?include_prereleases')
t.create('platform (valid)').get('/p/PackageManagement.json').expectBadge({
t.create('platform (valid').get('/p/DNS.1.1.1.1.json').expectBadge({
label: 'platform',
message: isPlatform,
})

View File

@@ -26,7 +26,7 @@ export default class PubPoints extends BaseJsonService {
keywords,
documentation,
namedParams: { packageName: 'analysis_options' },
staticPreview: this.render({ grantedPoints: 120, maxPoints: 140 }),
staticPreview: this.render({ grantedPoints: 120, maxPoints: 130 }),
},
]

View File

@@ -7,7 +7,7 @@ t.create('pub points (valid)')
.get('/analysis_options.json')
.expectBadge({
label: 'points',
message: Joi.string().regex(/^\d+\/140$/),
message: Joi.string().regex(/^\d+\/130$/),
})
t.create('pub points (not found)').get('/analysisoptions.json').expectBadge({

View File

@@ -62,10 +62,7 @@ t.create('valid repo -- unregistered')
color: COLOR_MAP.unregistered,
})
t.create('invalid repo')
.timeout(15000)
.get('/github.com/repo/invalid-repo.json')
.expectBadge({
label: 'reuse',
message: 'Not a Git repository',
})
t.create('invalid repo').get('/github.com/repo/invalid-repo.json').expectBadge({
label: 'reuse',
message: 'Not a Git repository',
})

View File

@@ -155,15 +155,6 @@ const isCustomCompactTestTotals = makeCompactTestTotalsValidator({
skipped: '🤷',
})
const isOrdinalNumber = Joi.string().regex(/^[1-9][0-9]*(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ)$/)
const isOrdinalNumberDaily = Joi.string().regex(
/^[1-9][0-9]*(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ) daily$/
)
const isHumanized = Joi.string().regex(
/[0-9a-z]+ (second|seconds|minute|minutes|hour|hours|day|days|month|months|year|years)/
)
export {
isSemver,
isVPlusTripleDottedVersion,
@@ -196,7 +187,4 @@ export {
isCustomCompactTestTotals,
makeTestTotalsValidator,
makeCompactTestTotalsValidator,
isOrdinalNumber,
isOrdinalNumberDaily,
isHumanized,
}

View File

@@ -124,11 +124,9 @@ function formatDate(d) {
}
function formatRelativeDate(timestamp) {
const parsedDate = dayjs.unix(parseInt(timestamp, 10))
if (!parsedDate.isValid()) {
return 'invalid date'
}
return dayjs().to(parsedDate).toLowerCase()
return dayjs()
.to(dayjs.unix(parseInt(timestamp, 10)))
.toLowerCase()
}
export {

View File

@@ -153,11 +153,5 @@ describe('Text formatters', function () {
.describe('when given the beginning of october')
.expect('a month ago')
})
test(formatRelativeDate, () => {
given(9999999999999)
.describe('when given invalid date')
.expect('invalid date')
})
})
})

View File

@@ -1,126 +0,0 @@
import Joi from 'joi'
import dayjs from 'dayjs'
import calendar from 'dayjs/plugin/calendar.js'
import duration from 'dayjs/plugin/duration.js'
import relativeTime from 'dayjs/plugin/relativeTime.js'
import { BaseJsonService } from '../index.js'
import { metric as formatMetric, ordinalNumber } from '../text-formatters.js'
dayjs.extend(calendar)
dayjs.extend(duration)
dayjs.extend(relativeTime)
const schema = Joi.object({
Keys: Joi.alternatives(Joi.string(), Joi.number()).required(),
Clicks: Joi.alternatives(Joi.string(), Joi.number()).required(),
UptimeSeconds: Joi.alternatives(Joi.string(), Joi.number()).required(),
Download: Joi.string().required(),
Upload: Joi.string().required(),
Ranks: Joi.object({
Keys: Joi.string().required(),
Clicks: Joi.string().required(),
Download: Joi.string().required(),
Upload: Joi.string().required(),
Uptime: Joi.string().required(),
}),
}).required()
const queryParamSchema = Joi.object({
rank: Joi.equal(''),
}).required()
export default class WhatPulse extends BaseJsonService {
static category = 'activity'
static route = {
base: 'whatpulse',
pattern:
':metric(keys|clicks|uptime|download|upload)/:userType(user|team)/:id',
queryParamSchema,
}
static examples = [
{
title: 'WhatPulse user metric',
namedParams: { metric: 'keys', userType: 'user', id: '179734' },
staticPreview: this.render({
metric: 'keys',
metricValue: '21G',
}),
},
{
title: 'WhatPulse team metric - rank',
namedParams: {
metric: 'upload',
userType: 'team',
id: 'dutch power cows',
},
queryParams: { rank: null },
staticPreview: this.render({
metric: 'upload',
metricValue: '1ˢᵗ',
}),
},
]
static defaultBadgeData = { label: 'whatpulse' }
static render({ metric, metricValue }) {
return {
label: metric,
message: metricValue,
color: 'informational',
}
}
async fetch({ userType, id }) {
return await this._requestJson({
schema,
url: `https://api.whatpulse.org/${userType}.php?${userType}=${id}&format=json`,
})
}
toLowerKeys(obj) {
return Object.keys(obj).reduce((accumulator, key) => {
accumulator[key.toLowerCase()] = obj[key]
return accumulator
}, {})
}
transform({ json, metric }, { rank }) {
// We want to compare with lowercase keys from the WhatPulse's API.
const jsonLowercase = this.toLowerKeys(json)
jsonLowercase.ranks = this.toLowerKeys(json.Ranks)
// Just metric, no rank.
if (rank === undefined) {
if (metric === 'uptime') {
return dayjs.duration(jsonLowercase.uptimeseconds, 'seconds').humanize()
}
let metricValue
metricValue = jsonLowercase[metric]
if (metric === 'keys' || metric === 'clicks') {
metricValue = formatMetric(metricValue)
}
if (metric === 'upload' || metric === 'download') {
metricValue = metricValue.replace(/([A-Za-z]+)/, ' $1')
}
return metricValue
}
// Rank achieved by the user/team with the given metric.
const rankFromResp = jsonLowercase.ranks[metric]
return ordinalNumber(rankFromResp)
}
async handle({ metric, userType, id }, { rank }) {
const json = await this.fetch({ userType, id, metric })
const metricValue = this.transform({ json, metric }, { rank })
return this.constructor.render({ metric, metricValue })
}
}

View File

@@ -1,42 +0,0 @@
import { createServiceTester } from '../tester.js'
import {
isFileSize,
isHumanized,
isMetric,
isOrdinalNumber,
} from '../test-validators.js'
export const t = await createServiceTester()
t.create('WhatPulse user as user id, uptime')
.get('/uptime/user/179734.json')
.expectBadge({ label: 'uptime', message: isHumanized })
t.create('WhatPulse user as user name, keys')
.get('/keys/user/jerone.json')
.expectBadge({ label: 'keys', message: isMetric })
t.create('WhatPulse team as team id, clicks')
.get('/clicks/team/1295.json')
.expectBadge({ label: 'clicks', message: isMetric })
t.create('WhatPulse team as team id, download')
.get('/download/team/1295.json')
.expectBadge({ label: 'download', message: isFileSize })
t.create('WhatPulse team as team id, upload')
.get('/upload/team/1295.json')
.expectBadge({ label: 'upload', message: isFileSize })
t.create('WhatPulse team as team name, keys - from Ranks')
.get('/keys/team/dutch power cows.json?rank')
.expectBadge({ label: 'keys', message: isOrdinalNumber })
t.create(
'WhatPulse invalid metric name (not one of the options from the modal`s dropdown)'
)
.get('/UpTIMe/user/jerone.json')
.expectBadge({ label: '404', message: 'badge not found' })
t.create('WhatPulse incorrect user name')
.get('/uptime/user/NonExistentUsername.json')
.expectBadge({ label: 'whatpulse', message: 'invalid response data' })

View File

@@ -190,22 +190,6 @@ t.create('Plugin Required PHP Version')
t.create('Plugin Required PHP Version (Not Set)')
.get('/plugin/required-php/akismet.json')
.intercept(nock =>
nock('https://api.wordpress.org')
.get('/plugins/info/1.2/')
.query(mockedQuerySelector)
.reply(200, {
version: '1.2',
rating: 80,
num_ratings: 100,
downloaded: 100,
active_installs: 100,
requires: false,
tested: '4.0.0',
last_updated: '2020-01-01 7:21am GMT',
requires_php: false,
})
)
.expectBadge({
label: 'php',
message: 'not set for this plugin',