Skip to content

Commit c1c784f

Browse files
Merge pull request #173 from node-strava/drop-sinon
chore: drop sinon as devDep: all mocks are now through nock.
2 parents edda7ea + c005ba6 commit c1c784f

32 files changed

+2553
-1771
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Test Suite
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
12+
strategy:
13+
matrix:
14+
node-version: [20.x, 22.x]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Use Node.js ${{ matrix.node-version }}
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: ${{ matrix.node-version }}
23+
cache: yarn
24+
25+
- name: Install dependencies
26+
run: yarn install --frozen-lockfile
27+
28+
- name: Run test suite
29+
run: yarn test

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ Example usage:
138138

139139
```js
140140
var strava = require('strava-v3');
141-
strava.athletes.get({id:12345},function(err,payload,limits) {
141+
strava.athlete.get({id:12345},function(err,payload,limits) {
142142
//do something with your payload, track rate limits
143143
});
144144
```
@@ -256,26 +256,22 @@ See Strava API docs for returned data structures.
256256
* `strava.athlete.get(args,done)`
257257
* `strava.athlete.update(args,done)` // only 'weight' can be updated.
258258
* `strava.athlete.listActivities(args,done)` *Get list of activity summaries*
259-
* `strava.athlete.listRoutes(args,done)`
260259
* `strava.athlete.listClubs(args,done)`
261260
* `strava.athlete.listZones(args,done)`
262261

263262
#### Athletes
264263

265-
* `strava.athletes.get(args,done)` *Get a single activity. args.id is required*
266264
* `strava.athletes.stats(args,done)`
267265

268266
#### Activities
269267

270268
* `strava.activities.get(args,done)`
271269
* `strava.activities.create(args,done)`
272270
* `strava.activities.update(args,done)`
273-
* `strava.activities.listFriends(args,done)` -> deprecated at 2.2.0
274271
* `strava.activities.listZones(args,done)`
275272
* `strava.activities.listLaps(args,done)`
276273
* `strava.activities.listComments(args,done)`
277274
* `strava.activities.listKudos(args,done)`
278-
* `strava.activities.listPhotos(args,done)` -> deprecated at 2.2.0
279275

280276
#### Clubs
281277

@@ -380,14 +376,16 @@ This update maintains feature parity with the previous implementation of `reques
380376
## Development
381377

382378
This package includes a full test suite runnable via `yarn test`.
383-
It will both lint and run shallow tests on API endpoints.
379+
It will both lint and run tests on API endpoints.
384380

385381
### Running the tests
386382

387-
You'll first need to supply `data/strava_config` with an `access_token` that
383+
Many unit tests now use nock to mock the Strava API and can run without any real credentials.
384+
However, some integration-style tests still expect a real token and account data.
385+
386+
If you want to run the full test suite (including integration tests), you'll need to supply `data/strava_config` with an `access_token` that
388387
has both private read and write permissions. Look in `./scripts` for a tool
389-
to help generate this token. Going forward we plan to more testing with a mocked
390-
version of the Strava API so testing with real account credentials are not required.
388+
to help generate this token.
391389

392390
* Make sure you've filled out all the fields in `data/strava_config`.
393391
* Use `strava.oauth.getRequestAccessURL({scope:"view_private,write"})` to generate the request url and query it via your browser.
@@ -408,15 +406,17 @@ data in the account:
408406
* Must have created at least one route
409407
* Most recent activity with an achievement should also contain a segment
410408

411-
(Contributions to make the test suite more self-contained and robust by converting more tests
412-
to use `nock` are welcome!)
409+
(Parts of the test suite already use `nock` to mock the API. Contributions to convert remaining integration tests to mocks are welcome.)
413410

414-
* You're done! Paste the new `access_token` to `data/strava_config` and go run some tests:
411+
You're done! Paste the new `access_token` to `data/strava_config` and run the full tests:
415412

416413
`yarn test`.
417414

418415
### How the tests work
419416

417+
- Tests use Mocha and Should.js.
418+
- HTTP interaction is performed with Axios; tests that mock HTTP use `nock`.
419+
420420
Using the provided `access_token` tests will access each endpoint individually:
421421

422422
* (For all `GET` endpoints) checks to ensure the correct type has been returned from the Strava.

axiosUtility.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const httpRequest = async (options) => {
4747
data: options.body, // For request body
4848
responseType: options.responseType || 'json', // Support different response types
4949
maxRedirects: options.maxRedirects || 5, // Set max redirects
50-
validateStatus: options.simple === false ? () => true : undefined // Handle 'simple' option
50+
validateStatus: options.simple === false ? () => true : (status) => status >= 200 && status < 300 // Handle 'simple' option
5151
})
5252
return response.data
5353
} catch (error) {

index.d.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,6 @@ export interface GearRoutes {
100100
get(args: any, done?: Callback): Promise<any>;
101101
}
102102

103-
export interface RunningRacesRoutes {
104-
get(args: any, done?: Callback): Promise<any>;
105-
listRaces(args: any, done?: Callback): Promise<any>;
106-
}
107-
108103
export interface ClubsRoutes {
109104
get(args: ClubsRoutesArgs, done?: Callback): Promise<any>;
110105
listMembers(args: ClubsRoutesListArgs, done?: Callback): Promise<any>;
@@ -350,7 +345,6 @@ export interface Strava {
350345
streams: StreamsRoutes;
351346
uploads: UploadsRoutes;
352347
rateLimiting: RateLimiting;
353-
runningRaces: RunningRacesRoutes;
354348
routes: RoutesRoutes;
355349
oauth: OAuthRoutes;
356350
}

index.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const SegmentEfforts = require('./lib/segmentEfforts')
1212
const Streams = require('./lib/streams')
1313
const Uploads = require('./lib/uploads')
1414
const rateLimiting = require('./lib/rateLimiting')
15-
const RunningRaces = require('./lib/runningRaces')
1615
const Routes = require('./lib/routes')
1716
const PushSubscriptions = require('./lib/pushSubscriptions')
1817
const { axiosInstance, httpRequest } = require('./axiosUtility')
@@ -49,7 +48,6 @@ strava.client = function (token, request = httpRequest) {
4948
this.streams = new Streams(httpClient)
5049
this.uploads = new Uploads(httpClient)
5150
this.rateLimiting = rateLimiting
52-
this.runningRaces = new RunningRaces(httpClient)
5351
this.routes = new Routes(httpClient)
5452
// No Push subscriptions on the client object because they don't use OAuth.
5553
}
@@ -77,7 +75,6 @@ strava.segmentEfforts = new SegmentEfforts(strava.defaultHttpClient)
7775
strava.streams = new Streams(strava.defaultHttpClient)
7876
strava.uploads = new Uploads(strava.defaultHttpClient)
7977
strava.rateLimiting = rateLimiting
80-
strava.runningRaces = new RunningRaces(strava.defaultHttpClient)
8178
strava.routes = new Routes(strava.defaultHttpClient)
8279
strava.pushSubscriptions = new PushSubscriptions(strava.defaultHttpClient)
8380

lib/athlete.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ athlete.prototype.listActivities = async function (args) {
2828
athlete.prototype.listClubs = async function (args) {
2929
return await this._listHelper('clubs', args)
3030
}
31-
athlete.prototype.listRoutes = async function (args) {
32-
return await this._listHelper('routes', args)
33-
}
3431
athlete.prototype.listZones = async function (args) {
3532
return await this._listHelper('zones', args)
3633
}

lib/athletes.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ var athletes = function (client) {
33
}
44

55
//= ==== athletes endpoint =====
6-
athletes.prototype.get = function (args, done) {
7-
return this._listHelper('', args, done)
8-
}
96
athletes.prototype.stats = function (args, done) {
107
return this._listHelper('stats', args, done)
118
}

lib/httpClient.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,18 @@ HttpClient.prototype._requestHelper = async function (options) {
188188
}
189189

190190
if (typeof response === 'string') {
191-
// parse the raw JSON string with big-integer reviver for 16+ digit numbers
192-
return JSON.parse(response, (key, value) => {
193-
if (options.responseType === 'json' || options.responseType === 'formdata') {
194-
return JSON.parse(response, (key, value) => {
195-
if (typeof value === 'string' && /^\d{16,}$/.test(value)) {
196-
return JSONbig.parse(value)
197-
}
198-
return value
199-
})
200-
} else {
201-
return response
202-
}
203-
})
191+
// If responseType is 'text', return the raw string
192+
if (options.responseType === 'text') {
193+
return response
194+
}
195+
196+
// For json or formdata, parse the raw JSON string with big-integer reviver for 16+ digit numbers
197+
if (options.responseType === 'json' || options.responseType === 'formdata') {
198+
return JSONbig.parse(response)
199+
}
200+
201+
// Default: return as-is
202+
return response
204203
}
205204

206205
// response is not a string or object return it

lib/runningRaces.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

lib/streams.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ var streams = function (client) {
33
}
44

55
var _qsAllowedProps = [
6+
'keys',
7+
'key_by_type',
8+
'original_size',
69
'resolution',
710
'series_type'
811
]
@@ -31,18 +34,14 @@ streams.prototype.route = function (args, done) {
3134

3235
//= ==== helpers =====
3336
streams.prototype._typeHelper = function (endpoint, args, done) {
34-
var qs = this.client.getQS(_qsAllowedProps, args)
35-
3637
// require id
3738
if (typeof args.id === 'undefined') {
3839
throw new Error('args must include an id')
3940
}
40-
// require types
41-
if (typeof args.types === 'undefined') {
42-
throw new Error('args must include types')
43-
}
4441

45-
endpoint += '/' + args.id + '/streams/' + args.types + '?' + qs
42+
const qs = this.client.getQS(_qsAllowedProps, args)
43+
44+
endpoint += '/' + args.id + '/streams' + '?' + qs
4645
return this.client.getEndpoint(endpoint, args, done)
4746
}
4847
//= ==== helpers =====

0 commit comments

Comments
 (0)