Fix tests

This commit is contained in:
Eugene Burmakin 2025-05-04 00:16:02 +02:00
parent ac5d14f4a7
commit e6fddddc01
5 changed files with 168 additions and 140 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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!

View file

@ -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