From 68a091eeb64e06d682664804f0be2fd05a407020 Mon Sep 17 00:00:00 2001 From: Alexei Yashkov Date: Sat, 24 Feb 2024 14:49:02 -0500 Subject: [PATCH] Story #4: introduce language parameter to the API --- .../doc/io/granito/segovia/spec/api/Api.md | 2 +- .../segovia/spec/api/sentences/Sentences.md | 17 ++--- .../test/doc/io/granito/segovia/spec/ui/Ui.md | 2 +- .../io/granito/segovia/spec/SpecBase.kt | 5 +- .../io/granito/segovia/core/model/Lang.kt | 12 ++++ .../io/granito/segovia/core/model/Sentence.kt | 4 +- .../segovia/core/service/SentenceService.kt | 9 +-- .../core/usecase/CreateSentenceCase.kt | 3 +- .../segovia/core/usecase/FetchSentenceCase.kt | 3 +- .../core/usecase/SearchSentencesCase.kt | 3 +- .../core/usecase/CreateSentenceCaseTest.kt | 7 ++- .../core/usecase/FetchSentenceCaseTest.kt | 5 +- .../core/usecase/SearchSentencesCaseTest.kt | 5 +- .../web/controller/SentenceController.kt | 19 ++++-- .../granito/segovia/web/model/RootResource.kt | 3 +- .../segovia/web/model/SentenceResource.kt | 6 +- .../web/controller/RootControllerTest.kt | 2 +- .../web/controller/SentenceControllerTest.kt | 62 ++++++++++--------- 18 files changed, 102 insertions(+), 67 deletions(-) create mode 100644 core/src/main/kotlin/io/granito/segovia/core/model/Lang.kt diff --git a/app/src/test/doc/io/granito/segovia/spec/api/Api.md b/app/src/test/doc/io/granito/segovia/spec/api/Api.md index d54bd6c..3b4b666 100644 --- a/app/src/test/doc/io/granito/segovia/spec/api/Api.md +++ b/app/src/test/doc/io/granito/segovia/spec/api/Api.md @@ -45,7 +45,7 @@ will contain JSON with the following HAL links:
{
   "_links": {
     "self": { "href": "/api/v1" },
-    "sentences": { "href": "/api/v1/sentences" }
+    "sentences": { "href": "/api/v1/languages/es/sentences" }
   }
 }
diff --git a/app/src/test/doc/io/granito/segovia/spec/api/sentences/Sentences.md b/app/src/test/doc/io/granito/segovia/spec/api/sentences/Sentences.md index 353fcc0..c98489a 100644 --- a/app/src/test/doc/io/granito/segovia/spec/api/sentences/Sentences.md +++ b/app/src/test/doc/io/granito/segovia/spec/api/sentences/Sentences.md @@ -4,7 +4,7 @@ All examples below assume that the application has only "[Roberto se había levantado de la cama.](- "#sentence")" -[sentence](- "store(#sentence)"). +[sentence](- "store('es', #sentence)"). ### ~~Common assumptions~~ @@ -15,7 +15,7 @@ collection. ### [Get sentences](-) When a client makes a -**[GET](- "#method") [/api/v1/sentences](- "#uri")** +**[GET](- "#method") [/api/v1/languages/es/sentences](- "#uri")** [HTTP request](- "#response=http(#method, #uri)"), then the application responds with [200](- "?=#response.status") HTTP status and [application/hal+json](- "?=#response.contentType") body containing @@ -23,7 +23,7 @@ JSON with at least following properties:
{
   "_links": {
-    "self": { "href": "/api/v1/sentences" }
+    "self": { "href": "/api/v1/languages/es/sentences" }
   },
   "_embedded": {
     "sentences": [
@@ -31,7 +31,7 @@ JSON with at least following properties:
         "id": "h6kLGAVxboVG",
         "text": "Roberto se había levantado de la cama.",
         "_links": {
-          "self": { "href": "/api/v1/sentences/h6kLGAVxboVG" }
+          "self": { "href": "/api/v1/languages/es/sentences/h6kLGAVxboVG" }
         }
       }
     ]
@@ -48,7 +48,8 @@ it will be returned as a HAL resource.
 ### [Get sentence](-)
 
 When a client makes a
-**[GET](- "#method") [/api/v1/sentences/h6kLGAVxboVG](- "#uri")**
+**[GET](- "#method")
+[/api/v1/languages/es/sentences/h6kLGAVxboVG](- "#uri")**
 [HTTP request](- "#response=http(#method, #uri)"), then the application
 responds with [200](- "?=#response.status") HTTP status and
 [application/hal+json](- "?=#response.contentType") body containing
@@ -58,7 +59,7 @@ JSON with at least following properties:
   "id": "h6kLGAVxboVG",
   "text": "Roberto se había levantado de la cama.",
   "_links": {
-    "self": { "href": "/api/v1/sentences/h6kLGAVxboVG" }
+    "self": { "href": "/api/v1/languages/es/sentences/h6kLGAVxboVG" }
   }
 }
@@ -70,7 +71,7 @@ respond with `404` HTTP status code. ### [Not found](-) When a client makes a -**[GET](- "#method") [/api/v1/sentences/unknown](- "#uri")** +**[GET](- "#method") [/api/v1/languages/es/sentences/unknown](- "#uri")** [HTTP request](- "#response=http(#method, #uri)"), then the application responds with [404](- "?=#response.status") HTTP status and [application/problem+json](- "?=#response.contentType") body containing @@ -81,7 +82,7 @@ JSON with at least following properties: "type": "https://segovia.granito.io/problem/not-found/sentence", "title": "Sentence is not found.", "detail": "Sentence identified by 'unknown' is not found.", - "instance": "/api/v1/sentences/unknown" + "instance": "/api/v1/languages/es/sentences/unknown" } ### ~~Not found~~ diff --git a/app/src/test/doc/io/granito/segovia/spec/ui/Ui.md b/app/src/test/doc/io/granito/segovia/spec/ui/Ui.md index bfb40f2..096a0c4 100644 --- a/app/src/test/doc/io/granito/segovia/spec/ui/Ui.md +++ b/app/src/test/doc/io/granito/segovia/spec/ui/Ui.md @@ -25,7 +25,7 @@ language using a text in the target language. Given that the application has "[Roberto se había levantado de la cama.](- "#sentence")" -[sentence](- "store(#sentence)"), when a user accesses +[sentence](- "store('es', #sentence)"), when a user accesses **[/study](- "load(#TEXT)")** URI, then: * the browser navigates to [/study](- "?=uri") URI; diff --git a/app/src/test/kotlin/io/granito/segovia/spec/SpecBase.kt b/app/src/test/kotlin/io/granito/segovia/spec/SpecBase.kt index 32b460a..fc1273b 100644 --- a/app/src/test/kotlin/io/granito/segovia/spec/SpecBase.kt +++ b/app/src/test/kotlin/io/granito/segovia/spec/SpecBase.kt @@ -1,5 +1,6 @@ package io.granito.segovia.spec +import io.granito.segovia.core.model.langFrom import io.granito.segovia.core.repo.SentenceRepo import io.granito.segovia.core.usecase.CreateSentenceCase import org.concordion.api.AfterExample @@ -28,8 +29,8 @@ abstract class SpecBase { sentenceRepo.clear().block() } - fun store(text: String) { - createSentenceCase.create(text).block() + fun store(lang: String, text: String) { + createSentenceCase.create(langFrom(lang), text).block() } fun contains(string: String?, sub: String?) = diff --git a/core/src/main/kotlin/io/granito/segovia/core/model/Lang.kt b/core/src/main/kotlin/io/granito/segovia/core/model/Lang.kt new file mode 100644 index 0000000..2d3bbea --- /dev/null +++ b/core/src/main/kotlin/io/granito/segovia/core/model/Lang.kt @@ -0,0 +1,12 @@ +package io.granito.segovia.core.model + +fun langFrom(code: String) = Lang.valueOf(code.uppercase()) + +enum class Lang { + EN, + ES, + FR, + IT; + + override fun toString() = name.lowercase() +} diff --git a/core/src/main/kotlin/io/granito/segovia/core/model/Sentence.kt b/core/src/main/kotlin/io/granito/segovia/core/model/Sentence.kt index 1994efe..28dcbcf 100644 --- a/core/src/main/kotlin/io/granito/segovia/core/model/Sentence.kt +++ b/core/src/main/kotlin/io/granito/segovia/core/model/Sentence.kt @@ -1,5 +1,5 @@ package io.granito.segovia.core.model -class Sentence(val id: Slug, val text: String) { - constructor(text: String): this(Slug.of(text), text) +class Sentence(val lang: Lang, val id: Slug, val text: String) { + constructor(lang: Lang, text: String): this(lang, Slug.of(text), text) } diff --git a/core/src/main/kotlin/io/granito/segovia/core/service/SentenceService.kt b/core/src/main/kotlin/io/granito/segovia/core/service/SentenceService.kt index fc4e6df..0997162 100644 --- a/core/src/main/kotlin/io/granito/segovia/core/service/SentenceService.kt +++ b/core/src/main/kotlin/io/granito/segovia/core/service/SentenceService.kt @@ -1,5 +1,6 @@ package io.granito.segovia.core.service +import io.granito.segovia.core.model.Lang import io.granito.segovia.core.model.Sentence import io.granito.segovia.core.model.Slug import io.granito.segovia.core.repo.SentenceRepo @@ -11,23 +12,23 @@ import reactor.core.publisher.Mono class SentenceService(private val sentenceRepo: SentenceRepo): SearchSentencesCase, FetchSentenceCase, CreateSentenceCase { - override fun search(): Flux = + override fun search(lang: Lang): Flux = try { sentenceRepo.select() } catch (ex: Exception) { Flux.error(ex) } - override fun fetch(id: Slug): Mono = + override fun fetch(lang: Lang, id: Slug): Mono = try { sentenceRepo.load(id) } catch (ex: Exception) { Mono.error(ex) } - override fun create(text: String): Mono = + override fun create(lang: Lang, text: String): Mono = try { - val sentence = Sentence(text) + val sentence = Sentence(lang, text) sentenceRepo.insert(sentence).thenReturn(sentence) } catch (ex: Exception) { diff --git a/core/src/main/kotlin/io/granito/segovia/core/usecase/CreateSentenceCase.kt b/core/src/main/kotlin/io/granito/segovia/core/usecase/CreateSentenceCase.kt index 0f6d8dd..9e47d61 100644 --- a/core/src/main/kotlin/io/granito/segovia/core/usecase/CreateSentenceCase.kt +++ b/core/src/main/kotlin/io/granito/segovia/core/usecase/CreateSentenceCase.kt @@ -1,8 +1,9 @@ package io.granito.segovia.core.usecase +import io.granito.segovia.core.model.Lang import io.granito.segovia.core.model.Sentence import reactor.core.publisher.Mono interface CreateSentenceCase { - fun create(text: String): Mono + fun create(lang: Lang, text: String): Mono } diff --git a/core/src/main/kotlin/io/granito/segovia/core/usecase/FetchSentenceCase.kt b/core/src/main/kotlin/io/granito/segovia/core/usecase/FetchSentenceCase.kt index 4386d7e..9b34f98 100644 --- a/core/src/main/kotlin/io/granito/segovia/core/usecase/FetchSentenceCase.kt +++ b/core/src/main/kotlin/io/granito/segovia/core/usecase/FetchSentenceCase.kt @@ -1,9 +1,10 @@ package io.granito.segovia.core.usecase +import io.granito.segovia.core.model.Lang import io.granito.segovia.core.model.Sentence import io.granito.segovia.core.model.Slug import reactor.core.publisher.Mono interface FetchSentenceCase { - fun fetch(id: Slug): Mono + fun fetch(lang: Lang, id: Slug): Mono } diff --git a/core/src/main/kotlin/io/granito/segovia/core/usecase/SearchSentencesCase.kt b/core/src/main/kotlin/io/granito/segovia/core/usecase/SearchSentencesCase.kt index f93f443..d8e8b06 100644 --- a/core/src/main/kotlin/io/granito/segovia/core/usecase/SearchSentencesCase.kt +++ b/core/src/main/kotlin/io/granito/segovia/core/usecase/SearchSentencesCase.kt @@ -1,8 +1,9 @@ package io.granito.segovia.core.usecase +import io.granito.segovia.core.model.Lang import io.granito.segovia.core.model.Sentence import reactor.core.publisher.Flux interface SearchSentencesCase { - fun search(): Flux + fun search(lang: Lang): Flux } diff --git a/core/src/test/kotlin/io/granito/segovia/core/usecase/CreateSentenceCaseTest.kt b/core/src/test/kotlin/io/granito/segovia/core/usecase/CreateSentenceCaseTest.kt index 226d2f6..8fed91c 100644 --- a/core/src/test/kotlin/io/granito/segovia/core/usecase/CreateSentenceCaseTest.kt +++ b/core/src/test/kotlin/io/granito/segovia/core/usecase/CreateSentenceCaseTest.kt @@ -1,5 +1,6 @@ package io.granito.segovia.core.usecase +import io.granito.segovia.core.model.Lang import io.granito.segovia.core.model.Slug import io.granito.segovia.core.repo.SentenceRepo import io.granito.segovia.core.service.SentenceService @@ -37,7 +38,7 @@ class CreateSentenceCaseTest { id == slug && text == sentence }) - StepVerifier.create(service.create("Llueve mucho.")) + StepVerifier.create(service.create(Lang.ES, "Llueve mucho.")) .assertNext { assertThat(it.id).isEqualTo(slug) assertThat(it.text).isEqualTo(sentence) @@ -54,7 +55,7 @@ class CreateSentenceCaseTest { doReturn(result).whenever(sentenceRepo).insert(any()) - StepVerifier.create(service.create("Se acabo.")) + StepVerifier.create(service.create(Lang.ES, "Se acabo.")) .verifyErrorSatisfies { assertThat(it).isSameAs(t) } @@ -66,7 +67,7 @@ class CreateSentenceCaseTest { doThrow(t).whenever(sentenceRepo).insert(any()) - StepVerifier.create(service.create("Se acabo.")) + StepVerifier.create(service.create(Lang.ES, "Se acabo.")) .verifyErrorSatisfies { assertThat(it).isSameAs(t) } diff --git a/core/src/test/kotlin/io/granito/segovia/core/usecase/FetchSentenceCaseTest.kt b/core/src/test/kotlin/io/granito/segovia/core/usecase/FetchSentenceCaseTest.kt index 860d52c..edede9c 100644 --- a/core/src/test/kotlin/io/granito/segovia/core/usecase/FetchSentenceCaseTest.kt +++ b/core/src/test/kotlin/io/granito/segovia/core/usecase/FetchSentenceCaseTest.kt @@ -1,5 +1,6 @@ package io.granito.segovia.core.usecase +import io.granito.segovia.core.model.Lang import io.granito.segovia.core.model.Sentence import io.granito.segovia.core.model.Slug import io.granito.segovia.core.repo.SentenceRepo @@ -35,7 +36,7 @@ class FetchSentenceCaseTest { fun `fetch() returns same data as repo when load succeeds`() { doReturn(result).whenever(sentenceRepo).load(id) - assertThat(service.fetch(id)).isSameAs(result) + assertThat(service.fetch(Lang.EN, id)).isSameAs(result) } @Test @@ -44,7 +45,7 @@ class FetchSentenceCaseTest { doThrow(t).whenever(sentenceRepo).load(any()) - StepVerifier.create(service.fetch(id)) + StepVerifier.create(service.fetch(Lang.EN, id)) .verifyErrorSatisfies { assertThat(it).isSameAs(t) } diff --git a/core/src/test/kotlin/io/granito/segovia/core/usecase/SearchSentencesCaseTest.kt b/core/src/test/kotlin/io/granito/segovia/core/usecase/SearchSentencesCaseTest.kt index c6ec5e2..4794d40 100644 --- a/core/src/test/kotlin/io/granito/segovia/core/usecase/SearchSentencesCaseTest.kt +++ b/core/src/test/kotlin/io/granito/segovia/core/usecase/SearchSentencesCaseTest.kt @@ -1,5 +1,6 @@ package io.granito.segovia.core.usecase +import io.granito.segovia.core.model.Lang import io.granito.segovia.core.model.Sentence import io.granito.segovia.core.repo.SentenceRepo import io.granito.segovia.core.service.SentenceService @@ -31,7 +32,7 @@ class SearchSentencesCaseTest { fun `search() returns same data as repo when select succeeds`() { doReturn(result).whenever(sentenceRepo).select() - assertThat(service.search()).isSameAs(result) + assertThat(service.search(Lang.EN)).isSameAs(result) } @Test @@ -40,7 +41,7 @@ class SearchSentencesCaseTest { doThrow(t).whenever(sentenceRepo).select() - StepVerifier.create(service.search()) + StepVerifier.create(service.search(Lang.ES)) .verifyErrorSatisfies { assertThat(it).isSameAs(t) } diff --git a/web/src/main/kotlin/io/granito/segovia/web/controller/SentenceController.kt b/web/src/main/kotlin/io/granito/segovia/web/controller/SentenceController.kt index 3794fa4..4d16600 100644 --- a/web/src/main/kotlin/io/granito/segovia/web/controller/SentenceController.kt +++ b/web/src/main/kotlin/io/granito/segovia/web/controller/SentenceController.kt @@ -1,6 +1,7 @@ package io.granito.segovia.web.controller import io.granito.segovia.core.model.Slug +import io.granito.segovia.core.model.langFrom import io.granito.segovia.core.usecase.FetchSentenceCase import io.granito.segovia.core.usecase.SearchSentencesCase import io.granito.segovia.web.model.SentenceNotFoundException @@ -14,7 +15,9 @@ import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController import reactor.core.publisher.Mono -const val SENTENCES = "$ROOT/sentences" +const val LANGUAGES = "$ROOT/languages" +const val LANGUAGE = "$LANGUAGES/{lang}" +const val SENTENCES = "$LANGUAGE/sentences" const val SENTENCE = "$SENTENCES/{id}" @RestController @@ -23,24 +26,28 @@ class SentenceController( private val searchSentencesCase: SearchSentencesCase, private val fetchSentenceCase: FetchSentenceCase) { @GetMapping(SENTENCES) - fun get(): Mono> = + fun get(@PathVariable("lang") code: String): + Mono> = try { - searchSentencesCase.search() + val lang = langFrom(code) + + searchSentencesCase.search(lang) .map { SentenceResource(it) } .collectList() .map { CollectionModel.of(it) .withFallbackType(SentenceResource::class.java) - .add(Link.of(SENTENCES)) + .add(Link.of(SENTENCES).expand(lang)) } } catch (ex: Exception) { Mono.error(ex) } @GetMapping(SENTENCE) - fun getOne(@PathVariable("id") id: String): Mono = + fun getOne(@PathVariable("lang") code: String, + @PathVariable("id") id: String): Mono = try { - fetchSentenceCase.fetch(Slug(id)) + fetchSentenceCase.fetch(langFrom(code), Slug(id)) .map { SentenceResource(it) } .switchIfEmpty(Mono.error(SentenceNotFoundException(id))) } catch (ex: Exception) { diff --git a/web/src/main/kotlin/io/granito/segovia/web/model/RootResource.kt b/web/src/main/kotlin/io/granito/segovia/web/model/RootResource.kt index 75fe68f..24cb603 100644 --- a/web/src/main/kotlin/io/granito/segovia/web/model/RootResource.kt +++ b/web/src/main/kotlin/io/granito/segovia/web/model/RootResource.kt @@ -5,6 +5,7 @@ import io.granito.segovia.web.controller.ROOT import io.granito.segovia.web.controller.SENTENCES import org.springframework.hateoas.Link import org.springframework.hateoas.RepresentationModel +import org.springframework.hateoas.UriTemplate import org.springframework.hateoas.server.core.Relation @Relation(itemRelation = "root") @@ -16,7 +17,7 @@ class RootResource(val status: String, val apiVersion: String): init { add( Link.of(ROOT), - Link.of(SENTENCES, "sentences") + Link.of(UriTemplate.of(SENTENCES), "sentences").expand("es") ) } } diff --git a/web/src/main/kotlin/io/granito/segovia/web/model/SentenceResource.kt b/web/src/main/kotlin/io/granito/segovia/web/model/SentenceResource.kt index cb53a9e..a685b0b 100644 --- a/web/src/main/kotlin/io/granito/segovia/web/model/SentenceResource.kt +++ b/web/src/main/kotlin/io/granito/segovia/web/model/SentenceResource.kt @@ -7,12 +7,12 @@ import org.springframework.hateoas.RepresentationModel import org.springframework.hateoas.server.core.Relation @Relation(itemRelation = "sentence", collectionRelation = "sentences") -class SentenceResource(val id: String, val text: String): +class SentenceResource(language: String, val id: String, val text: String): RepresentationModel() { constructor(sentence: Sentence): - this(sentence.id.toString(), sentence.text) + this(sentence.lang.toString(), sentence.id.toString(), sentence.text) init { - add(Link.of(SENTENCE).expand(id)) + add(Link.of(SENTENCE).expand(language, id)) } } diff --git a/web/src/test/kotlin/io/granito/segovia/web/controller/RootControllerTest.kt b/web/src/test/kotlin/io/granito/segovia/web/controller/RootControllerTest.kt index 36a401b..229dd91 100644 --- a/web/src/test/kotlin/io/granito/segovia/web/controller/RootControllerTest.kt +++ b/web/src/test/kotlin/io/granito/segovia/web/controller/RootControllerTest.kt @@ -86,7 +86,7 @@ internal class RootControllerTest { StepVerifier.create(controller.get()) .assertNext { assertThat(it.getRequiredLink("sentences").href) - .isEqualTo("/api/v1/sentences") + .isEqualTo("/api/v1/languages/es/sentences") } .verifyComplete() } diff --git a/web/src/test/kotlin/io/granito/segovia/web/controller/SentenceControllerTest.kt b/web/src/test/kotlin/io/granito/segovia/web/controller/SentenceControllerTest.kt index ef7c34e..69fe781 100644 --- a/web/src/test/kotlin/io/granito/segovia/web/controller/SentenceControllerTest.kt +++ b/web/src/test/kotlin/io/granito/segovia/web/controller/SentenceControllerTest.kt @@ -1,5 +1,6 @@ package io.granito.segovia.web.controller +import io.granito.segovia.core.model.Lang import io.granito.segovia.core.model.Sentence import io.granito.segovia.core.model.Slug import io.granito.segovia.core.usecase.FetchSentenceCase @@ -41,9 +42,9 @@ class SentenceControllerTest { .complete() .flux() - doReturn(sentences).whenever(searchSentencesCase).search() + doReturn(sentences).whenever(searchSentencesCase).search(Lang.EN) - StepVerifier.create(controller.get()) + StepVerifier.create(controller.get("en")) .assertNext { assertThat(it.resolvableType.resolveGeneric()) .isEqualTo(SentenceResource::class.java) @@ -56,14 +57,14 @@ class SentenceControllerTest { fun `get() emits collection of resources when search() emits sentences`() { val sentences = createCold() .emit( - Sentence(Slug("deadbeef"), "One."), - Sentence(Slug("babefeed"), "Two.") + Sentence(Lang.EN, Slug("deadbeef"), "One."), + Sentence(Lang.EN, Slug("babefeed"), "Two.") ) .flux() - doReturn(sentences).whenever(searchSentencesCase).search() + doReturn(sentences).whenever(searchSentencesCase).search(Lang.EN) - StepVerifier.create(controller.get()) + StepVerifier.create(controller.get("en")) .assertNext { assertThat(it.resolvableType.resolveGeneric()) .isEqualTo(SentenceResource::class.java) @@ -80,15 +81,15 @@ class SentenceControllerTest { @Test fun `get() adds self link to collection`() { val sentences = createCold() - .emit(Sentence("Llueve.")) + .emit(Sentence(Lang.ES, "Llueve.")) .flux() - doReturn(sentences).whenever(searchSentencesCase).search() + doReturn(sentences).whenever(searchSentencesCase).search(Lang.ES) - StepVerifier.create(controller.get()) + StepVerifier.create(controller.get("es")) .assertNext { assertThat(it.getRequiredLink("self").href) - .isEqualTo("/api/v1/sentences") + .isEqualTo("/api/v1/languages/es/sentences") } .verifyComplete() } @@ -97,13 +98,13 @@ class SentenceControllerTest { fun `get() propagates error, when search() emits error`() { val t = RuntimeException("sentences") val error = createCold() - .next(Sentence("Se acabo.")) + .next(Sentence(Lang.ES, "Se acabo.")) .error(t) .flux() - doReturn(error).whenever(searchSentencesCase).search() + doReturn(error).whenever(searchSentencesCase).search(Lang.ES) - StepVerifier.create(controller.get()) + StepVerifier.create(controller.get("es")) .verifyErrorSatisfies { assertThat(it).isSameAs(t) } @@ -113,9 +114,9 @@ class SentenceControllerTest { fun `get() wraps exception, when search() fails`() { val t = RuntimeException("sentences") - doThrow(t).whenever(searchSentencesCase).search() + doThrow(t).whenever(searchSentencesCase).search(Lang.FR) - StepVerifier.create(controller.get()) + StepVerifier.create(controller.get("fr")) .verifyErrorSatisfies { assertThat(it).isSameAs(t) } @@ -127,9 +128,10 @@ class SentenceControllerTest { .complete() .mono() - doReturn(sentence).whenever(fetchSentenceCase).fetch(Slug("deadbeef")) + doReturn(sentence).whenever(fetchSentenceCase) + .fetch(Lang.IT, Slug("deadbeef")) - StepVerifier.create(controller.getOne("deadbeef")) + StepVerifier.create(controller.getOne("it", "deadbeef")) .verifyErrorSatisfies { assertThat(it) .isInstanceOf(SentenceNotFoundException::class.java) @@ -140,12 +142,13 @@ class SentenceControllerTest { @Test fun `getOne() emits sentence when it exists`() { val sentence = createCold() - .emit(Sentence(Slug("deadbeef"), "Get it.")) + .emit(Sentence(Lang.EN, Slug("deadbeef"), "Get it.")) .mono() - doReturn(sentence).whenever(fetchSentenceCase).fetch(Slug("deadbeef")) + doReturn(sentence).whenever(fetchSentenceCase) + .fetch(Lang.EN, Slug("deadbeef")) - StepVerifier.create(controller.getOne("deadbeef")) + StepVerifier.create(controller.getOne("en", "deadbeef")) .assertNext { assertThat(it.id).isEqualTo("deadbeef") assertThat(it.text).isEqualTo("Get it.") @@ -156,15 +159,16 @@ class SentenceControllerTest { @Test fun `getOne() adds self link when it returns the sentence`() { val sentence = createCold() - .emit(Sentence(Slug("deadbeef"), "Get it.")) + .emit(Sentence(Lang.EN, Slug("deadbeef"), "Get it.")) .mono() - doReturn(sentence).whenever(fetchSentenceCase).fetch(Slug("deadbeef")) + doReturn(sentence).whenever(fetchSentenceCase) + .fetch(Lang.EN, Slug("deadbeef")) - StepVerifier.create(controller.getOne("deadbeef")) + StepVerifier.create(controller.getOne("en", "deadbeef")) .assertNext { assertThat(it.getRequiredLink("self").href) - .isEqualTo("/api/v1/sentences/deadbeef") + .isEqualTo("/api/v1/languages/en/sentences/deadbeef") } .verifyComplete() } @@ -176,9 +180,10 @@ class SentenceControllerTest { .error(t) .mono() - doReturn(error).whenever(fetchSentenceCase).fetch(Slug("deadbeef")) + doReturn(error).whenever(fetchSentenceCase).fetch( + Lang.IT, Slug("deadbeef")) - StepVerifier.create(controller.getOne("deadbeef")) + StepVerifier.create(controller.getOne("it", "deadbeef")) .verifyErrorSatisfies { assertThat(it).isSameAs(t) } @@ -188,9 +193,10 @@ class SentenceControllerTest { fun `getOne() wraps exception, when fetch() fails`() { val t = RuntimeException("sentence") - doThrow(t).whenever(fetchSentenceCase).fetch(Slug("deadbeef")) + doThrow(t).whenever(fetchSentenceCase).fetch( + Lang.IT, Slug("deadbeef")) - StepVerifier.create(controller.getOne("deadbeef")) + StepVerifier.create(controller.getOne("it", "deadbeef")) .verifyErrorSatisfies { assertThat(it).isSameAs(t) }