hackatime/spec/requests/api/admin/v1/admin_timeline_spec.rb
Tom (Deployor) 8d0215ff0f
feat: added actual api docs (rswag) + ci enforcement (#846)
* feat: add API documentation and CI checks

- Add Rswag for automated API documentation generation
- Add Swagger specs for all endpoints
- Add CI step to enforce that swagger.yaml stays in sync with code
- Add static test keys in seeds.rb for easier testing
- Update AGENTS.md and README.md to support this

* Merge branch 'main' of https://github.com/deployor/hackatime

* Merge branch 'main' into main

* Deprecations! Yay! :)

* It was wan addicent i swear linter! Dont hurt me

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Copilot..... we love you! Also this project is open and so are api docs meant to be if another AI reads ts!

* Merge branch 'main' of https://github.com/deployor/hackatime

* Merge branch 'main' into main

* Merge branch 'main' into main

* Update app/controllers/api/admin/v1/admin_controller.rb

If you say so

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update spec/requests/api/v1/my_spec.rb

I guessss?

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Failed my own CI wow.... EMBARRASSINGGGG

* Merge branch 'main' into main

* Merge branch 'main' into main

* clarify wording on internal/revoke

* Merge branch 'main' into main

* update swagger docs
2026-01-27 01:05:49 -05:00

221 lines
8.3 KiB
Ruby

require 'swagger_helper'
RSpec.describe 'Admin::Timeline', type: :request do
path '/api/admin/v1/timeline' do
get('Get timeline') do
tags 'Admin Timeline'
description 'Get timeline events including coding activity and commits for selected users.'
security [ AdminToken: [] ]
produces 'application/json'
parameter name: :date, in: :query, type: :string, format: :date, description: 'Date for the timeline (YYYY-MM-DD)'
parameter name: :user_ids, in: :query, type: :string, description: 'Comma-separated list of User IDs'
parameter name: :slack_uids, in: :query, type: :string, description: 'Comma-separated list of Slack User IDs'
response(200, 'successful') do
schema type: :object,
properties: {
date: { type: :string, format: :date },
next_date: { type: :string, format: :date },
prev_date: { type: :string, format: :date },
users: {
type: :array,
items: {
type: :object,
properties: {
user: {
type: :object,
properties: {
id: { type: :integer },
username: { type: :string },
display_name: { type: :string, nullable: true },
slack_username: { type: :string, nullable: true },
github_username: { type: :string, nullable: true },
timezone: { type: :string, nullable: true },
avatar_url: { type: :string, nullable: true }
}
},
spans: {
type: :array,
items: {
type: :object,
properties: {
start_time: { type: :number, format: :float },
end_time: { type: :number, format: :float },
duration: { type: :number, format: :float },
files_edited: { type: :array, items: { type: :string } },
projects_edited_details: {
type: :array,
items: {
type: :object,
properties: {
name: { type: :string },
repo_url: { type: :string, nullable: true }
}
}
},
editors: { type: :array, items: { type: :string } },
languages: { type: :array, items: { type: :string } }
}
}
},
total_coded_time: { type: :number, format: :float }
}
}
},
commit_markers: {
type: :array,
items: {
type: :object,
properties: {
user_id: { type: :integer },
timestamp: { type: :number, format: :float },
additions: { type: :integer, nullable: true },
deletions: { type: :integer, nullable: true },
github_url: { type: :string, nullable: true }
}
}
}
}
let(:Authorization) { "Bearer dev-admin-api-key-12345" }
let(:date) { Time.current.to_date.to_s }
let(:user_ids) { User.first&.id.to_s }
let(:slack_uids) { nil }
schema type: :object,
properties: {
date: { type: :string, format: :date },
next_date: { type: :string, format: :date },
prev_date: { type: :string, format: :date },
users: {
type: :array,
items: {
type: :object,
properties: {
user: {
type: :object,
properties: {
id: { type: :integer },
username: { type: :string },
display_name: { type: :string, nullable: true },
slack_username: { type: :string, nullable: true },
github_username: { type: :string, nullable: true },
timezone: { type: :string, nullable: true },
avatar_url: { type: :string, nullable: true }
}
},
spans: {
type: :array,
items: {
type: :object,
properties: {
start_time: { type: :number, format: :float },
end_time: { type: :number, format: :float },
duration: { type: :number, format: :float },
files_edited: { type: :array, items: { type: :string } },
projects_edited_details: {
type: :array,
items: {
type: :object,
properties: {
name: { type: :string },
repo_url: { type: :string, nullable: true }
}
}
},
editors: { type: :array, items: { type: :string } },
languages: { type: :array, items: { type: :string } }
}
}
},
total_coded_time: { type: :number, format: :float }
}
}
},
commit_markers: {
type: :array,
items: {
type: :object,
properties: {
user_id: { type: :integer },
timestamp: { type: :number, format: :float },
additions: { type: :integer, nullable: true },
deletions: { type: :integer, nullable: true },
github_url: { type: :string, nullable: true }
}
}
}
}
run_test!
end
end
end
path '/api/admin/v1/timeline/search_users' do
get('Search timeline users') do
tags 'Admin Timeline'
description 'Search users specifically for the timeline view by username, slack username, ID, or email.'
security [ AdminToken: [] ]
produces 'application/json'
parameter name: :query, in: :query, type: :string, description: 'Search query'
response(200, 'successful') do
let(:Authorization) { "Bearer dev-admin-api-key-12345" }
let(:query) { User.first&.username || 'admin' }
schema type: :object,
properties: {
users: {
type: :array,
items: {
type: :object,
properties: {
id: { type: :integer },
display_name: { type: :string, nullable: true },
avatar_url: { type: :string, nullable: true }
}
}
}
}
run_test!
end
response(422, 'unprocessable entity') do
let(:Authorization) { "Bearer dev-admin-api-key-12345" }
let(:query) { '' }
run_test!
end
end
end
path '/api/admin/v1/timeline/leaderboard_users' do
get('Get leaderboard users for timeline') do
tags 'Admin Timeline'
description 'Get users who should appear on the timeline leaderboard based on recent activity.'
security [ AdminToken: [] ]
produces 'application/json'
parameter name: :period, in: :query, type: :string, enum: [ 'daily', 'last_7_days' ], description: 'Leaderboard period'
response(200, 'successful') do
let(:Authorization) { "Bearer dev-admin-api-key-12345" }
let(:period) { 'last_7_days' }
schema type: :object,
properties: {
users: {
type: :array,
items: {
type: :object,
properties: {
id: { type: :integer },
display_name: { type: :string, nullable: true },
avatar_url: { type: :string, nullable: true }
}
}
}
}
run_test!
end
end
end
end