update get type(s) for pagination and filter
- update TypesEndpoint for all new endpoints - update application to use properties for sql script - update types controller - update types.http for all types of types calls - update test mocking for service - update getTypes to use filter, page, and show in TypesController - add validation dependency - update unit test for uuid assertion from test library in - remove UUIDAssert.kt - update IdentityControllerTest - update MappingKtTest - update NodeControllerTest - update TypeControllerTest - update TypesControllerTest - add test library dependency - update getTypes to handle filter limit and offset in TypeService - update TypeRepository - add findAllContaining with filter, limit and offset - add findAll with limit and offset - update type database with specific name key - split Type and Types
This commit is contained in:
@@ -16,12 +16,14 @@ dependencies {
|
|||||||
implementation(hlaeja.library.jwt)
|
implementation(hlaeja.library.jwt)
|
||||||
implementation(hlaeja.springboot.starter.actuator)
|
implementation(hlaeja.springboot.starter.actuator)
|
||||||
implementation(hlaeja.springboot.starter.r2dbc)
|
implementation(hlaeja.springboot.starter.r2dbc)
|
||||||
|
implementation(hlaeja.springboot.starter.validation)
|
||||||
implementation(hlaeja.springboot.starter.webflux)
|
implementation(hlaeja.springboot.starter.webflux)
|
||||||
|
|
||||||
runtimeOnly(hlaeja.postgresql)
|
runtimeOnly(hlaeja.postgresql)
|
||||||
runtimeOnly(hlaeja.postgresql.r2dbc)
|
runtimeOnly(hlaeja.postgresql.r2dbc)
|
||||||
|
|
||||||
testImplementation(hlaeja.assertj.core)
|
testImplementation(hlaeja.assertj.core)
|
||||||
|
testImplementation(hlaeja.library.test)
|
||||||
testImplementation(hlaeja.mockk)
|
testImplementation(hlaeja.mockk)
|
||||||
testImplementation(hlaeja.projectreactor.reactor.test)
|
testImplementation(hlaeja.projectreactor.reactor.test)
|
||||||
testImplementation(hlaeja.kotlin.test.junit5)
|
testImplementation(hlaeja.kotlin.test.junit5)
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
### let all types
|
|
||||||
GET {{hostname}}/types
|
|
||||||
|
|
||||||
|
|
||||||
### add type by name
|
### add type by name
|
||||||
POST {{hostname}}/type
|
POST {{hostname}}/type
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|||||||
17
http/types.http
Normal file
17
http/types.http
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
### get all types
|
||||||
|
GET {{hostname}}/types
|
||||||
|
|
||||||
|
### get all types
|
||||||
|
GET {{hostname}}/types/page-1
|
||||||
|
|
||||||
|
### get all types
|
||||||
|
GET {{hostname}}/types/page-1/show-2
|
||||||
|
|
||||||
|
### get all types
|
||||||
|
GET {{hostname}}/types/filter-{filter}
|
||||||
|
|
||||||
|
### get all types
|
||||||
|
GET {{hostname}}/types/filter-{filter}/page-1
|
||||||
|
|
||||||
|
### get all types
|
||||||
|
GET {{hostname}}/types/filter-{filter}/page-1/show-2
|
||||||
6
sql/002-types.sql
Normal file
6
sql/002-types.sql
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
-- make name index unique order by name
|
||||||
|
|
||||||
|
DROP INDEX IF EXISTS types_name_key;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS types_name_key
|
||||||
|
ON types (name ASC);
|
||||||
@@ -5,13 +5,18 @@ CREATE TABLE IF NOT EXISTS public.types
|
|||||||
(
|
(
|
||||||
id UUID DEFAULT gen_uuid_v7(),
|
id UUID DEFAULT gen_uuid_v7(),
|
||||||
timestamp timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
timestamp timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
name VARCHAR(50) UNIQUE NOT NULL,
|
name VARCHAR(50) NOT NULL,
|
||||||
CONSTRAINT pk_contact_types PRIMARY KEY (id)
|
CONSTRAINT pk_contact_types PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
ALTER TABLE IF EXISTS public.types
|
ALTER TABLE IF EXISTS public.types
|
||||||
OWNER to role_administrator;
|
OWNER to role_administrator;
|
||||||
|
|
||||||
|
-- Index: types_name_key
|
||||||
|
-- DROP INDEX IF EXISTS types_name_key;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS types_name_key
|
||||||
|
ON types (name ASC);
|
||||||
|
|
||||||
-- Revoke all permissions from existing roles
|
-- Revoke all permissions from existing roles
|
||||||
REVOKE ALL ON TABLE public.types FROM role_administrator, role_maintainer, role_support, role_service;
|
REVOKE ALL ON TABLE public.types FROM role_administrator, role_maintainer, role_support, role_service;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ltd.hlaeja.controller
|
|||||||
|
|
||||||
import ltd.hlaeja.library.deviceRegistry.Type
|
import ltd.hlaeja.library.deviceRegistry.Type
|
||||||
import ltd.hlaeja.test.container.PostgresContainer
|
import ltd.hlaeja.test.container.PostgresContainer
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.assertj.core.api.SoftAssertions
|
import org.assertj.core.api.SoftAssertions
|
||||||
import org.assertj.core.api.junit.jupiter.InjectSoftAssertions
|
import org.assertj.core.api.junit.jupiter.InjectSoftAssertions
|
||||||
import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension
|
import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension
|
||||||
@@ -35,23 +34,6 @@ class TypeEndpoint {
|
|||||||
webClient = WebTestClient.bindToServer().baseUrl("http://localhost:$port").build()
|
webClient = WebTestClient.bindToServer().baseUrl("http://localhost:$port").build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
|
||||||
inner class GetTypes {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `get types`() {
|
|
||||||
// when
|
|
||||||
val result = webClient.get().uri("/types").exchange()
|
|
||||||
|
|
||||||
// then
|
|
||||||
result.expectStatus().isOk()
|
|
||||||
.expectBody<List<Type.Response>>()
|
|
||||||
.consumeWith {
|
|
||||||
assertThat(it.responseBody?.size).isEqualTo(5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
inner class CreateType {
|
inner class CreateType {
|
||||||
|
|
||||||
@@ -80,7 +62,7 @@ class TypeEndpoint {
|
|||||||
fun `added type - fail name take`() {
|
fun `added type - fail name take`() {
|
||||||
// given
|
// given
|
||||||
val request = Type.Request(
|
val request = Type.Request(
|
||||||
name = "Thing 1",
|
name = "Thing 1 v1",
|
||||||
)
|
)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
package ltd.hlaeja.controller
|
||||||
|
|
||||||
|
import ltd.hlaeja.library.deviceRegistry.Type
|
||||||
|
import ltd.hlaeja.test.container.PostgresContainer
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.TestInstance
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT
|
||||||
|
import org.springframework.boot.test.web.server.LocalServerPort
|
||||||
|
import org.springframework.test.web.reactive.server.WebTestClient
|
||||||
|
import org.springframework.test.web.reactive.server.expectBody
|
||||||
|
|
||||||
|
@PostgresContainer
|
||||||
|
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||||
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
|
class TypesEndpoint {
|
||||||
|
|
||||||
|
@LocalServerPort
|
||||||
|
var port: Int = 0
|
||||||
|
|
||||||
|
lateinit var webClient: WebTestClient
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setup() {
|
||||||
|
webClient = WebTestClient.bindToServer().baseUrl("http://localhost:$port").build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get types default - success`() {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isOk()
|
||||||
|
.expectBody<List<Type.Response>>()
|
||||||
|
.consumeWith {
|
||||||
|
assertThat(it.responseBody?.size).isEqualTo(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
value = [
|
||||||
|
"1,4",
|
||||||
|
"2,0",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
fun `get types by page - success`(page: Int, expected: Int) {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/page-$page").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isOk()
|
||||||
|
.expectBody<List<Type.Response>>()
|
||||||
|
.consumeWith {
|
||||||
|
assertThat(it.responseBody?.size).isEqualTo(expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get types by pages - fail`() {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/page-0").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isBadRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
value = [
|
||||||
|
"1,2,2",
|
||||||
|
"2,2,2",
|
||||||
|
"3,2,0",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
fun `get types by page and show - success`(page: Int, show: Int, expected: Int) {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/page-$page/show-$show").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isOk()
|
||||||
|
.expectBody<List<Type.Response>>()
|
||||||
|
.consumeWith {
|
||||||
|
assertThat(it.responseBody?.size).isEqualTo(expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
value = [
|
||||||
|
"0,1",
|
||||||
|
"1,0",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
fun `get types by page and show - fail`(page: Int, show: Int) {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/page-$page/show-$show").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isBadRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
value = [
|
||||||
|
"'',4",
|
||||||
|
"v1,3",
|
||||||
|
"v2,1",
|
||||||
|
"v3,0",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
fun `get types filter - success`(filter: String, expected: Int) {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/filter-$filter").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isOk()
|
||||||
|
.expectBody<List<Type.Response>>()
|
||||||
|
.consumeWith {
|
||||||
|
assertThat(it.responseBody?.size).isEqualTo(expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
value = [
|
||||||
|
"'',1,4",
|
||||||
|
"'',2,0",
|
||||||
|
"v1,1,3",
|
||||||
|
"v1,2,0",
|
||||||
|
"v2,1,1",
|
||||||
|
"v2,2,0",
|
||||||
|
"v3,1,0",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
fun `get types by filter and page - success`(filter: String, page: Int, expected: Int) {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/filter-$filter/page-$page").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isOk()
|
||||||
|
.expectBody<List<Type.Response>>()
|
||||||
|
.consumeWith {
|
||||||
|
assertThat(it.responseBody?.size).isEqualTo(expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
value = [
|
||||||
|
"'',0",
|
||||||
|
"v1,0",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
fun `get types by filter and page - fail`(filter: String, page: Int) {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/filter-$filter/page-$page").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isBadRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
value = [
|
||||||
|
"'',1,2,2",
|
||||||
|
"'',2,2,2",
|
||||||
|
"'',3,2,0",
|
||||||
|
"v1,1,2,2",
|
||||||
|
"v1,2,2,1",
|
||||||
|
"v1,3,2,0",
|
||||||
|
"v2,1,2,1",
|
||||||
|
"v2,2,2,0",
|
||||||
|
"v3,1,2,0",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
fun `get types by filter, page and show - success`(filter: String, page: Int, show: Int, expected: Int) {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/filter-$filter/page-$page/show-$show").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isOk()
|
||||||
|
.expectBody<List<Type.Response>>()
|
||||||
|
.consumeWith {
|
||||||
|
assertThat(it.responseBody?.size).isEqualTo(expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(
|
||||||
|
value = [
|
||||||
|
"'',1,0",
|
||||||
|
"'',0,1",
|
||||||
|
"v1,1,0",
|
||||||
|
"v1,0,1",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
fun `get types by filter, page and show - fail`(filter: String, page: Int, show: Int) {
|
||||||
|
// when
|
||||||
|
val result = webClient.get().uri("/types/filter-$filter/page-$page/show-$show").exchange()
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.expectStatus().isBadRequest
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,3 +6,10 @@ spring:
|
|||||||
url: r2dbc:postgresql://placeholder
|
url: r2dbc:postgresql://placeholder
|
||||||
username: placeholder
|
username: placeholder
|
||||||
password: placeholder
|
password: placeholder
|
||||||
|
|
||||||
|
container:
|
||||||
|
postgres:
|
||||||
|
version: postgres:17
|
||||||
|
init: postgres/schema.sql
|
||||||
|
before: postgres/data.sql
|
||||||
|
after: postgres/reset.sql
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
-- Test data
|
-- Test data
|
||||||
INSERT INTO public.types (id, timestamp, name)
|
INSERT INTO public.types (id, timestamp, name)
|
||||||
VALUES ('00000000-0000-0000-0001-000000000001'::uuid, '2000-01-01 00:00:00.000001 +00:00', 'Thing 1'),
|
VALUES ('00000000-0000-0000-0001-000000000001'::uuid, '2000-01-01 00:00:00.000001 +00:00', 'Thing 1 v1'),
|
||||||
('00000000-0000-0000-0001-000000000002'::uuid, '2000-01-01 00:00:00.000001 +00:00', 'Thing 2'),
|
('00000000-0000-0000-0001-000000000002'::uuid, '2000-01-01 00:00:00.000001 +00:00', 'Thing 2 v1'),
|
||||||
('00000000-0000-0000-0001-000000000003'::uuid, '2000-01-01 00:00:00.000001 +00:00', 'Thing 3'),
|
('00000000-0000-0000-0001-000000000003'::uuid, '2000-01-01 00:00:00.000001 +00:00', 'Thing 3 v2'),
|
||||||
('00000000-0000-0000-0001-000000000004'::uuid, '2000-01-01 00:00:00.000001 +00:00', 'Thing 4');
|
('00000000-0000-0000-0001-000000000004'::uuid, '2000-01-01 00:00:00.000001 +00:00', 'Thing 4 v1');
|
||||||
|
|
||||||
INSERT INTO public.devices (id, timestamp, type)
|
INSERT INTO public.devices (id, timestamp, type)
|
||||||
VALUES ('00000000-0000-0000-0002-000000000001'::uuid, '2000-01-01 00:00:00.000001 +00:00', '00000000-0000-0000-0001-000000000001'::uuid),
|
VALUES ('00000000-0000-0000-0002-000000000001'::uuid, '2000-01-01 00:00:00.000001 +00:00', '00000000-0000-0000-0001-000000000001'::uuid),
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
-- Disable triggers on the tables
|
-- Disable triggers on the tables
|
||||||
|
|
||||||
-- Truncate tables
|
-- Truncate tables
|
||||||
TRUNCATE TABLE types;
|
TRUNCATE TABLE nodes CASCADE;
|
||||||
TRUNCATE TABLE devices;
|
TRUNCATE TABLE devices CASCADE;
|
||||||
TRUNCATE TABLE nodes;
|
TRUNCATE TABLE types CASCADE;
|
||||||
|
|
||||||
-- Enable triggers on the account table
|
-- Enable triggers on the account table
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
package ltd.hlaeja.controller
|
package ltd.hlaeja.controller
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import ltd.hlaeja.library.deviceRegistry.Type
|
import ltd.hlaeja.library.deviceRegistry.Type
|
||||||
import ltd.hlaeja.service.TypeService
|
import ltd.hlaeja.service.TypeService
|
||||||
import ltd.hlaeja.util.toTypeEntity
|
import ltd.hlaeja.util.toTypeEntity
|
||||||
import ltd.hlaeja.util.toTypeResponse
|
import ltd.hlaeja.util.toTypeResponse
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
import org.springframework.web.bind.annotation.RequestBody
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
@@ -16,9 +13,6 @@ class TypeController(
|
|||||||
private val service: TypeService,
|
private val service: TypeService,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@GetMapping("/types")
|
|
||||||
fun getTypes(): Flow<Type.Response> = service.getTypes().map { it.toTypeResponse() }
|
|
||||||
|
|
||||||
@PostMapping("/type")
|
@PostMapping("/type")
|
||||||
suspend fun addType(
|
suspend fun addType(
|
||||||
@RequestBody register: Type.Request,
|
@RequestBody register: Type.Request,
|
||||||
|
|||||||
36
src/main/kotlin/ltd/hlaeja/controller/TypesController.kt
Normal file
36
src/main/kotlin/ltd/hlaeja/controller/TypesController.kt
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package ltd.hlaeja.controller
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Min
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import ltd.hlaeja.library.deviceRegistry.Type
|
||||||
|
import ltd.hlaeja.service.TypeService
|
||||||
|
import ltd.hlaeja.util.toTypeResponse
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
class TypesController(
|
||||||
|
private val service: TypeService,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
const val DEFAULT_PAGE: Int = 1
|
||||||
|
const val DEFAULT_SIZE: Int = 25
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(
|
||||||
|
"/types",
|
||||||
|
"/types/page-{page}",
|
||||||
|
"/types/page-{page}/show-{show}",
|
||||||
|
"/types/filter-{filter}",
|
||||||
|
"/types/filter-{filter}/page-{page}",
|
||||||
|
"/types/filter-{filter}/page-{page}/show-{show}",
|
||||||
|
)
|
||||||
|
fun getTypes(
|
||||||
|
@PathVariable(required = false) @Min(1) page: Int = DEFAULT_PAGE,
|
||||||
|
@PathVariable(required = false) @Min(1) show: Int = DEFAULT_SIZE,
|
||||||
|
@PathVariable(required = false) filter: String? = null,
|
||||||
|
): Flow<Type.Response> = service.getTypes((page - 1) * show, show, filter)
|
||||||
|
.map { it.toTypeResponse() }
|
||||||
|
}
|
||||||
@@ -1,9 +1,27 @@
|
|||||||
package ltd.hlaeja.repository
|
package ltd.hlaeja.repository
|
||||||
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import ltd.hlaeja.entity.TypeEntity
|
import ltd.hlaeja.entity.TypeEntity
|
||||||
|
|
||||||
|
import org.springframework.data.r2dbc.repository.Query
|
||||||
import org.springframework.data.repository.kotlin.CoroutineCrudRepository
|
import org.springframework.data.repository.kotlin.CoroutineCrudRepository
|
||||||
|
import org.springframework.data.repository.query.Param
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
interface TypeRepository : CoroutineCrudRepository<TypeEntity, UUID>
|
interface TypeRepository : CoroutineCrudRepository<TypeEntity, UUID> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM types ORDER BY name LIMIT :limit OFFSET :offset")
|
||||||
|
fun findAll(
|
||||||
|
@Param("offset") offset: Int,
|
||||||
|
@Param("limit") limit: Int,
|
||||||
|
): Flow<TypeEntity>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM types WHERE name ILIKE :filter ORDER BY name LIMIT :limit OFFSET :offset")
|
||||||
|
fun findAllContaining(
|
||||||
|
@Param("filter") filter: String,
|
||||||
|
@Param("offset") offset: Int,
|
||||||
|
@Param("limit") limit: Int,
|
||||||
|
): Flow<TypeEntity>
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,7 +16,14 @@ class TypeService(
|
|||||||
private val typeRepository: TypeRepository,
|
private val typeRepository: TypeRepository,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun getTypes(): Flow<TypeEntity> = typeRepository.findAll()
|
fun getTypes(
|
||||||
|
page: Int,
|
||||||
|
show: Int,
|
||||||
|
filter: String?,
|
||||||
|
): Flow<TypeEntity> = when {
|
||||||
|
!filter.isNullOrEmpty() -> typeRepository.findAllContaining("%$filter%", page, show)
|
||||||
|
else -> typeRepository.findAll(page, show)
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun addType(
|
suspend fun addType(
|
||||||
entity: TypeEntity,
|
entity: TypeEntity,
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package ltd.hlaeja.assertj
|
|
||||||
|
|
||||||
import java.util.UUID
|
|
||||||
import org.assertj.core.api.AbstractAssert
|
|
||||||
|
|
||||||
class UUIDAssert(actual: UUID) : AbstractAssert<UUIDAssert, UUID>(actual, UUIDAssert::class.java) {
|
|
||||||
fun isUUID(expected: String): UUIDAssert {
|
|
||||||
objects.assertEqual(this.info, this.actual, UUID.fromString(expected))
|
|
||||||
return this.myself
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun assertThat(actual: UUID): UUIDAssert {
|
|
||||||
return UUIDAssert(actual)
|
|
||||||
}
|
|
||||||
@@ -8,9 +8,10 @@ import java.time.ZoneId
|
|||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import ltd.hlaeja.assertj.assertThat
|
|
||||||
import ltd.hlaeja.entity.NodeEntity
|
import ltd.hlaeja.entity.NodeEntity
|
||||||
import ltd.hlaeja.service.NodeService
|
import ltd.hlaeja.service.NodeService
|
||||||
|
import ltd.hlaeja.test.isEqualToUuid
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
@@ -48,8 +49,8 @@ class IdentityControllerTest {
|
|||||||
// then
|
// then
|
||||||
coVerify(exactly = 1) { service.getNodeFromDevice(any()) }
|
coVerify(exactly = 1) { service.getNodeFromDevice(any()) }
|
||||||
|
|
||||||
assertThat(response.node).isUUID("00000000-0000-0000-0000-000000000001")
|
assertThat(response.node).isEqualToUuid("00000000-0000-0000-0000-000000000001")
|
||||||
assertThat(response.client).isUUID("00000000-0000-0000-0000-000000000002")
|
assertThat(response.client).isEqualToUuid("00000000-0000-0000-0000-000000000002")
|
||||||
assertThat(response.device).isUUID("00000000-0000-0000-0000-000000000003")
|
assertThat(response.device).isEqualToUuid("00000000-0000-0000-0000-000000000003")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import io.mockk.coVerify
|
|||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import ltd.hlaeja.assertj.assertThat
|
|
||||||
import ltd.hlaeja.entity.NodeEntity
|
import ltd.hlaeja.entity.NodeEntity
|
||||||
import ltd.hlaeja.library.deviceRegistry.Node
|
import ltd.hlaeja.library.deviceRegistry.Node
|
||||||
import ltd.hlaeja.service.NodeService
|
import ltd.hlaeja.service.NodeService
|
||||||
|
import ltd.hlaeja.test.isEqualToUuid
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
@@ -42,9 +42,9 @@ class NodeControllerTest {
|
|||||||
// then
|
// then
|
||||||
coVerify(exactly = 1) { service.addNode(any()) }
|
coVerify(exactly = 1) { service.addNode(any()) }
|
||||||
|
|
||||||
assertThat(response.id).isUUID("00000000-0000-0000-0000-000000000003")
|
assertThat(response.id).isEqualToUuid("00000000-0000-0000-0000-000000000003")
|
||||||
assertThat(response.client).isUUID("00000000-0000-0000-0000-000000000001")
|
assertThat(response.client).isEqualToUuid("00000000-0000-0000-0000-000000000001")
|
||||||
assertThat(response.device).isUUID("00000000-0000-0000-0000-000000000002")
|
assertThat(response.device).isEqualToUuid("00000000-0000-0000-0000-000000000002")
|
||||||
assertThat(response.name).isEqualTo("test")
|
assertThat(response.name).isEqualTo("test")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,16 @@ package ltd.hlaeja.controller
|
|||||||
|
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.coVerify
|
import io.mockk.coVerify
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import kotlinx.coroutines.flow.single
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import ltd.hlaeja.entity.TypeEntity
|
import ltd.hlaeja.entity.TypeEntity
|
||||||
import ltd.hlaeja.library.deviceRegistry.Type
|
import ltd.hlaeja.library.deviceRegistry.Type
|
||||||
import ltd.hlaeja.service.TypeService
|
import ltd.hlaeja.service.TypeService
|
||||||
import ltd.hlaeja.assertj.assertThat
|
import ltd.hlaeja.test.isEqualToUuid
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
@@ -36,22 +32,7 @@ class TypeControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get all types`() = runTest {
|
fun `add type`() = runTest {
|
||||||
// given
|
|
||||||
every { service.getTypes() } returns flowOf(TypeEntity(id, timestamp, "name"))
|
|
||||||
|
|
||||||
// when
|
|
||||||
val response = controller.getTypes().single()
|
|
||||||
|
|
||||||
// then
|
|
||||||
verify(exactly = 1) { service.getTypes() }
|
|
||||||
|
|
||||||
assertThat(response.id).isUUID("00000000-0000-0000-0000-000000000000")
|
|
||||||
assertThat(response.name).isEqualTo("name")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `add types`() = runTest {
|
|
||||||
// given
|
// given
|
||||||
val request = Type.Request("name")
|
val request = Type.Request("name")
|
||||||
coEvery { service.addType(any()) } returns TypeEntity(id, timestamp, "name")
|
coEvery { service.addType(any()) } returns TypeEntity(id, timestamp, "name")
|
||||||
@@ -62,7 +43,7 @@ class TypeControllerTest {
|
|||||||
// then
|
// then
|
||||||
coVerify(exactly = 1) { service.addType(any()) }
|
coVerify(exactly = 1) { service.addType(any()) }
|
||||||
|
|
||||||
assertThat(response.id).isUUID("00000000-0000-0000-0000-000000000000")
|
assertThat(response.id).isEqualToUuid("00000000-0000-0000-0000-000000000000")
|
||||||
assertThat(response.name).isEqualTo("name")
|
assertThat(response.name).isEqualTo("name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/test/kotlin/ltd/hlaeja/controller/TypesControllerTest.kt
Normal file
49
src/test/kotlin/ltd/hlaeja/controller/TypesControllerTest.kt
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package ltd.hlaeja.controller
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.ZonedDateTime
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.single
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import ltd.hlaeja.entity.TypeEntity
|
||||||
|
import ltd.hlaeja.service.TypeService
|
||||||
|
import ltd.hlaeja.test.isEqualToUuid
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class TypesControllerTest {
|
||||||
|
companion object {
|
||||||
|
val id = UUID.fromString("00000000-0000-0000-0000-000000000000")
|
||||||
|
val timestamp = ZonedDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0, 0, 1), ZoneId.of("UTC"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val service: TypeService = mockk()
|
||||||
|
|
||||||
|
lateinit var controller: TypesController
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setUp() {
|
||||||
|
controller = TypesController(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get all types`() = runTest {
|
||||||
|
// given
|
||||||
|
every { service.getTypes(any(), any(), any()) } returns flowOf(TypeEntity(id, timestamp, "name"))
|
||||||
|
|
||||||
|
// when
|
||||||
|
val response = controller.getTypes().single()
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(exactly = 1) { service.getTypes(0, 25, null) }
|
||||||
|
|
||||||
|
assertThat(response.id).isEqualToUuid("00000000-0000-0000-0000-000000000000")
|
||||||
|
assertThat(response.name).isEqualTo("name")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,13 +37,27 @@ class TypeServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `get all types`() {
|
fun `get all types`() {
|
||||||
// given
|
// given
|
||||||
every { repository.findAll() } returns flowOf(mockk<TypeEntity>())
|
every { repository.findAll(any(), any()) } returns flowOf(mockk<TypeEntity>())
|
||||||
|
|
||||||
// when
|
// when
|
||||||
service.getTypes()
|
service.getTypes(1, 10, null)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(exactly = 1) { repository.findAll() }
|
verify(exactly = 1) { repository.findAll(1, 10) }
|
||||||
|
verify(exactly = 0) { repository.findAllContaining(any(), any(), any()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get all types with filter`() {
|
||||||
|
// given
|
||||||
|
every { repository.findAllContaining(any(), any(), any()) } returns flowOf(mockk<TypeEntity>())
|
||||||
|
|
||||||
|
// when
|
||||||
|
service.getTypes(1, 10, "abc")
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(exactly = 1) { repository.findAllContaining("%abc%", 1, 10) }
|
||||||
|
verify(exactly = 0) { repository.findAll(any(), any()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import java.time.ZoneId
|
|||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import ltd.hlaeja.assertj.assertThat
|
|
||||||
import ltd.hlaeja.entity.NodeEntity
|
import ltd.hlaeja.entity.NodeEntity
|
||||||
import ltd.hlaeja.entity.TypeEntity
|
import ltd.hlaeja.entity.TypeEntity
|
||||||
import ltd.hlaeja.library.deviceRegistry.Type
|
|
||||||
import ltd.hlaeja.library.deviceRegistry.Node
|
import ltd.hlaeja.library.deviceRegistry.Node
|
||||||
|
import ltd.hlaeja.library.deviceRegistry.Type
|
||||||
|
import ltd.hlaeja.test.isEqualToUuid
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.AfterEach
|
import org.junit.jupiter.api.AfterEach
|
||||||
import org.junit.jupiter.api.Assertions.assertThrows
|
import org.junit.jupiter.api.Assertions.assertThrows
|
||||||
@@ -68,7 +68,7 @@ class MappingKtTest {
|
|||||||
val response = entity.toTypeResponse()
|
val response = entity.toTypeResponse()
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(response.id).isUUID("00000000-0000-0000-0000-000000000000")
|
assertThat(response.id).isEqualToUuid("00000000-0000-0000-0000-000000000000")
|
||||||
assertThat(response.name).isEqualTo("name")
|
assertThat(response.name).isEqualTo("name")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,9 +119,9 @@ class MappingKtTest {
|
|||||||
val result = entity.toNodeResponse()
|
val result = entity.toNodeResponse()
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.id).isUUID("00000000-0000-0000-0000-000000000001")
|
assertThat(result.id).isEqualToUuid("00000000-0000-0000-0000-000000000001")
|
||||||
assertThat(result.client).isUUID("00000000-0000-0000-0000-000000000002")
|
assertThat(result.client).isEqualToUuid("00000000-0000-0000-0000-000000000002")
|
||||||
assertThat(result.device).isUUID("00000000-0000-0000-0000-000000000003")
|
assertThat(result.device).isEqualToUuid("00000000-0000-0000-0000-000000000003")
|
||||||
assertThat(result.name).isEqualTo("test")
|
assertThat(result.name).isEqualTo("test")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,9 +164,9 @@ class MappingKtTest {
|
|||||||
val result = entity.toIdentityResponse()
|
val result = entity.toIdentityResponse()
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result.node).isUUID("00000000-0000-0000-0000-000000000001")
|
assertThat(result.node).isEqualToUuid("00000000-0000-0000-0000-000000000001")
|
||||||
assertThat(result.client).isUUID("00000000-0000-0000-0000-000000000002")
|
assertThat(result.client).isEqualToUuid("00000000-0000-0000-0000-000000000002")
|
||||||
assertThat(result.device).isUUID("00000000-0000-0000-0000-000000000003")
|
assertThat(result.device).isEqualToUuid("00000000-0000-0000-0000-000000000003")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user