@@ -6,6 +6,7 @@ import com.jackpf.locationhistory.admin_service.{
66 DeleteDeviceRequest ,
77 DeleteDeviceResponse ,
88 ListDevicesRequest ,
9+ ListLocationsRequest ,
910 LoginRequest ,
1011 SendNotificationRequest ,
1112 SendNotificationResponse
@@ -15,9 +16,11 @@ import com.jackpf.locationhistory.beacon_service.{
1516 RegisterDeviceRequest ,
1617 RegisterDeviceResponse ,
1718 RegisterPushHandlerRequest ,
18- RegisterPushHandlerResponse
19+ RegisterPushHandlerResponse ,
20+ SetLocationRequest ,
21+ SetLocationResponse
1922}
20- import com .jackpf .locationhistory .common .{Device , PushHandler }
23+ import com .jackpf .locationhistory .common .{Device , Location , PushHandler , StoredLocation }
2124import com .jackpf .locationhistory .server .testutil .{GrpcMatchers , IntegrationTest , TestServer }
2225import io .grpc .Status .Code
2326import org .mockito .ArgumentMatchers .{any , anyString }
@@ -108,12 +111,10 @@ class AdminTest extends IntegrationTest with GrpcMatchers {
108111 }
109112
110113 " fail to approve already approved device" >> in(new RegisteredDeviceContext {}) { context =>
111- // First approval should succeed
112114 context.adminClient.approveDevice(
113115 ApproveDeviceRequest (deviceId = context.device.id)
114116 ) === ApproveDeviceResponse (success = true )
115117
116- // Second approval should fail
117118 context.adminClient.approveDevice(
118119 ApproveDeviceRequest (deviceId = context.device.id)
119120 ) must throwAGrpcRuntimeException(
@@ -200,5 +201,66 @@ class AdminTest extends IntegrationTest with GrpcMatchers {
200201 )
201202 }
202203 }
204+
205+ " list locations endpoint" >> {
206+ trait ApprovedDeviceContext extends RegisteredDeviceContext {
207+ adminClient.approveDevice(
208+ ApproveDeviceRequest (deviceId = device.id)
209+ ) === ApproveDeviceResponse (success = true )
210+ }
211+
212+ " list locations with metadata fields" >> in(new ApprovedDeviceContext {}) { context =>
213+ val timestamp = System .currentTimeMillis()
214+ val location = Location (lat = 51.5007 , lon = - 0.1246 , accuracy = 10.0 )
215+
216+ context.client.setLocation(
217+ SetLocationRequest (
218+ timestamp = timestamp,
219+ deviceId = context.device.id,
220+ location = Some (location)
221+ )
222+ ) === SetLocationResponse (success = true )
223+
224+ val response = context.adminClient.listLocations(
225+ ListLocationsRequest (deviceId = context.device.id)
226+ )
227+
228+ response.locations must haveSize(1 )
229+ val storedLocation = response.locations.head
230+ storedLocation.location must beSome(location)
231+ storedLocation.startTimestamp === timestamp
232+ storedLocation.endTimestamp === timestamp
233+ storedLocation.count === 1L
234+ }
235+
236+ " list locations with updated metadata after duplicates" >> in(new ApprovedDeviceContext {}) {
237+ context =>
238+ context.client.setLocation(
239+ SetLocationRequest (
240+ timestamp = 1000L ,
241+ deviceId = context.device.id,
242+ location = Some (Location (lat = 51.5007 , lon = - 0.1246 , accuracy = 10.0 ))
243+ )
244+ ) === SetLocationResponse (success = true )
245+
246+ context.client.setLocation(
247+ SetLocationRequest (
248+ timestamp = 2000L ,
249+ deviceId = context.device.id,
250+ location = Some (Location (lat = 51.5007 , lon = - 0.1246 , accuracy = 10.0 ))
251+ )
252+ ) === SetLocationResponse (success = true )
253+
254+ val response = context.adminClient.listLocations(
255+ ListLocationsRequest (deviceId = context.device.id)
256+ )
257+
258+ response.locations must haveSize(1 )
259+ val storedLocation = response.locations.head
260+ storedLocation.startTimestamp === 1000L
261+ storedLocation.endTimestamp === 2000L
262+ storedLocation.count === 2L
263+ }
264+ }
203265 }
204266}
0 commit comments