From e6fddddc0112a8b4b9e12c51eb21c78d624d568a Mon Sep 17 00:00:00 2001 From: Eugene Burmakin Date: Sun, 4 May 2025 00:16:02 +0200 Subject: [PATCH] Fix tests --- app/services/points/create.rb | 6 +- spec/requests/api/v1/points_spec.rb | 23 ++- spec/services/points/create_spec.rb | 4 +- spec/swagger/api/v1/points_controller_spec.rb | 150 +++++++++--------- swagger/v1/swagger.yaml | 125 ++++++++------- 5 files changed, 168 insertions(+), 140 deletions(-) diff --git a/app/services/points/create.rb b/app/services/points/create.rb index 81d46e14..24b5b275 100644 --- a/app/services/points/create.rb +++ b/app/services/points/create.rb @@ -5,10 +5,9 @@ class Points::Create def initialize(user, params) @user = user - @params = params + @params = params.to_h end - # rubocop:disable Metrics/MethodLength def call data = Points::Params.new(params, user.id).call @@ -19,7 +18,7 @@ class Points::Create result = Point.upsert_all( location_batch, unique_by: %i[lonlat timestamp user_id], - returning: %i[id lonlat timestamp] + returning: Arel.sql('id, timestamp, ST_X(lonlat::geometry) AS longitude, ST_Y(lonlat::geometry) AS latitude') ) # rubocop:enable Rails/SkipsModelValidations @@ -28,5 +27,4 @@ class Points::Create created_points end - # rubocop:enable Metrics/MethodLength end diff --git a/spec/requests/api/v1/points_spec.rb b/spec/requests/api/v1/points_spec.rb index 1983640c..50d3397e 100644 --- a/spec/requests/api/v1/points_spec.rb +++ b/spec/requests/api/v1/points_spec.rb @@ -9,6 +9,16 @@ RSpec.describe 'Api::V1::Points', type: :request do create(:point, user:, timestamp: 1.day.ago + i.minutes) end end + let(:point_params) do + { + locations: [ + { + geometry: { type: 'Point', coordinates: [1.0, 1.0] }, + properties: { timestamp: '2025-01-17T21:03:01Z' } + } + ] + } + end describe 'GET /index' do context 'when regular version of points is requested' do @@ -122,9 +132,16 @@ RSpec.describe 'Api::V1::Points', type: :request do describe 'POST /create' do it 'returns a successful response' do - post "/api/v1/points?api_key=#{user.api_key}", params: { point: { latitude: 1.0, longitude: 1.0 } } + post "/api/v1/points?api_key=#{user.api_key}", params: point_params - expect(response).to have_http_status(:success) + expect(response).to have_http_status(:ok) + + json_response = JSON.parse(response.body)['data'] + + expect(json_response.size).to be_positive + expect(json_response.first['latitude']).to eq(1.0) + expect(json_response.first['longitude']).to eq(1.0) + expect(json_response.first['timestamp']).to be_an_instance_of(Integer) end context 'when user is inactive' do @@ -133,7 +150,7 @@ RSpec.describe 'Api::V1::Points', type: :request do end it 'returns an unauthorized response' do - post "/api/v1/points?api_key=#{user.api_key}", params: { point: { latitude: 1.0, longitude: 1.0 } } + post "/api/v1/points?api_key=#{user.api_key}", params: point_params expect(response).to have_http_status(:unauthorized) end diff --git a/spec/services/points/create_spec.rb b/spec/services/points/create_spec.rb index b4420b2c..12f383eb 100644 --- a/spec/services/points/create_spec.rb +++ b/spec/services/points/create_spec.rb @@ -50,7 +50,7 @@ RSpec.describe Points::Create do .with( processed_data, unique_by: %i[lonlat timestamp user_id], - returning: %i[id lonlat timestamp] + returning: Arel.sql('id, timestamp, ST_X(lonlat::geometry) AS longitude, ST_Y(lonlat::geometry) AS latitude') ) .and_return(upsert_result) @@ -205,7 +205,7 @@ RSpec.describe Points::Create do .with( all_processed_data, unique_by: %i[lonlat timestamp user_id], - returning: %i[id lonlat timestamp] + returning: Arel.sql('id, timestamp, ST_X(lonlat::geometry) AS longitude, ST_Y(lonlat::geometry) AS latitude') ) .and_return(expected_results) end diff --git a/spec/swagger/api/v1/points_controller_spec.rb b/spec/swagger/api/v1/points_controller_spec.rb index 7b710f2d..7450df45 100644 --- a/spec/swagger/api/v1/points_controller_spec.rb +++ b/spec/swagger/api/v1/points_controller_spec.rb @@ -100,76 +100,84 @@ describe 'Points API', type: :request do parameter name: :locations, in: :body, schema: { type: :object, properties: { - type: { type: :string }, - geometry: { - type: :object, - properties: { - type: { - type: :string, - example: 'Point', - description: 'the geometry type, always Point' - }, - coordinates: { - type: :array, - items: { - type: :number, - example: [-122.40530871, 37.74430413], - description: 'the coordinates of the point, longitude and latitude' + locations: { + type: :array, + items: { + type: :object, + properties: { + type: { type: :string }, + geometry: { + type: :object, + properties: { + type: { + type: :string, + example: 'Point', + description: 'the geometry type, always Point' + }, + coordinates: { + type: :array, + items: { + type: :number, + example: [-122.40530871, 37.74430413], + description: 'the coordinates of the point, longitude and latitude' + } + } + } + }, + properties: { + type: :object, + properties: { + timestamp: { + type: :string, + example: '2025-01-17T21:03:01Z', + description: 'the timestamp of the point' + }, + horizontal_accuracy: { + type: :number, + example: 5, + description: 'the horizontal accuracy of the point in meters' + }, + vertical_accuracy: { + type: :number, + example: -1, + description: 'the vertical accuracy of the point in meters' + }, + altitude: { + type: :number, + example: 0, + description: 'the altitude of the point in meters' + }, + speed: { + type: :number, + example: 92.088, + description: 'the speed of the point in meters per second' + }, + speed_accuracy: { + type: :number, + example: 0, + description: 'the speed accuracy of the point in meters per second' + }, + course_accuracy: { + type: :number, + example: 0, + description: 'the course accuracy of the point in degrees' + }, + track_id: { + type: :string, + example: '799F32F5-89BB-45FB-A639-098B1B95B09F', + description: 'the track id of the point set by the device' + }, + device_id: { + type: :string, + example: '8D5D4197-245B-4619-A88B-2049100ADE46', + description: 'the device id of the point set by the device' + } + } } - } + }, + required: %w[geometry properties] } - }, - properties: { - type: :object, - properties: { - timestamp: { - type: :string, - example: '2025-01-17T21:03:01Z', - description: 'the timestamp of the point' - }, - horizontal_accuracy: { - type: :number, - example: 5, - description: 'the horizontal accuracy of the point in meters' - }, - vertical_accuracy: { - type: :number, - example: -1, - description: 'the vertical accuracy of the point in meters' - }, - altitude: { - type: :number, - example: 0, - description: 'the altitude of the point in meters' - }, - speed: { - type: :number, - example: 92.088, - description: 'the speed of the point in meters per second' - }, - speed_accuracy: { - type: :number, - example: 0, - description: 'the speed accuracy of the point in meters per second' - }, - course_accuracy: { - type: :number, - example: 0, - description: 'the course accuracy of the point in degrees' - }, - track_id: { - type: :string, - example: '799F32F5-89BB-45FB-A639-098B1B95B09F', - description: 'the track id of the point set by the device' - }, - device_id: { - type: :string, - example: '8D5D4197-245B-4619-A88B-2049100ADE46', - description: 'the device id of the point set by the device' - } - } - }, - required: %w[geometry properties] + } } } @@ -179,8 +187,7 @@ describe 'Points API', type: :request do let(:file_path) { 'spec/fixtures/files/points/geojson_example.json' } let(:file) { File.open(file_path) } let(:json) { JSON.parse(file.read) } - let(:params) { json } - let(:locations) { params['locations'] } + let(:locations) { json } let(:api_key) { create(:user).api_key } run_test! @@ -190,8 +197,7 @@ describe 'Points API', type: :request do let(:file_path) { 'spec/fixtures/files/points/geojson_example.json' } let(:file) { File.open(file_path) } let(:json) { JSON.parse(file.read) } - let(:params) { json } - let(:locations) { params['locations'] } + let(:locations) { json } let(:api_key) { 'invalid_api_key' } run_test! diff --git a/swagger/v1/swagger.yaml b/swagger/v1/swagger.yaml index 57db976d..a58bcb10 100644 --- a/swagger/v1/swagger.yaml +++ b/swagger/v1/swagger.yaml @@ -847,65 +847,72 @@ paths: schema: type: object properties: - type: - type: string - geometry: - type: object - properties: - type: - type: string - example: Point - description: the geometry type, always Point - coordinates: - type: array - items: - type: number - example: - - -122.40530871 - - 37.74430413 - description: the coordinates of the point, longitude and latitude - properties: - type: object - properties: - timestamp: - type: string - example: '2025-01-17T21:03:01Z' - description: the timestamp of the point - horizontal_accuracy: - type: number - example: 5 - description: the horizontal accuracy of the point in meters - vertical_accuracy: - type: number - example: -1 - description: the vertical accuracy of the point in meters - altitude: - type: number - example: 0 - description: the altitude of the point in meters - speed: - type: number - example: 92.088 - description: the speed of the point in meters per second - speed_accuracy: - type: number - example: 0 - description: the speed accuracy of the point in meters per second - course_accuracy: - type: number - example: 0 - description: the course accuracy of the point in degrees - track_id: - type: string - example: 799F32F5-89BB-45FB-A639-098B1B95B09F - description: the track id of the point set by the device - device_id: - type: string - example: 8D5D4197-245B-4619-A88B-2049100ADE46 - description: the device id of the point set by the device - required: - - geometry - - properties + locations: + type: array + items: + type: object + properties: + type: + type: string + geometry: + type: object + properties: + type: + type: string + example: Point + description: the geometry type, always Point + coordinates: + type: array + items: + type: number + example: + - -122.40530871 + - 37.74430413 + description: the coordinates of the point, longitude + and latitude + properties: + type: object + properties: + timestamp: + type: string + example: '2025-01-17T21:03:01Z' + description: the timestamp of the point + horizontal_accuracy: + type: number + example: 5 + description: the horizontal accuracy of the point in meters + vertical_accuracy: + type: number + example: -1 + description: the vertical accuracy of the point in meters + altitude: + type: number + example: 0 + description: the altitude of the point in meters + speed: + type: number + example: 92.088 + description: the speed of the point in meters per second + speed_accuracy: + type: number + example: 0 + description: the speed accuracy of the point in meters + per second + course_accuracy: + type: number + example: 0 + description: the course accuracy of the point in degrees + track_id: + type: string + example: 799F32F5-89BB-45FB-A639-098B1B95B09F + description: the track id of the point set by the device + device_id: + type: string + example: 8D5D4197-245B-4619-A88B-2049100ADE46 + description: the device id of the point set by the device + required: + - geometry + - properties examples: '0': summary: Creates a batch of points