diff --git a/package.json b/package.json index c7bd5721fc..bb9531ab8b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "panic-button": "./bin/panic-button.sh", "storybook": "lerna run --parallel storybook", "test": "lerna run --parallel test", - "test:ci": "nyc lerna run --parallel test:ci" + "test:ci": "nyc --silent lerna run --parallel test:ci" }, "engines": { "node": ">=16" diff --git a/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.spec.js b/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.spec.js index f6d147ab45..0fcb6a1c72 100644 --- a/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.spec.js +++ b/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.spec.js @@ -11,23 +11,26 @@ describe('SurveyTask', function () { describe('when choices are showing / without a selected choice', function () { describe('with characteristic filters', function () { - const DefaultStory = composeStory(Default, Meta) + let filterButton, choiceButtons, choicesShowingCount, clearFiltersButton - it('should show a filter button', function () { - const { getByRole } = render() - + before(function () { + const DefaultStory = composeStory(Default, Meta) + render() // filterButton is the Filter button above the choices - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - + filterButton = screen.queryByLabelText('SurveyTask.CharacteristicsFilter.filter') + const choiceMenu = document.querySelector('[role=menu]') + // choiceButtons are the menu items / buttons for the various choices (i.e. for the mock task the various animals) + choiceButtons = choiceMenu.querySelectorAll('[role=menuitemcheckbox]') + // choicesShowingCount is the text below choices that notes "Showing X of Y" + choicesShowingCount = screen.queryByText('SurveyTask.CharacteristicsFilter.showing') + clearFiltersButton = screen.queryByRole('button', { name: 'SurveyTask.CharacteristicsFilter.clearFilters' }) + }) + + it('should show a filter button', function () { expect(filterButton).to.be.ok() }) it('should show the choices', function () { - const { getAllByRole } = render() - - // choiceButtons are the menu items / buttons for the various choices (i.e. for the mock task the various animals) - const choiceButtons = getAllByRole('menuitemcheckbox') - expect(choiceButtons.length).to.equal(6) expect(choiceButtons[0]).to.have.text('Aardvark') expect(choiceButtons[1]).to.have.text('Elephant') @@ -38,48 +41,39 @@ describe('SurveyTask', function () { }) it('should show the choices showing count out of total choices count', function () { - const { getByText } = render() - - // choicesShowingCount is the text below choices that notes "Showing X of Y" - const choicesShowingCount = getByText('SurveyTask.CharacteristicsFilter.showing') - expect(choicesShowingCount).to.be.ok() }) it('should show a Clear Filters button', function () { - const { getByRole } = render() - - const clearFiltersButton = getByRole('button', { name: 'Clear SurveyTask.CharacteristicsFilter.clearFilters' }) - expect(clearFiltersButton).to.be.ok() }) it('should disable the Clear Filters button if showing choices = total choices', function () { - const { getByRole } = render() - - const clearFiltersButton = getByRole('button', { name: 'Clear SurveyTask.CharacteristicsFilter.clearFilters' }) - expect(clearFiltersButton).to.have.attribute('disabled') }) }) describe('without characteristic filters', function () { - const NoFiltersStory = composeStory(NoFilters, Meta) + let filterButton, choiceButtons, choicesShowingCount, clearFiltersButton + + before(function () { + const NoFiltersStory = composeStory(NoFilters, Meta) + render() + // filterButton is the Filter button above the choices + filterButton = screen.queryByLabelText('SurveyTask.CharacteristicsFilter.filter') + const choiceMenu = document.querySelector('[role=menu]') + // choiceButtons are the menu items / buttons for the various choices (i.e. for the mock task the various animals) + choiceButtons = choiceMenu.querySelectorAll('[role=menuitemcheckbox]') + // choicesShowingCount is the text below choices that notes "Showing X of Y" + choicesShowingCount = screen.queryByText('SurveyTask.CharacteristicsFilter.showing') + clearFiltersButton = screen.queryByRole('button', { name: 'SurveyTask.CharacteristicsFilter.clearFilters' }) + }) it('should not show a filter button', function () { - const { queryByRole } = render() - - const filterButton = queryByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - expect(filterButton).to.not.exist() }) it('should show the choices', function () { - const { getAllByRole } = render() - - // choiceButtons are the menu items / buttons for the various choices (i.e. for the mock task the various animals) - const choiceButtons = getAllByRole('menuitemcheckbox') - expect(choiceButtons.length).to.equal(6) expect(choiceButtons[0]).to.have.text('Aardvark') expect(choiceButtons[1]).to.have.text('Elephant') @@ -90,18 +84,10 @@ describe('SurveyTask', function () { }) it('should not show the choices showing count out of total choices count', function () { - const { queryByText } = render() - - const choicesShowingCount = queryByText('SurveyTask.CharacteristicsFilter.showing') - expect(choicesShowingCount).to.not.exist() }) - it('should not not show a clear filters button', function () { - const { queryByRole } = render() - - const clearFiltersButton = queryByRole('button', { name: 'Clear SurveyTask.CharacteristicsFilter.clearFilters' }) - + it('should not not show a Clear Filters button', function () { expect(clearFiltersButton).to.not.exist() }) }) @@ -113,268 +99,228 @@ describe('SurveyTask', function () { describe('when the Filter button is clicked', function () { it('should show characteristic filter sections', async function () { const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole } = render() + render() // filterButton is the Filter button above the choices - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) + const filterButton = screen.getByLabelText('SurveyTask.CharacteristicsFilter.filter') await user.click(filterButton) + const characteristicsSection = screen.getByTestId('characteristics') // the filterSections are the characteristic filter sections, i.e. the sections for "Like", "Pattern", and "Color" for the mock task - const filterSections = getAllByRole('radiogroup') + const filterSections = within(characteristicsSection).getAllByRole('radiogroup') expect(filterSections.length).to.equal(3) }) describe('when filters are clicked', function () { - it('should show the filter button with a remove filter button', async function () { - const user = userEvent.setup({ delay: null }) - const { getByRole, getByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) + let user, filterButton + + beforeEach(async function () { + user = userEvent.setup({ delay: null }) + render() + // click the Filter button above choices to open the characteristics filters + filterButton = screen.getByLabelText('SurveyTask.CharacteristicsFilter.filter') await user.click(filterButton) - // the stripesFilterButton is the button to filter choices by "stripes". Stripes is a specific value of the "Pattern" characteristic. - const stripesFilterButton = getByTestId('filter-PTTRN-STRPS') + }) + + it('should show the filter button with a remove filter button', async function () { + // the stripesFilterButton is the button to filter choices by "stripes". Stripes is a specific value of the "Pattern" characteristic + const stripesFilterButton = screen.getByTestId('filter-PTTRN-STRPS') expect(stripesFilterButton).to.be.ok() - // the stripesFilterRemoveButton is the small x button that appears over a filter to remove the filter, after it is selected. The presence of this button indicates that the filter is selected. The absence of this button indicates that the filter is not selected. - let characteristicsSection = getByTestId('characteristics') + // the stripesFilterRemoveButton is the small x button that appears over a filter to remove the filter, after it is selected. The presence of this button indicates that the filter is selected. The absence of this button indicates that the filter is not selected + let characteristicsSection = screen.getByTestId('characteristics') let stripesFilterRemoveButton = within(characteristicsSection).queryByTestId('remove-filter-PTTRN-STRPS') expect(stripesFilterRemoveButton).to.be.null() await user.click(stripesFilterButton) - characteristicsSection = getByTestId('characteristics') + characteristicsSection = screen.getByTestId('characteristics') stripesFilterRemoveButton = within(characteristicsSection).getByTestId('remove-filter-PTTRN-STRPS') expect(stripesFilterRemoveButton).to.be.ok() }) it('should show the choices that match the filter', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, getByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - await user.click(filterButton) - const redFilterButton = getByTestId('filter-CLR-RD') + const redFilterButton = screen.getByTestId('filter-CLR-RD') expect(redFilterButton).to.be.ok() - // the following user events filter choices by the color red and then close the characteristics filters, returning to the list of choices. + // the following user events filter choices by the color red and then close the characteristics filters, returning to the list of choices await user.click(redFilterButton) await user.click(filterButton) - const choiceButtons = getAllByRole('menuitemcheckbox') + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') + // confirm the choices are the 3 choices that match the red filter expect(choiceButtons.length).to.equal(3) expect(choiceButtons[0]).to.have.text('Aardvark') expect(choiceButtons[1]).to.have.text('Kudu') expect(choiceButtons[2]).to.have.text('Fire') }) - it.skip('should persist filters after a choice is selected', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, getByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - - // open the characteristics filters - await user.click(filterButton) - const redFilterButton = getByTestId('filter-CLR-RD') + it('should persist filters after a choice is selected', async function () { + const redFilterButton = screen.getByTestId('filter-CLR-RD') // click/apply the red filter, which filters 6 choices to 3 choices await user.click(redFilterButton) // close the characteristics filters await user.click(filterButton) - const fireChoiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) - expect(fireChoiceButton).to.be.ok() - + const fireChoiceButton = screen.getByText('Fire') // select the Fire choice await user.click(fireChoiceButton) - const identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) - expect(identifyButton).to.be.ok() - + const identifyButton = screen.getByText('SurveyTask.Choice.identify') // identify the Fire choice await user.click(identifyButton) + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') // confirm the remaining choices are the 3 choices that match the red filter - const choiceButtons = getAllByRole('menuitemcheckbox') expect(choiceButtons.length).to.equal(3) expect(choiceButtons[0]).to.have.text('Aardvark') expect(choiceButtons[1]).to.have.text('Kudu') expect(choiceButtons[2]).to.have.text('Fire') }) - it.skip('should remove the filter on remove filter button click (within Characteristics)', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, getByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - await user.click(filterButton) - const stripesFilterButton = getByTestId('filter-PTTRN-STRPS') + it('should remove the filter on remove filter button click (within Characteristics)', async function () { + const stripesFilterButton = screen.getByTestId('filter-PTTRN-STRPS') // click/apply the stripes filter await user.click(stripesFilterButton) - const characteristicsSection = getByTestId('characteristics') + const characteristicsSection = screen.getByTestId('characteristics') const stripesFilterRemoveButton = within(characteristicsSection).getByTestId('remove-filter-PTTRN-STRPS') + // confirm the stripes filter is selected by checking for the presence of the remove filter button + expect(stripesFilterRemoveButton).to.be.ok() + // remove the stripes filter await user.click(stripesFilterRemoveButton) + // close the characteristics filters await user.click(filterButton) + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') // confirm the choices are the total 6 choices, not filtered by the stripes filter - const choiceButtons = getAllByRole('menuitemcheckbox') expect(choiceButtons.length).to.equal(6) }) - it.skip('should remove the filter on remove filter button click (within FilterStatus)', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, getByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - await user.click(filterButton) - const stripesFilterButton = getByTestId('filter-PTTRN-STRPS') + it('should remove the filter on remove filter button click (within FilterStatus)', async function () { + const stripesFilterButton = screen.getByTestId('filter-PTTRN-STRPS') // click/apply the stripes filter await user.click(stripesFilterButton) await user.click(filterButton) // confirm the stripes filter is applied, of the total 6 choices only 1 choice (Kudu) matches the stripes filter - let choiceButtons = getAllByRole('menuitemcheckbox') + let choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(1) - const filterStatusSection = getByTestId('filter-status') + const filterStatusSection = screen.getByTestId('filter-status') const stripesFilterRemoveButton = within(filterStatusSection).getByTestId('remove-filter-PTTRN-STRPS') // remove the stripes filter await user.click(stripesFilterRemoveButton) + choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') // confirm the choices are the total 6 choices, not filtered by the stripes filter - choiceButtons = getAllByRole('menuitemcheckbox') expect(choiceButtons.length).to.equal(6) }) - it.skip('should remove filters on Clear Filters button click (within Characteristics) ', async function () { - const user = userEvent.setup({ delay: null }) - const { getByRole, getByTestId, queryByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - await user.click(filterButton) + it('should remove filters on Clear Filters button click (within Characteristics) ', async function () { // click/apply the like a cow/horse filter - const cowHorseFilterButton = getByTestId('filter-LK-CWHRS') + const cowHorseFilterButton = screen.getByTestId('filter-LK-CWHRS') await user.click(cowHorseFilterButton) // click/apply the color tan/yellow filter - const tanYellowFilterButton = getByTestId('filter-CLR-TNLLW') + const tanYellowFilterButton = screen.getByTestId('filter-CLR-TNLLW') await user.click(tanYellowFilterButton) - const characteristicsSection = getByTestId('characteristics') + const characteristicsSection = screen.getByTestId('characteristics') let cowHorseFilterRemoveButton = within(characteristicsSection).getByTestId('remove-filter-LK-CWHRS') let tanYellowFilterRemoveButton = within(characteristicsSection).getByTestId('remove-filter-CLR-TNLLW') // confirm the cow/horse and tan/yellow filters are applied expect(cowHorseFilterRemoveButton).to.be.ok() expect(tanYellowFilterRemoveButton).to.be.ok() - const clearFiltersButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.clearFilters' }) + const clearFiltersButton = within(characteristicsSection).getByText('SurveyTask.CharacteristicsFilter.clearFilters') // clear the filters await user.click(clearFiltersButton) - cowHorseFilterRemoveButton = queryByTestId('remove-filter-LK-CWHRS') - tanYellowFilterRemoveButton = queryByTestId('remove-filter-CLR-TNLLW') + cowHorseFilterRemoveButton = screen.queryByTestId('remove-filter-LK-CWHRS') + tanYellowFilterRemoveButton = screen.queryByTestId('remove-filter-CLR-TNLLW') // confirm the cow/horse and tan/yellow filters are removed expect(cowHorseFilterRemoveButton).to.be.null() expect(tanYellowFilterRemoveButton).to.be.null() }) - it.skip('should remove filters on Clear Filters button click (within Chooser)', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, getByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - await user.click(filterButton) - const cowHorseFilterButton = getByTestId('filter-LK-CWHRS') + it('should remove filters on Clear Filters button click (within Chooser)', async function () { + const cowHorseFilterButton = screen.getByTestId('filter-LK-CWHRS') // click/apply the like a cow/horse filter await user.click(cowHorseFilterButton) - const tanYellowFilterButton = getByTestId('filter-CLR-TNLLW') + const tanYellowFilterButton = screen.getByTestId('filter-CLR-TNLLW') // click/apply the color tan/yellow filter await user.click(tanYellowFilterButton) await user.click(filterButton) - let choiceButtons = getAllByRole('menuitemcheckbox') + let choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') // confirm the choices remaining are the 1 choice (Kudu) that matches the cow/horse and tan/yellow filters expect(choiceButtons.length).to.equal(1) - const clearFiltersButton = getByRole('button', { name: 'Clear SurveyTask.CharacteristicsFilter.clearFilters' }) + const clearFiltersButton = screen.getByText('SurveyTask.CharacteristicsFilter.clearFilters') // clear the filters await user.click(clearFiltersButton) - choiceButtons = getAllByRole('menuitemcheckbox') + choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') // confirm the choices are the total 6 choices, not filtered by the cow/horse and tan/yellow filters expect(choiceButtons.length).to.equal(6) }) }) }) - describe.skip('when a choice is clicked', function () { - it('should show the choice heading', async function () { - const user = userEvent.setup({ delay: null }) - const { getByRole } = render() - const choiceButton = getByRole('menuitemcheckbox', { name: 'Aardvark' }) + describe('when a choice is clicked', function () { + let user + + beforeEach(function () { + user = userEvent.setup({ delay: null }) + render() + }) + + it('should show the choice description', async function () { + const choiceButton = screen.getByText('Aardvark') await user.click(choiceButton) - const choiceHeading = getByRole('heading', { name: 'Aardvark' }) + const choiceDescription = screen.getByText('Not as awesome as a pangolin, but surprisingly big.') - expect(choiceHeading).to.be.ok() + expect(choiceDescription).to.be.ok() }) it('should show choice images', async function () { - const user = userEvent.setup({ delay: null }) - const { getByRole, getByTestId } = render() - const choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) + const choiceButton = screen.getByText('Fire') await user.click(choiceButton) - const choiceImages = getByTestId('choice-images') + const choiceImages = screen.getByTestId('choice-images') expect(choiceImages).to.be.ok() }) it('should show choices when Not This button is clicked', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, queryByRole } = render() - const choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) + const choiceButton = screen.getByText('Fire') await user.click(choiceButton) - const notThisButton = getByRole('button', { name: 'SurveyTask.Choice.notThis' }) + const notThisButton = screen.getByText('SurveyTask.Choice.notThis') // close choice (Fire) component await user.click(notThisButton) - // confirm choice (Fire) heading, and therefore choice, is not shown - const choiceHeading = queryByRole('heading', { name: 'Fire' }) - expect(choiceHeading).to.be.null() + // confirm choice (Fire) description, and therefore choice, is not shown + const choiceDescription = screen.queryByText('It\'s a fire. Pretty sure you know what this looks like.') + expect(choiceDescription).to.be.null() // confirm choices are shown - const choiceButtons = getAllByRole('menuitemcheckbox') + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(6) }) it('should show choices with selected choice checked when Identify button is clicked', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, queryByRole } = render() - const choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) + const choiceButton = screen.getByText('Fire') await user.click(choiceButton) - const identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) + const identifyButton = screen.getByText('SurveyTask.Choice.identify') // identify choice (Fire) and close choice (Fire) component await user.click(identifyButton) - // confirm choice (Fire) heading, and therefore choice, is not shown - const choiceHeading = queryByRole('heading', { name: 'Fire' }) - expect(choiceHeading).to.be.null() + // confirm choice (Fire) description, and therefore choice, is not shown + const choiceDescription = screen.queryByText('It\'s a fire. Pretty sure you know what this looks like.') + expect(choiceDescription).to.be.null() // confirm choices are shown - const choiceButtons = getAllByRole('menuitemcheckbox') + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(6) // confirm choice (Fire) is shown as checked - const fireChoiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) + const fireChoiceButton = Array.from(choiceButtons).find(choiceButton => choiceButton.textContent === 'Fire') expect(fireChoiceButton.getAttribute('aria-checked')).to.equal('true') }) - it('should disable the Identify button until required questions are answered', async function () { - const user = userEvent.setup({ delay: null }) - const { getByRole } = render() - const choiceButton = getByRole('menuitemcheckbox', { name: 'Aardvark' }) - await user.click(choiceButton) - let identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) - // confirm the Identify button is disabled, pending required questions answered - expect(identifyButton.disabled).to.be.true() - // the required questions for Aardvark are "How many?" and "What behavior do you see?" - // the following answers "How many?" with "3" and "What behavior do you see?" with "Eating" - const howManyInput = getByRole('radio', { name: "3" }) - await user.click(howManyInput) - const whatBehaviorsInput = getByRole('checkbox', { name: "Eating" }) - await user.click(whatBehaviorsInput) - identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) - // confirm the Identify button is enabled, now that required questions answered - expect(identifyButton.disabled).to.be.false() - }) - it('should disable "Done & Talk" and "Done" buttons', async function () { - const user = userEvent.setup({ delay: null }) - const { getByRole } = render() - let doneAndTalkButton = getByRole('button', { name: 'TaskArea.Tasks.DoneAndTalkButton.doneAndTalk' }) - let doneButton = getByRole('button', { name: 'TaskArea.Tasks.DoneButton.done' }) + let doneAndTalkButton = screen.getByRole('button', { name: 'TaskArea.Tasks.DoneAndTalkButton.doneAndTalk' }) + let doneButton = screen.getByRole('button', { name: 'TaskArea.Tasks.DoneButton.done' }) // mock task doesn't require an identified choice, so confirm the Done & Talk and Done buttons are enabled before selecting a choice expect(doneAndTalkButton.disabled).to.be.false() expect(doneButton.disabled).to.be.false() - const choiceButton = getByRole('menuitemcheckbox', { name: 'Aardvark' }) + const choiceButton = screen.getByText('Aardvark') await user.click(choiceButton) - doneAndTalkButton = getByRole('button', { name: 'TaskArea.Tasks.DoneAndTalkButton.doneAndTalk' }) - doneButton = getByRole('button', { name: 'TaskArea.Tasks.DoneButton.done' }) + doneAndTalkButton = screen.getByRole('button', { name: 'TaskArea.Tasks.DoneAndTalkButton.doneAndTalk' }) + doneButton = screen.getByRole('button', { name: 'TaskArea.Tasks.DoneButton.done' }) // confirm the Done & Talk and Done buttons are disabled while a choice is selected expect(doneAndTalkButton.disabled).to.be.true() expect(doneButton.disabled).to.be.true() @@ -385,260 +331,250 @@ describe('SurveyTask', function () { describe('with user keystrokes', function () { const DefaultStory = composeStory(Default, Meta) const NoFiltersStory = composeStory(NoFilters, Meta) + let user + + beforeEach(function () { + user = userEvent.setup({ delay: null }) + }) + + it('should remove a previously identified choice with delete key', async function () { + render() + let choiceButton = screen.getByText('Fire') + await user.click(choiceButton) + const identifyButton = screen.getByText('SurveyTask.Choice.identify') + // identify choice (Fire) and close choice (Fire) component + await user.click(identifyButton) + // confirm choices showing + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') + expect(choiceButtons.length).to.equal(6) + + // confirm choice Fire selected + choiceButton = Array.from(choiceButtons).find(choiceButton => choiceButton.textContent === 'Fire') + expect(choiceButton.getAttribute('aria-checked')).to.equal('true') + + // confirm choice Fire active element + expect(choiceButton).to.equal(document.activeElement) + + // press delete key to remove choice (Fire) + await user.keyboard('[Delete]') + choiceButton = Array.from(choiceButtons).find(choiceButton => choiceButton.textContent === 'Fire') + // confirm choice Fire not selected + expect(choiceButton.getAttribute('aria-checked')).to.equal('false') + }) + + it('should remove a previously identified choice with backspace key', async function () { + render() + let choiceButton = screen.getByText('Fire') + await user.click(choiceButton) + const identifyButton = screen.getByText('SurveyTask.Choice.identify') + // identify choice (Fire) and close choice (Fire) component + await user.click(identifyButton) + // confirm choices showing + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') + expect(choiceButtons.length).to.equal(6) + + // confirm choice Fire selected + choiceButton = Array.from(choiceButtons).find(choiceButton => choiceButton.textContent === 'Fire') + expect(choiceButton.getAttribute('aria-checked')).to.equal('true') + + // confirm choice Fire active element + expect(choiceButton).to.equal(document.activeElement) + + // press backspace key to remove choice (Fire) + await user.keyboard('[Backspace]') + choiceButton = Array.from(choiceButtons).find(choiceButton => choiceButton.textContent === 'Fire') + // confirm choice Fire not selected + expect(choiceButton.getAttribute('aria-checked')).to.equal('false') + }) describe('when the Filter button is keyed with Enter', function () { it('should show characteristic filter sections', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole } = render() + render() // tabbing to the Filter button await user.keyboard('[Tab]') - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) + const filterButton = screen.getByLabelText('SurveyTask.CharacteristicsFilter.filter') expect(filterButton).to.equal(document.activeElement) // pressing the Enter key to open the Filter button await user.keyboard('[Enter]') // the filterSections are the characteristic filter sections, i.e. the sections for "Like", "Pattern", and "Color" for the mock task - const filterSections = getAllByRole('radiogroup') + const characteristicsSection = screen.getByTestId('characteristics') + const filterSections = within(characteristicsSection).getAllByRole('radiogroup') expect(filterSections.length).to.equal(3) }) describe('when filters are keyed', function () { - it('should show the filter button with a remove filter button', async function () { - const user = userEvent.setup({ delay: null }) - const { getByTestId, queryByTestId } = render() + let user, filterButton + + beforeEach(async function () { + user = userEvent.setup({ delay: null }) + render() + filterButton = screen.getByLabelText('SurveyTask.CharacteristicsFilter.filter') // tabbing to and opening the Filter button await user.keyboard('[Tab][Enter]') - // the solidFilterButton is the button to filter choices by "solid". Solid is a specific value of the "Pattern" characteristic. - const solidFilterButton = getByTestId('filter-PTTRN-SLD') + }) + + it('should show the filter button with a remove filter button', async function () { + // the solidFilterButton is the button to filter choices by "solid". Solid is a specific value of the "Pattern" characteristic + const solidFilterButton = screen.getByTestId('filter-PTTRN-SLD') expect(solidFilterButton).to.be.ok() - // the solidFilterRemoveButton is the small x button that appears over a filter to remove the filter, after it is selected. The presence of this button indicates that the filter is selected. The absence of this button indicates that the filter is not selected. - let characteristicsSection = queryByTestId('characteristics') + // the solidFilterRemoveButton is the small x button that appears over a filter to remove the filter, after it is selected. The presence of this button indicates that the filter is selected. The absence of this button indicates that the filter is not selected + let characteristicsSection = screen.queryByTestId('characteristics') let solidFilterRemoveButton = within(characteristicsSection).queryByTestId('remove-filter-PTTRN-SLD') expect(solidFilterRemoveButton).to.be.null() // tabbing to the pattern section that contains the solid filter and selecting the solid filter with space key await user.keyboard('[Tab][Tab][Space]') - characteristicsSection = queryByTestId('characteristics') + characteristicsSection = screen.queryByTestId('characteristics') solidFilterRemoveButton = within(characteristicsSection).getByTestId('remove-filter-PTTRN-SLD') expect(solidFilterRemoveButton).to.be.ok() }) - it.skip('should show the choices that match the filter', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - // tabbing to and opening the Filter button - await user.keyboard('[Tab][Enter]') + it('should show the choices that match the filter', async function () { // tabbing to the pattern section that contains the solid filter and selecting the solid filter with space key await user.keyboard('[Tab][Tab][Space]') // close the filters await user.click(filterButton) // confirming that the choices are filtered by the solid filter - const choiceButtons = getAllByRole('menuitemcheckbox') + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(3) expect(choiceButtons[0]).to.have.text('Aardvark') expect(choiceButtons[1]).to.have.text('Elephant') expect(choiceButtons[2]).to.have.text('Kudu') }) - it.skip('should remove the filter on remove filter button keypress (within Characteristics)', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, queryByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - // tabbing to and opening the Filter button - await user.keyboard('[Tab][Enter]') + it('should remove the filter on remove filter button keypress (within Characteristics)', async function () { // tabbing to the pattern section that contains the solid filter and selecting the solid filter with space key await user.keyboard('[Tab][Tab][Space]') // confirm the solid filter is selected with existence of the related remove filter button - let characteristicsSection = queryByTestId('characteristics') + let characteristicsSection = screen.queryByTestId('characteristics') let solidFilterRemoveButton = within(characteristicsSection).getByTestId('remove-filter-PTTRN-SLD') expect(solidFilterRemoveButton).to.be.ok() // remove the solid filter with the "Remove solid filter" small x button await user.keyboard('[Tab][Tab][Space]') // confirm the solid filter is no longer selected with absence of the related remove filter button - solidFilterRemoveButton = queryByTestId('remove-filter-PTTRN-SLD') + solidFilterRemoveButton = screen.queryByTestId('remove-filter-PTTRN-SLD') expect(solidFilterRemoveButton).to.be.null() // close the filters await user.click(filterButton) // confirm the choices are the total 6 choices, not filtered by the solid filter - const choiceButtons = getAllByRole('menuitemcheckbox') + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(6) }) - it.skip('should remove the filter on remove filter button keypress (within FilterStatus)', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, getByTestId } = render() - const filterButton = getByRole('button', { name: 'SurveyTask.CharacteristicsFilter.filter' }) - // tabbing to and opening the Filter button - await user.keyboard('[Tab][Enter]') + it('should remove the filter on remove filter button keypress (within FilterStatus)', async function () { // tabbing to the pattern section that contains the solid filter and selecting the solid filter with space key await user.keyboard('[Tab][Tab][Space]') // confirm the solid filter is selected with existence of the related remove filter button - let filterStatusSection = getByTestId('filter-status') + let filterStatusSection = screen.getByTestId('filter-status') let solidFilterRemoveButton = within(filterStatusSection).getByTestId('remove-filter-PTTRN-SLD') expect(solidFilterRemoveButton).to.be.ok() // close the filters await user.click(filterButton) // confirm the solid filter is applied, of the total 6 choices only 1 choice (Kudu) matches the solid filter - let choiceButtons = getAllByRole('menuitemcheckbox') + let choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(3) // remove the solid filter with the "Remove solid filter" small x button in the Filter Status component await user.keyboard('[Tab][Space]') // confirm the choices are the total 6 choices, not filtered by the solid filter - choiceButtons = getAllByRole('menuitemcheckbox') + choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(6) }) }) }) describe('when a choice is selected with Enter', function () { - it('should show the choice heading', async function () { - const user = userEvent.setup({ delay: null }) - const { getByRole } = render() + let user + + beforeEach(function () { + user = userEvent.setup({ delay: null }) + render() + }) + + it('should show the choice description', async function () { // tabbing to the first choice (Aardvark) await user.keyboard('[Tab]') - const choiceButton = getByRole('menuitemcheckbox', { name: 'Aardvark' }) - expect(choiceButton).to.equal(document.activeElement) + const choiceButton = screen.getByText('Aardvark') // pressing Enter to open the choice (Aardvark) await user.keyboard('[Enter]') - const choiceHeading = getByRole('heading', { name: 'Aardvark' }) - expect(choiceHeading).to.be.ok() + const choiceDescription = screen.getByText('Not as awesome as a pangolin, but surprisingly big.') + expect(choiceDescription).to.be.ok() }) it('should show choice images', async function () { - const user = userEvent.setup({ delay: null }) - const { getByTestId } = render() // tabbing to the first choice (Aardvark) and pressing Enter to open the choice (Aardvark) await user.keyboard('[Tab][Enter]') - const choiceImages = getByTestId('choice-images') + const choiceImages = screen.getByTestId('choice-images') expect(choiceImages).to.be.ok() }) - it.skip('should show choices with recent choice as active choice when Not This button keyed with Enter', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, queryByRole } = render() + it('should show choices with recent choice as active choice when Not This button keyed with Enter', async function () { // tabbing to the first choice (Aardvark), arrowing up to the last choice (Nothing here), and pressing Enter to open the choice (Nothing here) await user.keyboard('[Tab]') await user.keyboard('[ArrowUp]') await user.keyboard('[Enter]') - let choiceHeading = getByRole('heading', { name: 'Nothing here' }) - expect(choiceHeading).to.be.ok() + let choiceDescription = screen.getByText('Don\'t tell the plant biologists we called vegetation \"nothing here\"!') + expect(choiceDescription).to.be.ok() // tabbing to the "Not this" button await user.keyboard('[Tab][Tab]') - const notThisButton = getByRole('button', { name: 'SurveyTask.Choice.notThis' }) + const notThisButton = screen.getByRole('button', { name: 'SurveyTask.Choice.notThis' }) expect(notThisButton).to.equal(document.activeElement) // pressing Enter to close the choice (Nothing here) await user.keyboard('[Enter]') - // confirm choice (Nothing here) heading, and therefore choice, is not shown - choiceHeading = queryByRole('heading', { name: 'Nothing here' }) - expect(choiceHeading).to.be.null() + // confirm choice (Nothing here) description, and therefore choice, is not shown + choiceDescription = screen.queryByText('Don\'t tell the plant biologists we called vegetation \"nothing here\"!') + expect(choiceDescription).to.be.null() // confirm choices are shown - const choiceButtons = getAllByRole('menuitemcheckbox') + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(6) }) - it.skip('should show choices with identified choice as active choice when Identify keyed with Enter', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole, queryByRole } = render() + it('should show choices with identified choice as active choice when Identify keyed with Enter', async function () { // tabbing to the first choice (Aardvark), arrowing up to the last choice (Nothing here), and pressing Enter to open the choice (Nothing here) await user.keyboard('[Tab]') await user.keyboard('[ArrowUp]') await user.keyboard('[Enter]') - let choiceHeading = getByRole('heading', { name: 'Nothing here' }) - expect(choiceHeading).to.be.ok() + let choiceDescription = screen.getByText('Don\'t tell the plant biologists we called vegetation \"nothing here\"!') + expect(choiceDescription).to.be.ok() // tabbing to the "Identify" button await user.keyboard('[Tab][Tab][Tab]') - const identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) + const identifyButton = screen.getByRole('button', { name: 'SurveyTask.Choice.identify' }) expect(identifyButton).to.equal(document.activeElement) // pressing Enter to identify and close the choice (Nothing here) await user.keyboard('[Enter]') - // confirm choice (Nothing here) heading, and therefore choice, is not shown - choiceHeading = queryByRole('heading', { name: 'Fire' }) - expect(choiceHeading).to.be.null() + // confirm choice (Nothing here) description, and therefore choice, is not shown + choiceDescription = screen.queryByText('Don\'t tell the plant biologists we called vegetation \"nothing here\"!') + expect(choiceDescription).to.be.null() // confirm choices are shown - const choiceButtons = getAllByRole('menuitemcheckbox') + const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(6) // confirm the identified choice (Nothing here) is the active choice - const nothingHereChoiceButton = getByRole('menuitemcheckbox', { name: 'Nothing here' }) + const nothingHereChoiceButton = Array.from(choiceButtons).find(choiceButton => choiceButton.textContent === 'Nothing here') expect(nothingHereChoiceButton).to.equal(document.activeElement) }) - it.skip('should disable the Identify button until required questions are answered', async function () { - const user = userEvent.setup({ delay: null }) - const { getByRole } = render() + it('should disable the Identify button until required questions are answered', async function () { // tabbing to the first choice (Aardvark) and pressing Enter to open the choice (Aardvark) await user.keyboard('[Tab][Enter]') - let identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) + let identifyButton = screen.getByTestId('choice-identify-button') // confirm the Identify button is disabled, pending required questions answered expect(identifyButton.disabled).to.be.true() // the required questions for Aardvark are "How many?" and "What behavior do you see?" - // the following answers "How many?" with "1" and "What behavior do you see?" with "Eating" + // the following answers "How many?" with "1" and "What behavior do you see?" with "Resting" - // tabbing (x3) to the "How many?" question, selecting the "1" answer with space key, tabbing (x4) to the "What behavior do you see?" question, selecting the "Eating" answer with space key - await user.keyboard('[Tab][Tab][Tab][Space][Tab][Tab][Tab][Tab][Space]') + // tabbing (x3) to the "How many?" question, selecting the "1" answer with space key, tabbing (x1) to the "What behavior do you see?" question, selecting the "Resting" answer with space key + await user.keyboard('[Tab][Tab][Tab][Space][Tab][Space]') // confirm the Identify button is enabled, now that required questions are answered - identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) + identifyButton = screen.getByTestId('choice-identify-button') // confirm the Identify button is enabled, now that required questions answered expect(identifyButton.disabled).to.be.false() }) }) - - it.skip('should remove a previously identified choice with delete key', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole } = render() - let choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) - await user.click(choiceButton) - const identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) - // identify choice (Fire) and close choice (Fire) component - await user.click(identifyButton) - // confirm choices showing - const choiceButtons = getAllByRole('menuitemcheckbox') - expect(choiceButtons.length).to.equal(6) - - // confirm choice Fire selected - choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) - expect(choiceButton.getAttribute('aria-checked')).to.equal('true') - - // confirm choice Fire active element - expect(choiceButton).to.equal(document.activeElement) - - // press delete key to remove choice (Fire) - await user.keyboard('[Delete]') - // confirm choice Fire not selected - choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) - expect(choiceButton.getAttribute('aria-checked')).to.equal('false') - }) - - it.skip('should remove a previously identified choice with backspace key', async function () { - const user = userEvent.setup({ delay: null }) - const { getAllByRole, getByRole } = render() - let choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) - await user.click(choiceButton) - const identifyButton = getByRole('button', { name: 'SurveyTask.Choice.identify' }) - // identify choice (Fire) and close choice (Fire) component - await user.click(identifyButton) - // confirm choices showing - const choiceButtons = getAllByRole('menuitemcheckbox') - expect(choiceButtons.length).to.equal(6) - - // confirm choice Fire selected - choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) - expect(choiceButton.getAttribute('aria-checked')).to.equal('true') - - // confirm choice Fire active element - expect(choiceButton).to.equal(document.activeElement) - - // press backspace key to remove choice (Fire) - await user.keyboard('[Backspace]') - // confirm choice Fire not selected - choiceButton = getByRole('menuitemcheckbox', { name: 'Fire' }) - expect(choiceButton.getAttribute('aria-checked')).to.equal('false') - }) }) }) diff --git a/packages/lib-classifier/src/plugins/tasks/survey/components/components/Choice/Choice.js b/packages/lib-classifier/src/plugins/tasks/survey/components/components/Choice/Choice.js index 041ffa9a35..6db408fd50 100644 --- a/packages/lib-classifier/src/plugins/tasks/survey/components/components/Choice/Choice.js +++ b/packages/lib-classifier/src/plugins/tasks/survey/components/components/Choice/Choice.js @@ -97,6 +97,7 @@ export default function Choice({ onClick={() => handleDelete(choiceId)} /> Choice', function () { expect(screen.queryAllByRole('checkbox', { hidden: true })).to.have.lengthOf(0) }) }) + + describe('with choice with required questions unanswered', function () { + // choice 'RDVRK' (Aardvark) has 2 required questions + + it('should disable the Identify button', function () { + render( + + ) + expect(screen.getByRole('button', { name: 'SurveyTask.Choice.identify' }).disabled).to.be.true() + }) + }) + + describe('with choice with required questions answered', function () { + // choice 'RDVRK' (Aardvark) has 2 required questions + + it('should enable the Identify button', function () { + render( + + ) + expect(screen.getByRole('button', { name: 'SurveyTask.Choice.identify' }).disabled).to.be.false() + }) + }) }) diff --git a/packages/lib-classifier/src/plugins/tasks/survey/components/components/Chooser/Chooser.js b/packages/lib-classifier/src/plugins/tasks/survey/components/components/Chooser/Chooser.js index 0978d6b725..a4c6573613 100644 --- a/packages/lib-classifier/src/plugins/tasks/survey/components/components/Chooser/Chooser.js +++ b/packages/lib-classifier/src/plugins/tasks/survey/components/components/Chooser/Chooser.js @@ -20,6 +20,10 @@ function Chooser ({ }) { const [filterDropOpen, setFilterDropOpen] = useState(false) + function clearFilters() { + handleFilter() + } + function handleFilterDropClose () { setFilterDropOpen(false) } @@ -56,7 +60,7 @@ function Chooser ({ /> {showFilters ? () diff --git a/packages/lib-classifier/src/plugins/tasks/survey/components/components/Chooser/components/CharacteristicsFilter/ClearFilters/ClearFilters.js b/packages/lib-classifier/src/plugins/tasks/survey/components/components/Chooser/components/CharacteristicsFilter/ClearFilters/ClearFilters.js index 686f70d79b..5f494ffc10 100644 --- a/packages/lib-classifier/src/plugins/tasks/survey/components/components/Chooser/components/CharacteristicsFilter/ClearFilters/ClearFilters.js +++ b/packages/lib-classifier/src/plugins/tasks/survey/components/components/Chooser/components/CharacteristicsFilter/ClearFilters/ClearFilters.js @@ -4,13 +4,12 @@ import PropTypes from 'prop-types' import { PlainButton, SpacedText } from '@zooniverse/react-components' import { useTranslation } from '@translations/i18n' -export default function ClearFilters (props) { - const { - handleFilter, - showingChoices, - totalChoices - } = props - +const defaultHandler = () => true +export default function ClearFilters ({ + onClick = defaultHandler, + showingChoices = 0, + totalChoices = 0 +}) { const { t } = useTranslation('plugins') return ( @@ -27,22 +26,16 @@ export default function ClearFilters (props) { } - onClick={() => handleFilter()} + icon={