From 7bc01712c3f70e1e7977ef7b7680594a6319ecee Mon Sep 17 00:00:00 2001 From: Reem Ibrahim Date: Tue, 28 Apr 2026 16:17:04 +0100 Subject: [PATCH 1/3] added new endpoint and spec --- app/controllers/v2/tasks_controller.rb | 12 +++++++ config/routes.rb | 1 + spec/requests/v2/tasks_spec.rb | 50 ++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 app/controllers/v2/tasks_controller.rb create mode 100644 spec/requests/v2/tasks_spec.rb diff --git a/app/controllers/v2/tasks_controller.rb b/app/controllers/v2/tasks_controller.rb new file mode 100644 index 000000000..b3dc503d9 --- /dev/null +++ b/app/controllers/v2/tasks_controller.rb @@ -0,0 +1,12 @@ +class V2::TasksController < ActionController::API + include ApiKeyAuthenticatable + + def index + @tasks = Task.all + @tasks = @tasks.where(updated_at: Time.zone.parse(params[:updated_at])..Time.zone.now) if params[:updated_at].present? + + render json: @tasks + rescue ArgumentError + render json: { error: 'updated_at must be a valid date or datetime' }, status: :bad_request + end +end diff --git a/config/routes.rb b/config/routes.rb index 84d0fc374..48de4e6f6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -80,6 +80,7 @@ resources :frameworks, only: :index resources :framework_lots, only: :index resources :agreement_framework_lots, only: :index + resources :tasks, only: :index end namespace :admin do diff --git a/spec/requests/v2/tasks_spec.rb b/spec/requests/v2/tasks_spec.rb new file mode 100644 index 000000000..fcd45cd3c --- /dev/null +++ b/spec/requests/v2/tasks_spec.rb @@ -0,0 +1,50 @@ +require 'rails_helper' + +RSpec.describe 'V2::Tasks', type: :request do + let(:valid_api_key) { create(:api_key) } + let(:invalid_api_key) { 'invalid_key' } + + describe 'GET /v2/tasks' do + context 'with valid API key' do + before do + create_list(:task, 3) + get v2_tasks_path, headers: { 'API-Key' => valid_api_key.key } + end + + it 'returns all tasks when updated_at is not provided' do + expect(response).to have_http_status(:ok) + expect(JSON.parse(response.body).size).to eq(3) + end + + it 'returns tasks updated since the provided date' do + old_task = create(:task, updated_at: 3.days.ago) + recent_task = create(:task, updated_at: 1.hour.ago) + + get v2_tasks_path, params: { updated_at: 2.days.ago.iso8601 }, headers: { 'API-Key' => valid_api_key.key } + task_ids = JSON.parse(response.body).pluck('id') + + expect(response).to have_http_status(:ok) + expect(task_ids).to include(recent_task.id) + expect(task_ids).not_to include(old_task.id) + end + end + + context 'with missing API key' do + before { get v2_tasks_path } + + it 'returns unauthorized status' do + expect(response).to have_http_status(:unauthorized) + expect(JSON.parse(response.body)['error']).to eq('API key is missing') + end + end + + context 'with invalid API key' do + before { get v2_tasks_path, headers: { 'API-Key' => invalid_api_key } } + + it 'returns unauthorized status' do + expect(response).to have_http_status(:unauthorized) + expect(JSON.parse(response.body)['error']).to eq('API key is invalid') + end + end + end +end From bfe0d9c81538220fbfbf6185d3699816164a4e5b Mon Sep 17 00:00:00 2001 From: Reem Ibrahim Date: Tue, 28 Apr 2026 16:18:21 +0100 Subject: [PATCH 2/3] rubocop --- app/controllers/v2/tasks_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/v2/tasks_controller.rb b/app/controllers/v2/tasks_controller.rb index b3dc503d9..1c6221800 100644 --- a/app/controllers/v2/tasks_controller.rb +++ b/app/controllers/v2/tasks_controller.rb @@ -3,7 +3,9 @@ class V2::TasksController < ActionController::API def index @tasks = Task.all - @tasks = @tasks.where(updated_at: Time.zone.parse(params[:updated_at])..Time.zone.now) if params[:updated_at].present? + if params[:updated_at].present? + @tasks = @tasks.where(updated_at: Time.zone.parse(params[:updated_at])..Time.zone.now) + end render json: @tasks rescue ArgumentError From 82845c2782dca51288994237ac833b74515b951b Mon Sep 17 00:00:00 2001 From: Reem Ibrahim Date: Wed, 29 Apr 2026 12:40:57 +0100 Subject: [PATCH 3/3] added submissions endpoint and spec --- app/controllers/v2/submissions_controller.rb | 14 ++++++ config/routes.rb | 1 + spec/requests/v2/submissions_spec.rb | 50 ++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 app/controllers/v2/submissions_controller.rb create mode 100644 spec/requests/v2/submissions_spec.rb diff --git a/app/controllers/v2/submissions_controller.rb b/app/controllers/v2/submissions_controller.rb new file mode 100644 index 000000000..3e86e450c --- /dev/null +++ b/app/controllers/v2/submissions_controller.rb @@ -0,0 +1,14 @@ +class V2::SubmissionsController < ActionController::API + include ApiKeyAuthenticatable + + def index + @submissions = Submission.all + if params[:updated_at].present? + @submissions = @submissions.where(updated_at: Time.zone.parse(params[:updated_at])..Time.zone.now) + end + + render json: @submissions + rescue ArgumentError + render json: { error: 'updated_at must be a valid date or datetime' }, status: :bad_request + end +end diff --git a/config/routes.rb b/config/routes.rb index 48de4e6f6..042d10e48 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -81,6 +81,7 @@ resources :framework_lots, only: :index resources :agreement_framework_lots, only: :index resources :tasks, only: :index + resources :submissions, only: :index end namespace :admin do diff --git a/spec/requests/v2/submissions_spec.rb b/spec/requests/v2/submissions_spec.rb new file mode 100644 index 000000000..1aec67cbf --- /dev/null +++ b/spec/requests/v2/submissions_spec.rb @@ -0,0 +1,50 @@ +require 'rails_helper' + +RSpec.describe 'V2::Submissions', type: :request do + let(:valid_api_key) { create(:api_key) } + let(:invalid_api_key) { 'invalid_key' } + + describe 'GET /v2/submissions' do + context 'with valid API key' do + before do + create_list(:submission, 3) + get v2_submissions_path, headers: { 'API-Key' => valid_api_key.key } + end + + it 'returns all submissions when updated_at is not provided' do + expect(response).to have_http_status(:ok) + expect(JSON.parse(response.body).size).to eq(3) + end + + it 'returns submissions updated since the provided date' do + old_submission = create(:submission, updated_at: 3.days.ago) + recent_submission = create(:submission, updated_at: 1.hour.ago) + + get v2_submissions_path, params: { updated_at: 2.days.ago.iso8601 }, headers: { 'API-Key' => valid_api_key.key } + submission_ids = JSON.parse(response.body).pluck('id') + + expect(response).to have_http_status(:ok) + expect(submission_ids).to include(recent_submission.id) + expect(submission_ids).not_to include(old_submission.id) + end + end + + context 'with missing API key' do + before { get v2_submissions_path } + + it 'returns unauthorized status' do + expect(response).to have_http_status(:unauthorized) + expect(JSON.parse(response.body)['error']).to eq('API key is missing') + end + end + + context 'with invalid API key' do + before { get v2_submissions_path, headers: { 'API-Key' => invalid_api_key } } + + it 'returns unauthorized status' do + expect(response).to have_http_status(:unauthorized) + expect(JSON.parse(response.body)['error']).to eq('API key is invalid') + end + end + end +end