Skip to content

Commit

Permalink
Enable repeated search in DocumentUnitSearchEntryForm (#1525)
Browse files Browse the repository at this point in the history
* Add repeated search in DocumentUnitSearchEntryForm

The test is WIP.
RISDEV-4003

* Refactor code to always search on button click

RISDEV-4003
In order to avoid having too many conditionals and variables (e.g. isIdenticalSearch), this solution decouples the search completely from the route. The route is still pushed to the router, in order to maintain the search on reload, but now the search is always triggered, when the search button is clicked and on first mount.

* Fix search on changed route and test

This search has been triggered twice
RISDEV-4003

---------

Co-authored-by: Leonie Koch <leonie.koch@digitalservice.bund.de>
  • Loading branch information
anne-ds and leonie-koch committed May 28, 2024
1 parent 00cc3c9 commit bae763d
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 23 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/DocumentUnitSearch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const isLoading = ref(false)
const searchQuery = ref<Query<DocumentUnitSearchParameter>>()
const pageNumber = ref<number>(0)
const emptyStatus = computed(() => {
const emptyStateLabel = computed(() => {
if (!documentUnitListEntries.value) {
return "Starten Sie die Suche oder erstellen Sie eine neue Dokumentationseinheit."
} else if (documentUnitListEntries.value.length === 0) {
Expand Down Expand Up @@ -241,7 +241,7 @@ const showDefaultLink = computed(() => {
<DocumentUnitList
class="grow"
:document-unit-list-entries="documentUnitListEntries"
:empty-state="emptyStatus"
:empty-state="emptyStateLabel"
is-deletable
:is-loading="isLoading"
:search-response-error="searchResponseError"
Expand Down
71 changes: 50 additions & 21 deletions frontend/src/components/DocumentUnitSearchEntryForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ const { route, getQueryFromRoute, pushQueryToRoute } =
useQuery<DocumentUnitSearchParameter>()
const query = ref(getQueryFromRoute())
const searchEntryEmpty = computed(() => {
const isEmptySearch = computed(() => {
return Object.keys(query.value).length === 0
})
const submitButtonError = ref()
const dropdownItems: DropdownItem[] = [
Expand Down Expand Up @@ -77,6 +78,24 @@ function resetErrors(id?: DocumentUnitSearchParameter) {
submitButtonError.value = undefined
}
function isSearchInputInvalid() {
if (isEmptySearch.value) {
submitButtonError.value = "Geben Sie mindestens ein Suchkriterium ein"
return true
}
if (hasValidationErrors()) {
submitButtonError.value = "Fehler in Suchkriterien"
return true
}
return false
}
function hasValidationErrors() {
return validationStore.getAll().length > 0
}
async function validateSearchInput() {
//Startdatum fehlt
if (
Expand All @@ -92,7 +111,7 @@ async function validateSearchInput() {
validationStore.remove("decisionDate")
}
//Enddatum darf nich vor Startdatum liegen
//Enddatum darf nicht vor Startdatum liegen
if (
query.value?.decisionDateEnd &&
query.value?.decisionDate &&
Expand Down Expand Up @@ -121,42 +140,52 @@ function handleLocalInputError(error: ValidationError | undefined, id: string) {
validateSearchInput()
}
/**
* Computed property that determines whether the current search query is identical to the previous search query.
* @returns {ComputedRef<boolean>} - Returns `true` if the queries are identical, otherwise `false`.
*/
const isIdenticalSearch = (): boolean => {
const previousQuery = getQueryFromRoute()
const newQuery = query.value
return JSON.stringify(previousQuery) === JSON.stringify(newQuery)
}
function handleSearchButtonClicked() {
validateSearchInput()
if (searchEntryEmpty.value) {
submitButtonError.value = "Geben Sie mindestens ein Suchkriterium ein"
} else if (validationStore.getAll().length > 0) {
submitButtonError.value = "Fehler in Suchkriterien"
} else {
pushQueryToRoute(query.value)
if (isSearchInputInvalid()) {
return
}
if (isIdenticalSearch()) {
handleSearch()
}
pushQueryToRoute(query.value)
}
function handleSearchShortcut(event: KeyboardEvent) {
if (event.key == "Enter" && (event.ctrlKey || event.metaKey))
handleSearchButtonClicked()
}
watch(
route,
() => {
query.value = getQueryFromRoute()
if (!searchEntryEmpty.value) emit("search", getQueryFromRoute())
else resetSearch()
},
{ deep: true },
)
function handleSearch() {
if (!isEmptySearch.value) {
emit("search", getQueryFromRoute())
} else {
resetSearch()
}
}
watch(
query,
route,
() => {
validateSearchInput()
handleSearch()
},
{ deep: true },
)
onMounted(async () => {
if (!searchEntryEmpty.value) emit("search", getQueryFromRoute())
handleSearch()
window.addEventListener("keydown", handleSearchShortcut)
})
Expand Down Expand Up @@ -359,7 +388,7 @@ export type DocumentUnitSearchParameter =
</div>
<TextButton
v-if="!searchEntryEmpty"
v-if="!isEmptySearch"
aria-label="Suche zurücksetzen"
button-type="ghost"
class="ml-8 self-start"
Expand Down
20 changes: 20 additions & 0 deletions frontend/test/components/documentUnitSearchEntryForm.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { userEvent } from "@testing-library/user-event"
import { render, screen } from "@testing-library/vue"
import { expect } from "vitest"
import { createRouter, createWebHistory } from "vue-router"
import DocumentUnitSearchEntryForm from "@/components/DocumentUnitSearchEntryForm.vue"

Expand Down Expand Up @@ -67,6 +68,25 @@ describe("Documentunit search form", () => {
expect(emitted().search).toBeTruthy()
})

test("click on 'Ergebnisse anzeigen' with the same search entry, emits search event again", async () => {
const { emitted, user } = await renderComponent()

await user.type(
screen.getByLabelText("Entscheidungsdatum Suche"),
"23.03.2003",
)
await user.click(
screen.getByLabelText("Nach Dokumentationseinheiten suchen"),
)
expect(emitted().search.length).toBe(1)

await user.click(
screen.getByLabelText("Nach Dokumentationseinheiten suchen"),
)

expect(emitted().search.length).toBe(2)
})

test("click on 'Nur meine Dokstelle' renders 'Nur fehlerhafte Dokumentationseinheiten' checkbox", async () => {
const { user } = await renderComponent()
expect(
Expand Down
4 changes: 4 additions & 0 deletions frontend/test/e2e/caselaw/documentunit-search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ test.describe("search", () => {
).toBeVisible()

await page.getByLabel("Entscheidungsdatum Suche", { exact: true }).clear()
await page.getByLabel("Entscheidungsdatum Suche", { exact: true }).blur()
await expect(page.getByText("Startdatum fehlt")).toBeVisible()
await expect(
page.getByText("Enddatum darf nich vor Startdatum liegen"),
Expand All @@ -360,6 +361,9 @@ test.describe("search", () => {
await page
.getByLabel("Entscheidungsdatum Suche Ende", { exact: true })
.clear()
await page
.getByLabel("Entscheidungsdatum Suche Ende", { exact: true })
.blur()
await expect(page.getByText("Startdatum fehlt")).toBeHidden()
})

Expand Down

0 comments on commit bae763d

Please sign in to comment.