Commit Graph

11 Commits

Author SHA1 Message Date
Paul Melnikow
db4bffb300 Split BaseService and BaseJsonService into separate modules (#1889)
There’s a lot of behavior here, and going to be even more, so I think it makes sense to split these up as I’ve done with the tests.
2018-08-11 10:43:05 -04:00
chris48s
f05a3496ee Validate response json in [apm appveyor cdnjs clojars gem] (#1883)
* split gem service into multiple files
* add validation to apm, appveyor, cdnjs, clojars & gem services
* fix the apm examples
2018-08-10 20:52:09 +01:00
Paul Melnikow
7a664ca3e8 Run prettier (#1866)
Merging this separately so the commit with the tooling change is readable. This is a follow-on to #1167 which turned prettier on.
2018-08-08 17:57:14 -04:00
Paul Melnikow
e3b100504d Add Joi-based request validation to BaseJsonService and rewrite [NPM] and [node] badges (#1743)
When JSON responses come back, they are sometimes not in the format expected by the API. As a result we have a lot of defensive coding (expressions like `(data || {}).someProperty`) to avoid exceptions being thrown in badge processing. Often we rely on the `try` blocks that wrap so much of the badge-processing code, which catch all JavaScript exceptions and return some error result, usually **invalid**. The problem with this is that these `try` blocks catch all sorts of programmer errors too, so when we see **invalid** we don't know whether the API returned something unexpected, or we've made a mistake. We also spend a lot of time writing defensive tests around malformed responses, and creating and maintaining the defensive coding.

A better solution is to validate the API responses using declarative contracts. Here the programmer says exactly what they expect from the API. That way, if the response isn't what we expect we can just say it's an **invalid json response**. And if our code then throws an exception, well that's our mistake; when we catch that we can call it a **shields internal error**. It's also less code and less error-prone. Over time we may be confident enough in the contracts that we won't need so many tests of malformed responses. The contract doesn't need to describe the entire response, only the part that's needed. Unknown keys can simply be dropped, preventing unvalidated parts of the response from creeping into the code. Checking what's in our response before calling values on it also makes our code more secure.

I used Joi here, since we're already using it for testing. There may be another contracts library that's a better fit, though I think we could look at that later.

Those changes are in base.js.

The rest is a rewrite of the remaining NPM badges, including the extraction of an NpmBase class. Inspired by @chris48s's work in #1740, this class splits the service concerns into fetching, validation, transformation, and rendering. This is treated as a design pattern. See the PR discussion for more. There are two URL patterns, one which allows specifying a tag (used by e.g. the version badge `https://img.shields.io/npm/v/npm/next.svg`), and the other which does not accept a tag (e.g. the license badge `https://img.shields.io/npm/l/express.svg`). Subclasses like NpmLicense and NpmTypeDefinitions can specify the URL fragment, examples, the validation schema for the chunk of the package data they use, and a render function. The NpmVersion subclass uses a different endpoint, so it overrides the `handle` implementation from NpmBase.

The remaining services using BaseJsonService are shimmed, so they will keep working after the changes.
2018-08-08 17:08:16 -04:00
Paul Melnikow
7e04f25fc5 Tweak layout of services to conveniently handle large service families 2018-08-01 16:49:07 -04:00
chris48s
d572abff4f re-organise badge examples (#1800)
Re-organise badge examples into categories:

- Build
- Chat
- Dependencies
- Downloads
- Funding
- Issue Tracking
- License
- Rating
- Social
- Version
- Other
2018-07-23 19:36:24 -05:00
Paul Melnikow
6e09a93cf0 Provide a descriptive message when json can’t be parsed (#1796)
* Test handling of invalid JSON on BaseJsonService
* Remove invalidJSON tests from new-style services
2018-07-23 19:35:42 -05:00
chris48s
f78e6f1f8a [gem cdnjs appveyor clojars] refactor clojars, establish BaseJsonService (#1702)
* refactor clojars integration

* DRY up services that request data from JSON endpoints
2018-06-16 20:50:14 +01:00
chris48s
bf53e612f5 [cdnjs gem] make exception classes more consistent (#1683)
make exception classes more consistent
2018-05-15 18:57:33 +01:00
chris48s
b5635bf55a [gem cdnjs appveyor] refactor ruby gems service (#1680)
* allow services to export >1 classes

This change to loadServiceClasses() allows us to define
services which either export a single service class e.g:

module.exports = class Cdnjs extends BaseService {
  //...
}

or more than one. e.g:

module.exports = {
  GemVersion,
  GemDownloads,
  GemOwner,
  GemRank,
}

* refactor ruby gem badges

- move badge code to service classes
- throw exceptions for errors
- use let and const
- change tests to expect 'downloads' label for error badges
- general tidying

* fix typo in tests

* Don't always use class name in example label

This allows (for example) GemVersion and GemDownloads
both to use the example label 'Gem'
2018-05-10 17:32:45 +01:00
Paul Melnikow
ea4b758612 Move service tests alongside code (#1563)
Per discussion in #1543
2018-03-20 18:32:48 -07:00