Skip to content

Commit

Permalink
Added rounds and sups to the API. Closes #10.
Browse files Browse the repository at this point in the history
  • Loading branch information
dblock committed Aug 20, 2017
1 parent 57cb197 commit 654af30
Show file tree
Hide file tree
Showing 19 changed files with 279 additions and 9 deletions.
2 changes: 2 additions & 0 deletions slack-sup/api/endpoints.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require 'slack-sup/api/endpoints/teams_endpoint'
require 'slack-sup/api/endpoints/users_endpoint'
require 'slack-sup/api/endpoints/rounds_endpoint'
require 'slack-sup/api/endpoints/sups_endpoint'
require 'slack-sup/api/endpoints/subscriptions_endpoint'
require 'slack-sup/api/endpoints/status_endpoint'
require 'slack-sup/api/endpoints/credit_cards_endpoint'
Expand Down
2 changes: 2 additions & 0 deletions slack-sup/api/endpoints/root_endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class RootEndpoint < Grape::API
mount Api::Endpoints::StatusEndpoint
mount Api::Endpoints::TeamsEndpoint
mount Api::Endpoints::UsersEndpoint
mount Api::Endpoints::RoundsEndpoint
mount Api::Endpoints::SupsEndpoint
mount Api::Endpoints::SubscriptionsEndpoint
mount Api::Endpoints::CreditCardsEndpoint
mount Api::Endpoints::SlackEndpoint
Expand Down
34 changes: 34 additions & 0 deletions slack-sup/api/endpoints/rounds_endpoint.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module Api
module Endpoints
class RoundsEndpoint < Grape::API
format :json
helpers Api::Helpers::CursorHelpers
helpers Api::Helpers::SortHelpers
helpers Api::Helpers::PaginationParameters

namespace :rounds do
desc "Get a S'Up round."
params do
requires :id, type: String, desc: 'Round ID.'
end
get ':id' do
round = Round.find(params[:id]) || error!('Not Found', 404)
error!('Not Found', 404) unless round.team.api?
present round, with: Api::Presenters::RoundPresenter
end

desc "Get all the S'Up rounds for a team."
params do
requires :team_id, type: String, desc: 'Team ID.'
use :pagination
end
get do
team = Team.find(params[:team_id]) || error!('Not Found', 404)
error!('Not Found', 404) unless team.api?
rounds = paginate_and_sort_by_cursor(team.rounds, default_sort_order: '_id')
present rounds, with: Api::Presenters::RoundsPresenter
end
end
end
end
end
34 changes: 34 additions & 0 deletions slack-sup/api/endpoints/sups_endpoint.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module Api
module Endpoints
class SupsEndpoint < Grape::API
format :json
helpers Api::Helpers::CursorHelpers
helpers Api::Helpers::SortHelpers
helpers Api::Helpers::PaginationParameters

namespace :sups do
desc "Get a S'Up."
params do
requires :id, type: String, desc: 'Sup ID.'
end
get ':id' do
sup = Sup.find(params[:id]) || error!('Not Found', 404)
error!('Not Found', 404) unless sup.round.team.api?
present sup, with: Api::Presenters::SupPresenter
end

desc "Get all the S'Up for a round."
params do
requires :round_id, type: String, desc: 'Team ID.'
use :pagination
end
get do
round = Round.find(params[:round_id]) || error!('Not Found', 404)
error!('Not Found', 404) unless round.team.api?
sups = paginate_and_sort_by_cursor(round.sups, default_sort_order: '_id')
present sups, with: Api::Presenters::SupsPresenter
end
end
end
end
end
2 changes: 1 addition & 1 deletion slack-sup/api/endpoints/users_endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class UsersEndpoint < Grape::API
requires :id, type: String, desc: 'User ID.'
end
get ':id' do
user = User.where(_id: params[:id]).first || error!('Not Found', 404)
user = User.find(params[:id]) || error!('Not Found', 404)
error!('Not Found', 404) unless user.team.api?
present user, with: Api::Presenters::UserPresenter
end
Expand Down
4 changes: 4 additions & 0 deletions slack-sup/api/presenters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
require 'slack-sup/api/presenters/root_presenter'
require 'slack-sup/api/presenters/user_presenter'
require 'slack-sup/api/presenters/users_presenter'
require 'slack-sup/api/presenters/round_presenter'
require 'slack-sup/api/presenters/rounds_presenter'
require 'slack-sup/api/presenters/sup_presenter'
require 'slack-sup/api/presenters/sups_presenter'
16 changes: 15 additions & 1 deletion slack-sup/api/presenters/root_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,21 @@ module RootPresenter
}
end

%i[user team].each do |model|
link :rounds do |opts|
{
href: "#{base_url(opts)}/api/rounds/#{link_params(Api::Helpers::PaginationParameters::ALL, :team_id)}",
templated: true
}
end

link :sups do |opts|
{
href: "#{base_url(opts)}/api/sups/#{link_params(Api::Helpers::PaginationParameters::ALL, :round_id)}",
templated: true
}
end

%i[user team round sup].each do |model|
link model do |opts|
{
href: "#{base_url(opts)}/api/#{model.to_s.pluralize}/{id}",
Expand Down
30 changes: 30 additions & 0 deletions slack-sup/api/presenters/round_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Api
module Presenters
module RoundPresenter
include Roar::JSON::HAL
include Roar::Hypermedia
include Grape::Roar::Representer

property :id, type: String, desc: 'Round ID.'
property :ran_at, type: DateTime, desc: 'Date/time when the round was run.'
property :asked_at, type: DateTime, desc: 'Date/time when outcomes were collected.'
property :created_at, type: DateTime, desc: 'Date/time when the round was created.'
property :updated_at, type: DateTime, desc: 'Date/time when the round was updated.'

link :team do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/teams/#{team_id}"
end

link :sups do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/sups?round_id=#{id}"
end

link :self do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/rounds/#{id}"
end
end
end
end
12 changes: 12 additions & 0 deletions slack-sup/api/presenters/rounds_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Api
module Presenters
module RoundsPresenter
include Roar::JSON::HAL
include Roar::Hypermedia
include Grape::Roar::Representer
include Api::Presenters::PaginatedPresenter

collection :results, extend: RoundPresenter, as: :rounds, embedded: true
end
end
end
26 changes: 26 additions & 0 deletions slack-sup/api/presenters/sup_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Api
module Presenters
module SupPresenter
include Roar::JSON::HAL
include Roar::Hypermedia
include Grape::Roar::Representer

property :id, type: String, desc: "S'Up ID."
property :outcome, type: String, desc: "S'up outcome."
property :created_at, type: DateTime, desc: "Date/time when the S'Up was created."
property :updated_at, type: DateTime, desc: "Date/time when the S'Up was updated."

collection :users, extend: UserPresenter, as: :users, embedded: true

link :round do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/rounds/#{round_id}"
end

link :self do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/sups/#{id}"
end
end
end
end
12 changes: 12 additions & 0 deletions slack-sup/api/presenters/sups_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Api
module Presenters
module SupsPresenter
include Roar::JSON::HAL
include Roar::Hypermedia
include Grape::Roar::Representer
include Api::Presenters::PaginatedPresenter

collection :results, extend: SupPresenter, as: :sups, embedded: true
end
end
end
7 changes: 6 additions & 1 deletion slack-sup/api/presenters/team_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module TeamPresenter
property :subscribed, type: Boolean, desc: 'Team is a paid subscriber.'
property :subscribed_at, type: DateTime, desc: 'Date/time when a subscription was purchased.'
property :created_at, type: DateTime, desc: 'Date/time when the team was created.'
property :updated_at, type: DateTime, desc: 'Date/time when the team was accepted, declined or canceled.'
property :updated_at, type: DateTime, desc: 'Date/time when the team was updated.'
property :sup_wday, type: Integer, desc: "S'Up day of the week."
property :sup_day, type: String, desc: "S'Up day of the week in English."
property :sup_tz, type: String, desc: 'Team timezone.'
Expand All @@ -23,6 +23,11 @@ module TeamPresenter
"#{request.base_url}/api/users?team_id=#{id}"
end

link :rounds do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/rounds?team_id=#{id}"
end

link :self do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/teams/#{id}"
Expand Down
6 changes: 3 additions & 3 deletions slack-sup/api/presenters/user_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ module UserPresenter
property :is_admin, type: Boolean, desc: 'User is an admin.'
property :enabled, type: Boolean, desc: 'User is enabled.'
property :opted_in, type: Boolean, desc: "User is opted into S'Up."
property :created_at, type: DateTime, desc: 'Date/time when the team was created.'
property :updated_at, type: DateTime, desc: 'Date/time when the team was accepted, declined or canceled.'
property :created_at, type: DateTime, desc: 'Date/time when the user was created.'
property :updated_at, type: DateTime, desc: 'Date/time when the user was updated.'

link :team do |opts|
request = Grape::Request.new(opts[:env])
"#{request.base_url}/api/teams/#{team.id}"
"#{request.base_url}/api/teams/#{team_id}"
end

link :self do |opts|
Expand Down
4 changes: 4 additions & 0 deletions spec/api/documentation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
'/api/teams',
'/api/users/{id}',
'/api/users',
'/api/rounds/{id}',
'/api/rounds',
'/api/sups/{id}',
'/api/sups',
'/api/subscriptions',
'/api/credit_cards',
'/api/slack/action'
Expand Down
2 changes: 1 addition & 1 deletion spec/api/endpoints/root_endpoint_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
get '/api'
expect(last_response.status).to eq 200
links = JSON.parse(last_response.body)['_links']
expect(links.keys.sort).to eq(%w[self status subscriptions credit_cards team teams user users].sort)
expect(links.keys.sort).to eq(%w[self round rounds status subscriptions credit_cards sup sups team teams user users].sort)
end
it 'follows all links' do
get '/api'
Expand Down
45 changes: 45 additions & 0 deletions spec/api/endpoints/rounds_endpoint_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'spec_helper'

describe Api::Endpoints::RoundsEndpoint do
include Api::Test::EndpointTest

let!(:team) { Fabricate(:team, api: true) }

before do
@cursor_params = { team_id: team.id.to_s }
end

it_behaves_like 'a cursor api', Round

context 'round' do
let(:existing_round) { Fabricate(:round, team: team) }
it 'returns a round' do
round = client.round(id: existing_round.id)
expect(round.id).to eq existing_round.id.to_s
expect(round._links.self._url).to eq "http://example.org/api/rounds/#{existing_round.id}"
end
it 'cannot return a round for a team with api off' do
team.update_attributes!(api: false)
expect { client.round(id: existing_round.id).resource }.to raise_error Faraday::ClientError do |e|
json = JSON.parse(e.response[:body])
expect(json['error']).to eq 'Not Found'
end
end
end

context 'rounds' do
let!(:round_1) { Fabricate(:round, team: team) }
let!(:round_2) { Fabricate(:round, team: team) }
it 'cannot return rounds for a team with api off' do
team.update_attributes!(api: false)
expect { client.rounds(team_id: team.id).resource }.to raise_error Faraday::ClientError do |e|
json = JSON.parse(e.response[:body])
expect(json['error']).to eq 'Not Found'
end
end
it 'returns rounds' do
rounds = client.rounds(team_id: team.id)
expect(rounds.map(&:id).sort).to eq [round_1, round_2].map(&:id).map(&:to_s).sort
end
end
end
46 changes: 46 additions & 0 deletions spec/api/endpoints/sups_endpoint_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'spec_helper'

describe Api::Endpoints::SupsEndpoint do
include Api::Test::EndpointTest

let!(:team) { Fabricate(:team, api: true) }
let!(:round) { Fabricate(:round, team: team) }

before do
@cursor_params = { round_id: round.id.to_s }
end

it_behaves_like 'a cursor api', Sup

context 'sup' do
let(:existing_sup) { Fabricate(:sup, round: round) }
it 'returns a sup' do
sup = client.sup(id: existing_sup.id)
expect(sup.id).to eq existing_sup.id.to_s
expect(sup._links.self._url).to eq "http://example.org/api/sups/#{existing_sup.id}"
end
it 'cannot return a sup for a team with api off' do
team.update_attributes!(api: false)
expect { client.sup(id: existing_sup.id).resource }.to raise_error Faraday::ClientError do |e|
json = JSON.parse(e.response[:body])
expect(json['error']).to eq 'Not Found'
end
end
end

context 'sups' do
let!(:sup_1) { Fabricate(:sup, round: round) }
let!(:sup_2) { Fabricate(:sup, round: round) }
it 'cannot return sups for a team with api off' do
team.update_attributes!(api: false)
expect { client.sups(round_id: round.id).resource }.to raise_error Faraday::ClientError do |e|
json = JSON.parse(e.response[:body])
expect(json['error']).to eq 'Not Found'
end
end
it 'returns sups' do
sups = client.sups(round_id: round.id)
expect(sups.map(&:id).sort).to eq [sup_1, sup_2].map(&:id).map(&:to_s).sort
end
end
end
2 changes: 1 addition & 1 deletion spec/fabricators/round_fabricator.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Fabricator(:round) do
team { Fabricate(:team) }
team { Team.first || Fabricate(:team) }
end
2 changes: 1 addition & 1 deletion spec/fabricators/sup_fabricator.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Fabricator(:sup) do
round { Fabricate(:round) }
round { Round.first || Fabricate(:round) }
end

0 comments on commit 654af30

Please sign in to comment.