Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
### 3.0.0 (Next)

* [#93](https://github.com/dblock/strava-ruby-client/pull/93): Updates GitHub Actions workflows - [@simonneutert](https://github.com/simonneutert).
* [#94](https://github.com/dblock/strava-ruby-client/pull/94): Adds video fields to `Strava::Models::Photo` - [@dblock](https://github.com/dblock).
* [#92](https://github.com/dblock/strava-ruby-client/pull/92): Fixes `Hashie::Trash` serialization warning for `object_id` of `Strava::Webhooks::Models::Event` - [@simonneutert](https://github.com/simonneutert).
* [#93](https://github.com/dblock/strava-ruby-client/pull/93): Updates GitHub Actions workflows - [@simonneutert](https://github.com/simonneutert).
* Your contribution here.

### 2.3.0 (2025/10/16)
Expand Down
19 changes: 19 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ bundle exec rake

## Contribute Code

### Obtain a Strava Token

The token from the Strava website does not have enough permissions to retrieve your own activities.
Use the [strava-oauth-token tool](#strava-oauth-token) to obtain a short lived with more access scopes.

Obtain `STRAVA_CLIENT_ID` and `STRAVA_CLIENT_SECRET` from [My API Application](https://www.strava.com/settings/api).

```bash
export STRAVA_CLIENT_ID=...
export STRAVA_CLIENT_SECRET=...
bundle exec ruby bin/strava-oauth-token
```

This will open a browser window. Complete the OAuth workflow and note `access_token`.

```
export STRAVA_ACCESS_TOKEN=...
```

### Create a Topic Branch

Make sure your fork is up-to-date and create a topic branch for your feature or bug fix.
Expand Down
8 changes: 8 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

### Upgrading to >= 3.0.0

#### Removed `id` from `Strava::Models::Photo`

The Strava Photos API returns `unique_id` and does not return `id`. The latter has been removed.

See [#94](https://github.com/dblock/strava-ruby-client/pull/94) for details.

#### Renamed `object_id` to `id` in `Strava::Webhooks::Models::Event`

The `Strava::Webhooks::Models::Event` model has been refactored to map the `object_id` field to `id` for consistency and to resolve `Hashie::Trash` serialization warnings.

**Breaking Change**: If you're using webhooks and accessing the `object_id` property, you must now use `id` instead.
Expand Down
15 changes: 11 additions & 4 deletions lib/strava/models/photo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,27 @@
module Strava
module Models
class Photo < Strava::Models::Response
property 'id'
property 'unique_id'
property 'urls'
property 'source'
property 'athlete_id'
property 'activity_id'
property 'activity_name'
property 'post_id'
property 'resource_state'
property 'caption'
property 'type'
property 'source'
property 'status'
property 'uploaded_at', transform_with: ->(v) { Time.parse(v) }
property 'created_at', transform_with: ->(v) { Time.parse(v) }
property 'created_at_local', transform_with: ->(v) { Time.parse(v) }
property 'uploaded_at', transform_with: ->(v) { Time.parse(v) }
property 'urls'
property 'placeholder_image'
property 'sizes'
property 'default_photo'
property 'cursor'
property 'duration'
property 'video_url'
property 'location'
end
end
end
131 changes: 29 additions & 102 deletions spec/fixtures/strava/client/activity_photos.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 57 additions & 21 deletions spec/strava/api/client/endpoints/activities/activity_photos_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,66 @@

RSpec.describe 'Strava::Api::Client#activity_photos', vcr: { cassette_name: 'client/activity_photos' } do
include_context 'with API client'
it 'returns activity photos' do
activity_photos = client.activity_photos(id: 7_287_327_028)
expect(activity_photos).to be_a Enumerable
expect(activity_photos.count).to eq 2
activity_photo = activity_photos.first
expect(activity_photo.id).to be_nil
expect(activity_photo.unique_id).to eq 'f5ebd6e7-8c87-4478-86ce-ce5cf31cf519'
expect(activity_photo.urls).to eq('5000' => 'https://dgtzuqphqg23d.cloudfront.net/3wt2DyGHKHX6gJSXzpAcVdEI1QE2luP9xoDLD0CX2w4-2048x1536.jpg')
expect(activity_photo.source).to eq 1
expect(activity_photo.athlete_id).to eq 24_776_507
expect(activity_photo.activity_id).to eq 7_287_327_028
expect(activity_photo.activity_name).to eq 'Die Rückkehr der Cornichons! 🥒'
expect(activity_photo.resource_state).to eq 2
expect(activity_photo.caption).to eq ''
expect(activity_photo.created_at).to be_a Time
expect(activity_photo.created_at_local).to be_a Time
expect(activity_photo.uploaded_at).to be_a Time
expect(activity_photo.sizes).to eq('5000' => [2048, 1536])
expect(activity_photo.default_photo).to be true

context 'with activity photos' do
let(:activity_photos) { client.activity_photos(id: 16_181_809_559) }

it 'returns activity photos' do
expect(activity_photos).to be_a Enumerable
expect(activity_photos.count).to eq 4
end

context 'when photo' do
let(:activity_photo) { activity_photos.first }

it 'returns all fields' do
expect(activity_photo.unique_id).to eq '6D1E4A0B-0A46-406A-874A-C3ED694DDE55'
expect(activity_photo.urls).to eq('5000' => 'https://dgtzuqphqg23d.cloudfront.net/gskSZVRgkpQ-O9HOdMXpYLEfDvRkZBNs_hGKBKbsmds-1536x2048.jpg')
expect(activity_photo.source).to eq 1
expect(activity_photo.status).to eq 3
expect(activity_photo.cursor).to be_nil
expect(activity_photo.athlete_id).to eq 26_462_176
expect(activity_photo.activity_id).to eq 16_181_809_559
expect(activity_photo.activity_name).to eq 'Run with Artyom'
expect(activity_photo.resource_state).to eq 2
expect(activity_photo.caption).to eq ''
expect(activity_photo.created_at).to be_a Time
expect(activity_photo.created_at_local).to be_a Time
expect(activity_photo.uploaded_at).to be_a Time
expect(activity_photo.sizes).to eq('5000' => [1536, 2048])
expect(activity_photo.default_photo).to be true
end
end

context 'when video' do
let(:activity_video) { activity_photos[3] }

it 'returns all fields' do
expect(activity_video.unique_id).to eq '077BE6E7-DDA8-4F38-BB4A-DF0F4640C2D5'
expect(activity_video.urls).to eq('5000' => 'https://d35tn3x5zm6xrc.cloudfront.net/LEpTlUieI8wxuKwsdTd_CAHz0i2BccppnSXEfVV5_p4/thumbnails/LEpTlUieI8wxuKwsdTd_CAHz0i2BccppnSXEfVV5_p4_1080x1920.jpg')
expect(activity_video.source).to eq 1
expect(activity_video.status).to eq 3
expect(activity_video.cursor).to be_nil
expect(activity_video.athlete_id).to eq 26_462_176
expect(activity_video.activity_id).to eq 16_181_809_559
expect(activity_video.activity_name).to eq 'Run with Artyom'
expect(activity_video.resource_state).to eq 2
expect(activity_video.caption).to eq ''
expect(activity_video.created_at).to be_a Time
expect(activity_video.created_at_local).to be_a Time
expect(activity_video.uploaded_at).to be_a Time
expect(activity_video.sizes).to eq('5000' => [1080, 1920])
expect(activity_video.default_photo).to be false
expect(activity_video.video_url).to eq 'https://d35tn3x5zm6xrc.cloudfront.net/LEpTlUieI8wxuKwsdTd_CAHz0i2BccppnSXEfVV5_p4/hls/LEpTlUieI8wxuKwsdTd_CAHz0i2BccppnSXEfVV5_p4.m3u8'
expect(activity_video.duration).to eq 4
expect(activity_video.location).to eq([40.7557, -73.9966])
end
end
end

it 'returns activity photos by id' do
activity_photos = client.activity_photos(3_958_491_750)
activity_photos = client.activity_photos(16_181_809_559)
expect(activity_photos).to be_a Enumerable
expect(activity_photos.count).to eq 1
expect(activity_photos.count).to eq 4
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@
expect(photos.count).to eq 1
photo = photos.primary
expect(photo).to be_a Strava::Models::Photo
expect(photo.id).to be_nil
expect(photo.unique_id).to eq 'F775717B-D1C1-443A-AD99-3D9A80FF11C9'
expect(photo.urls).to eq(
'100' => 'https://dgtzuqphqg23d.cloudfront.net/BO0H-YeNRZOfFhc0PctUheAKchsY2ll4vsagU58MNKg-128x96.jpg',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,6 @@
expect(photos.count).to eq 9
photo = photos.primary
expect(photo).to be_a Strava::Models::Photo
expect(photo.id).to be_nil
expect(photo.unique_id).to eq '5e8006d0-8349-40ad-a4ef-72b5e6e82dfe'
expect(photo.urls).to eq(
'100' => 'https://dgtzuqphqg23d.cloudfront.net/mo8thQ4Z5qAylUaRZHOWAR1sp16Bo-pp0ggYQKSWiZE-90x128.jpg',
Expand Down
2 changes: 1 addition & 1 deletion spec/strava/webhooks/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
end

context 'with a client id and secret' do
let(:client) { described_class.new(client_id: ENV.fetch('STRAVA_CLIENT_ID', '24523'), client_secret: ENV.fetch('STRAVA_CLIENT_SECRET', 'client-secret')) }
let(:client) { described_class.new(client_id: '24523', client_secret: 'client-secret') }

describe '#push_subscriptions' do
it 'gets an empty set of push subscriptions', vcr: { cassette_name: 'webhooks/no_push_subscriptions' } do
Expand Down
2 changes: 1 addition & 1 deletion spec/support/vcr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
VCR.configure do |config|
config.cassette_library_dir = 'spec/fixtures/strava'
config.hook_into :webmock
# config.default_cassette_options = { record: :new_episodes }
config.default_cassette_options = { record: :new_episodes }
config.configure_rspec_metadata!
config.before_record do |i|
i.request.headers['Authorization'] = ['Bearer access-token'] if ENV.key?('STRAVA_ACCESS_TOKEN')
Expand Down