-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: #185 fix conflict in kodemy-search/build.gradle
- Loading branch information
Showing
5 changed files
with
332 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
kodemy-search/src/test/groovy/pl/sknikod/kodemysearch/SuperclassSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package pl.sknikod.kodemysearch | ||
|
||
import com.github.tomakehurst.wiremock.WireMockServer | ||
import com.github.tomakehurst.wiremock.core.WireMockConfiguration | ||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration | ||
import org.springframework.boot.test.context.SpringBootTest | ||
import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration | ||
import org.springframework.test.context.ContextConfiguration | ||
import org.springframework.test.context.DynamicPropertyRegistry | ||
import org.springframework.test.context.DynamicPropertySource | ||
import org.testcontainers.spock.Testcontainers | ||
import spock.lang.Specification | ||
|
||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) | ||
@ContextConfiguration(classes = KodemySearchApplication.class) | ||
@ImportAutoConfiguration(value = TestChannelBinderConfiguration.class) | ||
@Testcontainers | ||
abstract class SuperclassSpec extends Specification { | ||
|
||
protected static final WireMockServer WIREMOCK | ||
protected static int WIREMOCK_PORT = 9999 | ||
|
||
static { | ||
WIREMOCK = new WireMockServer( | ||
WireMockConfiguration.options() | ||
.port(WIREMOCK_PORT) | ||
) | ||
} | ||
|
||
@DynamicPropertySource | ||
private static void containerProperties(DynamicPropertyRegistry registry) { | ||
|
||
final String wiremockBaseUrl = "http://localhost:${WIREMOCK_PORT}" | ||
|
||
Map.of( | ||
"opensearch.host", wiremockBaseUrl, | ||
"opensearch.username", "admin", | ||
"opensearch.password", "admin", | ||
"opensearch.indices.materials.name", "materials", | ||
"opensearch.indices.materials.alias", "materials-alias", | ||
"service.baseUrl.gateway", "${wiremockBaseUrl}/gateway", | ||
"eureka.client.enabled", false, | ||
).forEach { | ||
key, value -> registry.add(key, { value }) | ||
} | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
...earch/src/test/groovy/pl/sknikod/kodemysearch/module/material/MaterialSearchHelper.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package pl.sknikod.kodemysearch.module.material | ||
|
||
import pl.sknikod.kodemysearch.configuration.LogbookConfiguration | ||
import pl.sknikod.kodemysearch.configuration.OpenSearchConfiguration | ||
import pl.sknikod.kodemysearch.infrastructure.module.material.MaterialSearchService | ||
import pl.sknikod.kodemysearch.infrastructure.module.material.MaterialSearchService$MaterialSearchMapperImpl | ||
import pl.sknikod.kodemysearch.infrastructure.store.MaterialSearchStore | ||
import pl.sknikod.kodemysearch.util.opensearch.OpenSearchClientEnhanced | ||
|
||
class MaterialSearchHelper { | ||
|
||
static MaterialSearchService createMaterialSearchService(String host = "http://localhost:9999", | ||
String username = "admin", | ||
String password = "admin", | ||
String indexName = "materials", | ||
String aliasName = "materials-alias") { | ||
def properties = new OpenSearchConfiguration.OpenSearchProperties( | ||
host: host, | ||
username: username, | ||
password: password, | ||
indices: [ | ||
"materials": new OpenSearchClientEnhanced.Index( | ||
name: indexName, | ||
alias: aliasName | ||
) | ||
] | ||
) | ||
|
||
def openSearchClient = new OpenSearchConfiguration().openSearchClient( | ||
properties, | ||
new LogbookConfiguration().logbook() | ||
) | ||
|
||
def materialSearchStore = new MaterialSearchStore(openSearchClient) | ||
|
||
return new MaterialSearchService( | ||
materialSearchStore, | ||
new MaterialSearchService$MaterialSearchMapperImpl() | ||
) | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
.../src/test/groovy/pl/sknikod/kodemysearch/module/material/MaterialSearchServiceSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package pl.sknikod.kodemysearch.module.material | ||
|
||
|
||
import org.springframework.data.domain.PageRequest | ||
import pl.sknikod.kodemysearch.infrastructure.module.material.MaterialSearchService | ||
import pl.sknikod.kodemysearch.infrastructure.module.material.MaterialSearchService$MaterialSearchMapperImpl | ||
import pl.sknikod.kodemysearch.infrastructure.store.MaterialSearchStore | ||
import spock.lang.Specification | ||
import spock.lang.Subject | ||
import spock.lang.Unroll | ||
|
||
import static pl.sknikod.kodemysearch.infrastructure.rest.MaterialControllerDefinition.* | ||
|
||
class MaterialSearchServiceSpec extends Specification { | ||
|
||
def materialSearchStore = Mock(MaterialSearchStore) | ||
|
||
@Subject | ||
MaterialSearchService materialSearchService = new MaterialSearchService(materialSearchStore, new MaterialSearchService$MaterialSearchMapperImpl()) | ||
|
||
@Unroll | ||
def "should create search criteria from filter search params for #description"() { | ||
given: | ||
def filterSearchParams = params | ||
def pageable = PageRequest.of(0, 10) | ||
|
||
when: | ||
try { | ||
materialSearchService.search(filterSearchParams as MaterialFilterSearchParams, pageable) | ||
} catch (Exception ignored) { | ||
// We don't care about the result. We only check creating search criteria | ||
} | ||
|
||
then: "search criteria are created based on filter search params" | ||
1 * materialSearchStore.search({ | ||
it.anyPhrase == filterSearchParams.phrase && | ||
it.pageable == pageable && | ||
it.phraseFields.size() == expected.phraseFieldsCount && | ||
it.phraseFields.any { field -> field.name == "id" && field.value == filterSearchParams.id.toString() } && | ||
it.phraseFields.any { field -> field.name == "sectionId" && field.value == filterSearchParams.sectionId.toString() } && | ||
it.arrayFields.size() == expected.arrayFieldsCount && | ||
it.arrayFields.any { field -> field.name == "categoryId" && field.values == filterSearchParams.categoryIds.collect { it.toString() } } && | ||
it.rangeFields.size() == expected.rangeFieldsCount && | ||
it.rangeFields.any { field -> field.name == "avgGrade" && field.from == filterSearchParams.minAvgGrade && field.to == filterSearchParams.maxAvgGrade } | ||
}) | ||
|
||
where: | ||
[params, expected, description] << searchParamsProvider() | ||
} | ||
|
||
def searchParamsProvider() { | ||
return [[ | ||
params: new MaterialFilterSearchParams( | ||
phrase: "phrase1", | ||
id: 1L, | ||
sectionId: 1L, | ||
categoryIds: [1L], | ||
minAvgGrade: 2.2f, | ||
maxAvgGrade: 4.2f | ||
), | ||
expected: [ | ||
phraseFieldsCount: 2, | ||
arrayFieldsCount: 1, | ||
rangeFieldsCount: 1 | ||
], | ||
description: "Standard case with all fields populated" | ||
], | ||
[ | ||
params: new MaterialFilterSearchParams( | ||
phrase: "searchText", | ||
id: 10L, | ||
sectionId: 5L, | ||
categoryIds: [3L, 4L, 5L], | ||
minAvgGrade: 1.0f, | ||
maxAvgGrade: 5.0f | ||
), | ||
expected: [ | ||
phraseFieldsCount: 2, | ||
arrayFieldsCount: 1, | ||
rangeFieldsCount: 1 | ||
], | ||
description: "Case with multiple categories" | ||
]] | ||
} | ||
|
||
} |
156 changes: 156 additions & 0 deletions
156
...t/groovy/pl/sknikod/kodemysearch/module/material/MaterialSearchServiceWiremockSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package pl.sknikod.kodemysearch.module.material | ||
|
||
import org.springframework.data.domain.Page | ||
import org.springframework.data.domain.PageRequest | ||
import org.springframework.data.domain.Pageable | ||
import pl.sknikod.kodemysearch.SuperclassSpec | ||
import pl.sknikod.kodemysearch.configuration.LogbookConfiguration | ||
import pl.sknikod.kodemysearch.configuration.OpenSearchConfiguration | ||
import pl.sknikod.kodemysearch.infrastructure.module.material.MaterialSearchService | ||
import pl.sknikod.kodemysearch.infrastructure.module.material.MaterialSearchService$MaterialSearchMapperImpl | ||
import pl.sknikod.kodemysearch.infrastructure.module.material.model.MaterialPageable | ||
import pl.sknikod.kodemysearch.infrastructure.rest.MaterialControllerDefinition | ||
import pl.sknikod.kodemysearch.infrastructure.store.MaterialSearchStore | ||
import pl.sknikod.kodemysearch.util.opensearch.OpenSearchClientEnhanced | ||
import spock.lang.Shared | ||
import spock.lang.Subject | ||
|
||
import static com.github.tomakehurst.wiremock.client.WireMock.* | ||
import static org.assertj.core.api.Assertions.assertThat | ||
import static pl.sknikod.kodemysearch.module.material.MaterialSearchHelper.createMaterialSearchService | ||
|
||
class MaterialSearchServiceWiremockSpec extends SuperclassSpec { | ||
|
||
@Subject | ||
MaterialSearchService materialSearchService = createMaterialSearchService() | ||
|
||
def setupSpec() { | ||
WIREMOCK.start() | ||
setupWireMockStubs() | ||
} | ||
|
||
def cleanupSpec() { | ||
WIREMOCK.stop() | ||
} | ||
|
||
def "should search materials and map results correctly"() { | ||
given: "A mocked OpenSearch response" | ||
WIREMOCK.stubFor(post(urlPathMatching("/materials/_search")) | ||
.willReturn(aResponse() | ||
.withHeader("Content-Type", "application/json") | ||
.withBody(""" | ||
{ | ||
"took": 123, | ||
"timed_out": false, | ||
"_shards": { | ||
"total": 5, | ||
"successful": 5, | ||
"skipped": 0, | ||
"failed": 0 | ||
}, | ||
"hits": { | ||
"total": {"value": 2, "relation": "eq"}, | ||
"hits": [ | ||
{ | ||
"_source": { | ||
"id": 1, | ||
"title": "Material 1", | ||
"description": "Description 1", | ||
"status": "APPROVED", | ||
"active": true, | ||
"avgGrade": 4.5, | ||
"author": {"id": 100, "username": "Author1"}, | ||
"createdDate": "2024-12-07T10:00:00Z", | ||
"sectionId": 10, | ||
"categoryId": 20, | ||
"tags": [{"id": 1, "name": "Tag1"}] | ||
} | ||
}, | ||
{ | ||
"_source": { | ||
"id": 2, | ||
"title": "Material 2", | ||
"description": "Description 2", | ||
"status": "DRAFT", | ||
"isActive": false, | ||
"avgGrade": 3.0, | ||
"author": {"id": 200, "username": "Author2"}, | ||
"createdDate": "2024-12-07T10:00:00Z", | ||
"sectionId": 11, | ||
"categoryId": 21, | ||
"tags": [{"id": 2, "name": "Tag2"}] | ||
} | ||
} | ||
] | ||
} | ||
} | ||
"""))) | ||
|
||
and: "Search criteria and pageable parameters" | ||
def searchParams = new MaterialControllerDefinition.MaterialFilterSearchParams(phrase: "Material") | ||
Pageable pageable = PageRequest.of(0, 10) | ||
|
||
when: "The search method is called" | ||
Page<MaterialPageable> result = materialSearchService.search(searchParams, pageable) | ||
|
||
then: "The results are correctly mapped" | ||
assertThat(result).isNotNull() | ||
assertThat(result.content).hasSize(2) | ||
|
||
with(result.content[0]) { | ||
assertThat(id).isEqualTo(1) | ||
assertThat(title).isEqualTo("Material 1") | ||
assertThat(description).isEqualTo("Description 1") | ||
assertThat(isActive).isTrue() | ||
assertThat(avgGrade).isEqualTo(4.5f) | ||
assertThat(author.username).isEqualTo("Author1") | ||
assertThat(sectionId).isEqualTo(10) | ||
assertThat(categoryId).isEqualTo(20) | ||
assertThat(tags).hasSize(1) | ||
assertThat(tags[0].name).isEqualTo("Tag1") | ||
} | ||
|
||
with(result.content[1]) { | ||
assertThat(id).isEqualTo(2) | ||
assertThat(title).isEqualTo("Material 2") | ||
assertThat(description).isEqualTo("Description 2") | ||
assertThat(isActive).isFalse() | ||
assertThat(avgGrade).isEqualTo(3.0f) | ||
assertThat(author.username).isEqualTo("Author2") | ||
assertThat(sectionId).isEqualTo(11) | ||
assertThat(categoryId).isEqualTo(21) | ||
assertThat(tags).hasSize(1) | ||
assertThat(tags[0].name).isEqualTo("Tag2") | ||
} | ||
|
||
and: "The correct request was sent to OpenSearch" | ||
WIREMOCK.verify(postRequestedFor(urlPathMatching("/materials/_search")) | ||
.withRequestBody(matching(".*"))) | ||
} | ||
|
||
|
||
private static void setupWireMockStubs() { | ||
WIREMOCK.stubFor(head(urlPathEqualTo("/materials")) | ||
.willReturn(aResponse().withStatus(200))) | ||
|
||
WIREMOCK.stubFor(put(urlPathEqualTo("/materials")) | ||
.willReturn(aResponse().withStatus(201).withBody(""" | ||
{ | ||
"acknowledged": true, | ||
"shards_acknowledged": true, | ||
"index": "materials" | ||
} | ||
"""))) | ||
|
||
WIREMOCK.stubFor(head(urlPathEqualTo("/materials/_alias/materials-alias")) | ||
.willReturn(aResponse().withStatus(404))) | ||
|
||
WIREMOCK.stubFor(post(urlPathEqualTo("/_aliases")) | ||
.willReturn(aResponse().withStatus(200).withBody(""" | ||
{ | ||
"acknowledged": true | ||
} | ||
"""))) | ||
} | ||
|
||
} |