diff --git a/solution/ui/e2e/cypress/e2e/search.spec.cy.js b/solution/ui/e2e/cypress/e2e/search.spec.cy.js index d9d8c8f81e..2fc842744b 100644 --- a/solution/ui/e2e/cypress/e2e/search.spec.cy.js +++ b/solution/ui/e2e/cypress/e2e/search.spec.cy.js @@ -41,6 +41,10 @@ describe("Search flow", () => { cy.intercept("**/v3/resources/public/categories**", { fixture: "categories.json", }).as("categories"); + + cy.intercept(`**/v3/content-search/counts**`, { + fixture: "counts.json", + }).as("counts"); }); it("has a working search box on the homepage on desktop", () => { @@ -161,10 +165,6 @@ describe("Search flow", () => { }); it("should not show internal checkbox when not logged in", () => { - cy.intercept(`**/v3/content-search/counts**`, { - fixture: "counts.json", - }).as("counts"); - cy.viewport("macbook-15"); cy.visit(`/search/?q=${SEARCH_TERM}`, { timeout: 60000 }); cy.get(".doc-type__toggle fieldset > div") @@ -196,7 +196,7 @@ describe("Search flow", () => { .should("have.text", "Internal Resources(1)"); }); - it("should not show the categories dropdown when only regulations are selected", () => { + it("should not show the categories or subjects dropdowns when only regulations are selected", () => { cy.viewport("macbook-15"); cy.eregsLogin({ @@ -207,16 +207,22 @@ describe("Search flow", () => { cy.visit(`/search/?q=${SEARCH_TERM}`, { timeout: 60000 }); cy.get("div[data-testid='category-select']").should("be.visible"); + cy.get("button[data-testid='subjects-activator']").should("be.visible"); cy.get(".doc-type__toggle fieldset > div") .eq(0) .find("input") .check({ force: true }); cy.get("div[data-testid='category-select']").should("not.be.visible"); + cy.get("button[data-testid='subjects-activator']").should( + "not.be.visible", + ); + cy.get(".doc-type__toggle fieldset > div"); cy.get(".doc-type__toggle fieldset > div") .eq(1) .find("input") .check({ force: true }); cy.get("div[data-testid='category-select']").should("be.visible"); + cy.get("button[data-testid='subjects-activator']").should("be.visible"); }); it("has the correct type params in URL for each doc type combination", () => { @@ -263,13 +269,124 @@ describe("Search flow", () => { it("category should be selected on load if included in URL", () => { cy.viewport("macbook-15"); - cy.visit("/subjects/?categories=3"); + cy.visit(`/search?q={SEARCH_TERM}&categories=3`); cy.get("div[data-testid='category-select']") .should("exist") .find(".v-select__selection") .should("have.text", "Related Regulations Fixture Item"); }); + it("subject should be selected on load if included in the URL", () => { + cy.viewport("macbook-15"); + cy.visit(`/search?q={SEARCH_TERM}&subjects=2`); + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .find(".subjects-select__label") + .should("have.text", "ABP") + .click({ force: true }); + + cy.get("button[data-testid=add-subject-2]").should( + "have.class", + "subjects-li__button--selected", + ); + }); + + it("subject should change in URL if new subject is selected from the Subjects dropdown", () => { + cy.viewport("macbook-15"); + cy.visit(`/search?q=${SEARCH_TERM}&subjects=2`); + + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .find(".subjects-select__label") + .should("have.text", "ABP") + .click({ force: true }); + + cy.get("button[data-testid=add-subject-3]") + .should("not.have.class", "subjects-li__button--selected") + .find(".count") + .should("have.text", "(15)"); + + cy.get("button[data-testid=add-subject-3]").click({ force: true }); + + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .find(".subjects-select__label") + .should("have.text", "Access to Services") + .click({ force: true }); + + cy.get("button[data-testid=add-subject-2]").should( + "not.have.class", + "subjects-li__button--selected", + ); + + cy.get("button[data-testid=add-subject-3]").should( + "have.class", + "subjects-li__button--selected", + ); + + cy.url().should("include", "subjects=3"); + }); + + it("subjects and categories can be selected simultaneously", () => { + cy.viewport("macbook-15"); + cy.visit(`/search?q=${SEARCH_TERM}`); + + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .click(); + + cy.get("button[data-testid=add-subject-3]").click({ force: true }); + + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .find(".subjects-select__label") + .should("have.text", "Access to Services") + .click({ force: true }); + + cy.get("div[data-testid='category-select']").click(); + cy.get("div[data-testid='external-0']").click({ force: true }); + + cy.get("div[data-testid='category-select']") + .find(".v-select__selection") + .should("have.text", "Related Statutes in Fixture"); + + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .find(".subjects-select__label") + .should("have.text", "Access to Services"); + + cy.url().should("include", "subjects=3").and("include", "categories=1"); + }); + + it("subjects can be cleared by clicking the clear button", () => { + cy.viewport("macbook-15"); + cy.visit(`/search?q=${SEARCH_TERM}`); + + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .click(); + + cy.get("button[data-testid=add-subject-3]").click({ force: true }); + + cy.url().should("include", "subjects=3"); + + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .find(".subjects-select__label") + .should("have.text", "Access to Services") + .click({ force: true }); + + cy.get("i[data-testid='subjects-select-clear']").click({ force: true }); + + cy.get("button[data-testid='subjects-activator']") + .should("exist") + .find(".subjects-select__label") + .should("have.text", "Choose Subject"); + + cy.url().should("not.include", "subjects=3"); + + }); + it("displays results of the search and highlights search term in regulation text", () => { cy.viewport("macbook-15"); cy.visit(`/search/?q=${SEARCH_TERM}`, { timeout: 60000 }); diff --git a/solution/ui/e2e/cypress/e2e/subjects.spec.cy.js b/solution/ui/e2e/cypress/e2e/subjects.spec.cy.js index ea3bf6b0d0..61736fa0b2 100644 --- a/solution/ui/e2e/cypress/e2e/subjects.spec.cy.js +++ b/solution/ui/e2e/cypress/e2e/subjects.spec.cy.js @@ -427,14 +427,14 @@ describe("Find by Subjects", () => { cy.get(`button[data-testid=remove-subject-77]`).should("exist"); cy.get("button[data-testid=add-subject-63]").should( "not.have.class", - "sidebar-li__button--selected" + "subjects-li__button--selected" ); cy.get("button[data-testid=add-subject-63]").click({ force: true, }); cy.get("button[data-testid=add-subject-63]").should( "have.class", - "sidebar-li__button--selected" + "subjects-li__button--selected" ); cy.get(`button[data-testid=remove-subject-63]`).should("exist"); cy.get(`button[data-testid=remove-subject-77]`).should("not.exist"); @@ -541,11 +541,11 @@ describe("Find by Subjects", () => { cy.get(".doc-type__toggle fieldset > div") .eq(0) .find("label") - .should("have.text", "Public Resources"); + .should("include.text", "Public Resources"); cy.get(".doc-type__toggle fieldset > div") .eq(1) .find("label") - .should("have.text", "Internal Resources"); + .should("include.text", "Internal Resources"); // Remove subject cy.get("button[data-testid=remove-subject-63]").click({ force: true }); @@ -566,11 +566,11 @@ describe("Find by Subjects", () => { cy.get(".doc-type__toggle fieldset > div") .eq(0) .find("label") - .should("have.text", "Public Resources"); + .should("include.text", "Public Resources"); cy.get(".doc-type__toggle fieldset > div") .eq(1) .find("label") - .should("have.text", "Internal Resources"); + .should("include.text", "Internal Resources"); // Clear search cy.get("form.search-form .v-field__clearable i").click({ diff --git a/solution/ui/e2e/cypress/fixtures/counts.json b/solution/ui/e2e/cypress/fixtures/counts.json index a1a6e5371f..4d57b0e2fd 100644 --- a/solution/ui/e2e/cypress/fixtures/counts.json +++ b/solution/ui/e2e/cypress/fixtures/counts.json @@ -1,5 +1,36 @@ { "internal_resource_count": 1, "public_resource_count": 2, - "regulation_text_count": 3 + "regulation_text_count": 3, + "subjects": [ + { + "subject": 2, + "count": 41 + }, + { + "subject": 3, + "count": 15 + }, + { + "subject": 4, + "count": 6 + } + ], + "categories": [ + { + "category": 2, + "parent": null, + "count": 100 + }, + { + "category": 4, + "parent": 3, + "count": 20 + }, + { + "category": 5, + "parent": 3, + "count": 13 + } + ] } diff --git a/solution/ui/regulations/alias.js b/solution/ui/regulations/alias.js index 2db6c58d8d..cf178e04f5 100644 --- a/solution/ui/regulations/alias.js +++ b/solution/ui/regulations/alias.js @@ -4,6 +4,7 @@ const r = (p) => resolve(__dirname, p); export default { "@": r("src"), + composables: r("./composables"), cypress: r("../e2e/cypress"), eregsComponentLib: r("../regulations/eregs-component-lib"), legacy: r("../../regulations"), diff --git a/solution/ui/regulations/css/scss/partials/_search.scss b/solution/ui/regulations/css/scss/partials/_search.scss index 8ddfd56c3a..8e63859b04 100644 --- a/solution/ui/regulations/css/scss/partials/_search.scss +++ b/solution/ui/regulations/css/scss/partials/_search.scss @@ -14,7 +14,6 @@ &--menu { background-color: white; max-height: 300px; - overflow-y: scroll; .subjects__list-container { form { diff --git a/solution/ui/regulations/css/scss/partials/_subjects_selector.scss b/solution/ui/regulations/css/scss/partials/_subjects_selector.scss index 1d1037e2a9..7124ebfb5f 100644 --- a/solution/ui/regulations/css/scss/partials/_subjects_selector.scss +++ b/solution/ui/regulations/css/scss/partials/_subjects_selector.scss @@ -76,7 +76,7 @@ ul.subjects__list { height: 300px; - overflow: scroll; + overflow-y: auto; padding: 0; margin: 0; @@ -87,19 +87,11 @@ margin-bottom: 0; } - .sidebar-li__button { + .subjects-li__button { text-align: left; color: #000; width: 100%; - .match__container { - @include font-bold-keep-width; - - .match { - @include font-bold-keep-width-reset; - } - } - &--selected { @include font-bold-keep-width; @@ -113,6 +105,18 @@ cursor: pointer; } + + .match__container { + @include font-bold-keep-width; + + .match { + @include font-bold-keep-width-reset; + } + } + + .count { + margin-left: var(--spacer-1); + } } } } @@ -160,6 +164,12 @@ font-size: $font_size_sm; line-height: 22px; margin-bottom: var(--spacer-2); + + .subjects-li__button { + display: flex; + justify-content: space-between; + line-height: 22px; + } } } } diff --git a/solution/ui/regulations/eregs-vite/src/components/SearchContinueResearch.test.js b/solution/ui/regulations/eregs-vite/src/components/SearchContinueResearch.test.js index 847c0bf525..25cbb9e588 100644 --- a/solution/ui/regulations/eregs-vite/src/components/SearchContinueResearch.test.js +++ b/solution/ui/regulations/eregs-vite/src/components/SearchContinueResearch.test.js @@ -5,9 +5,7 @@ import SearchContinueResearch from "./SearchContinueResearch.vue"; describe("Search Continue Research", () => { it("correctly determines if a query string has spaces", () => { expect(SearchContinueResearch.hasSpaces("test")).toBe(false); - expect(SearchContinueResearch.hasSpaces("test query")).toBe( - true - ); + expect(SearchContinueResearch.hasSpaces("test query")).toBe(true); }); it("correctly determines if a query has quotes", () => { diff --git a/solution/ui/regulations/eregs-vite/src/components/dropdowns/Categories.vue b/solution/ui/regulations/eregs-vite/src/components/dropdowns/Categories.vue index 731eab2e36..4a687c5a60 100644 --- a/solution/ui/regulations/eregs-vite/src/components/dropdowns/Categories.vue +++ b/solution/ui/regulations/eregs-vite/src/components/dropdowns/Categories.vue @@ -187,7 +187,6 @@ const onMenuUpdate = () => { data-testid="category-select" item-type="CategoriesItem" label="Choose Category" - :loading="loading" :disabled="loading" :items="list" :item-props="itemProps" diff --git a/solution/ui/regulations/eregs-vite/src/components/dropdowns/FetchItemsContainer.vue b/solution/ui/regulations/eregs-vite/src/components/dropdowns/FetchItemsContainer.vue new file mode 100644 index 0000000000..d796263cf0 --- /dev/null +++ b/solution/ui/regulations/eregs-vite/src/components/dropdowns/FetchItemsContainer.vue @@ -0,0 +1,91 @@ + + + + + + + diff --git a/solution/ui/regulations/eregs-vite/src/components/dropdowns/Subjects.vue b/solution/ui/regulations/eregs-vite/src/components/dropdowns/Subjects.vue index 8cedfb1649..f7d2a36fa4 100644 --- a/solution/ui/regulations/eregs-vite/src/components/dropdowns/Subjects.vue +++ b/solution/ui/regulations/eregs-vite/src/components/dropdowns/Subjects.vue @@ -16,6 +16,10 @@ const props = defineProps({ type: Object, required: true, }, + counts: { + type: Array, + default: () => [], + }, loading: { type: Boolean, default: true, @@ -44,7 +48,8 @@ const labelClasses = computed(() => ({ const menuItemClick = (event) => { const menuItemClicked = - event.target.className.includes("sidebar-li__button") || event.target.className.includes("match__container"); + event.target.className.includes("subjects-li__button") || + event.target.className.includes("match__container"); if (event.target.dataset.name) { buttonTitle.value = event.target.dataset.name; @@ -57,7 +62,7 @@ const menuItemClick = (event) => { const clearClick = (event) => { // don't let click fall through to menu activator - event.stopPropagation(); + if (event) event.stopPropagation(); // if menu is open, close it if (menuToggleModel.value === true) menuToggleModel.value = false; @@ -79,18 +84,38 @@ const clearClick = (event) => { }); }; +const transformedList = ref({}); + watchEffect(() => { + if (props.loading === false) { + const clonedCounts = [...props.counts]; + + const sortedCountList = clonedCounts.map((item) => { + const subject = props.list.find( + (subject) => subject.id == item.subject + ); + + return { + ...subject, + count: item.count, + }; + }); + + transformedList.value = { + results: sortedCountList, + loading: props.loading, + }; + } + if ($route.query?.subjects === undefined) { buttonTitle.value = undefined; return; } - if (props.list.loading === false && $route.query.subjects) { + if (props.loading === false && $route.query.subjects) { const subjectId = $route.query.subjects; - const subject = props.list.results.find( - (subject) => subject.id == subjectId - ); + const subject = props.list.find((subject) => subject.id == subjectId); buttonTitle.value = getSubjectName(subject); } @@ -100,6 +125,7 @@ watchEffect(() => {