Skip to content

Commit

Permalink
Vebt 443 update Prevent API call with empty filters (#32115)
Browse files Browse the repository at this point in the history
* #vebt-443 #comment Appended Submit to function name

* #vebt-443 #comment Updated error message to appear and disappear at appropriate times

* #vebt-443 #comment removed comments and fixed reset search

* #vebt-443 #comment Removed comments

---------

Co-authored-by: Chad Chotikasatien <chad.chotikasatien@va.gov.com>
  • Loading branch information
govcioChad and Chad Chotikasatien authored Sep 30, 2024
1 parent 65045dc commit fbd418b
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/applications/gi/components/ClearFiltersBtn.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function ClearFiltersBtn({
accredited: false,
studentVeteran: false,
yellowRibbonScholarship: false,
employers: false,
employers: true,
vettec: false,
preferredProvider: false,
country: 'ALL',
Expand Down
5 changes: 1 addition & 4 deletions src/applications/gi/components/search/KeywordSearch.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export function KeywordSearch({
required,
suggestions,
version,
filters,
dispatchError,
errorReducer,
type,
Expand Down Expand Up @@ -94,9 +93,7 @@ export function KeywordSearch({
if (value !== '') {
debouncedFetchSuggestion(value);
}
if (validateSearchTerm) {
validateSearchTerm(value, dispatchError, error, filters, type);
}
validateSearchTerm(value, dispatchError, error, type);
}
};

Expand Down
8 changes: 8 additions & 0 deletions src/applications/gi/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,11 @@ export const yellowRibbonColumns = {
key: 'contributionAmount',
},
};

export const ERROR_MESSAGES = {
searchByNameInputEmpty:
'Please fill in a school, employer, or training provider.',
searchbyLocationInputEmpty: 'Please fill in a city, state, or postal code.',
invalidZipCode: 'Please enter a valid postal code.',
checkBoxFilterEmpty: 'Please select at least one filter.',
};
42 changes: 39 additions & 3 deletions src/applications/gi/containers/FilterYourResults.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { connect } from 'react-redux';
import _ from 'lodash';
Expand All @@ -14,14 +14,16 @@ import {
sortOptionsByStateName,
addAllOption,
createId,
validateSearchTerm,
validateSearchTermSubmit,
isShowVetTec,
isEmptyCheckboxFilters,
} from '../utils/helpers';
import { showModal, filterChange, setError, focusSearch } from '../actions';
import {
TABS,
INSTITUTION_TYPES,
INSTITUTION_TYPES_DICTIONARY,
ERROR_MESSAGES,
} from '../constants';
import CheckboxGroup from '../components/CheckboxGroup';
import { updateUrlParams } from '../selectors/search';
Expand Down Expand Up @@ -82,6 +84,7 @@ export function FilterYourResults({
const { version } = preview;
const { error } = errorReducer;
const {
schools,
expanded,
excludedSchoolTypes,
excludeCautionFlags,
Expand All @@ -105,6 +108,33 @@ export function FilterYourResults({
specialMissionTRIBAL,
} = filters;

useEffect(
() => {
const isEmpty = isEmptyCheckboxFilters(filters);

if (error === ERROR_MESSAGES.checkBoxFilterEmpty && !isEmpty)
dispatchError(null);
},
[
schools,
excludeCautionFlags,
accredited,
studentVeteran,
yellowRibbonScholarship,
employers,
specialMissionHbcu,
specialMissionMenonly,
specialMissionWomenonly,
specialMissionRelaffil,
specialMissionHSI,
specialMissionNANTI,
specialMissionANNHI,
specialMissionAANAPII,
specialMissionPBI,
specialMissionTRIBAL,
],
);

const facets =
search.tab === TABS.name ? search.name.facets : search.location.facets;
const [nameValue, setNameValue] = useState(
Expand Down Expand Up @@ -208,7 +238,13 @@ export function FilterYourResults({

const updateResults = () => {
if (
validateSearchTerm(nameValue, dispatchError, error, filters, searchType)
validateSearchTermSubmit(
nameValue,
dispatchError,
error,
filters,
searchType,
)
) {
updateInstitutionFilters('search', true);
updateUrlParams(history, search.tab, search.query, filters, version);
Expand Down
41 changes: 38 additions & 3 deletions src/applications/gi/containers/search/FilterBeforeResults.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ import {
createId,
specializedMissionDefinitions,
sortedSpecializedMissionDefinitions,
validateSearchTerm,
validateSearchTermSubmit,
isShowVetTec,
isShowCommunityFocusVACheckbox,
isEmptyCheckboxFilters,
} from '../../utils/helpers';
import { showModal, filterChange, setError } from '../../actions';
import {
TABS,
INSTITUTION_TYPES,
INSTITUTION_TYPES_DICTIONARY,
ERROR_MESSAGES,
} from '../../constants';
import CheckboxGroup from '../../components/CheckboxGroup';
import { updateUrlParams } from '../../selectors/search';
Expand Down Expand Up @@ -344,6 +346,33 @@ export function FilterBeforeResults({
specialMissionTRIBAL,
} = filters;

useEffect(
() => {
const isEmpty = isEmptyCheckboxFilters(filters);

if (error === ERROR_MESSAGES.checkBoxFilterEmpty && !isEmpty)
dispatchError(null);
},
[
schools,
excludeCautionFlags,
accredited,
studentVeteran,
yellowRibbonScholarship,
employers,
specialMissionHbcu,
specialMissionMenonly,
specialMissionWomenonly,
specialMissionRelaffil,
specialMissionHSI,
specialMissionNANTI,
specialMissionANNHI,
specialMissionAANAPII,
specialMissionPBI,
specialMissionTRIBAL,
],
);

const facets =
search.tab === TABS.name ? search.name.facets : search.location.facets;

Expand Down Expand Up @@ -536,7 +565,7 @@ export function FilterBeforeResults({
accredited: false,
studentVeteran: false,
yellowRibbonScholarship: false,
employers: false,
employers: true,
vettec: false,
preferredProvider: false,
country: 'ALL',
Expand Down Expand Up @@ -571,7 +600,13 @@ export function FilterBeforeResults({

const closeAndUpdate = () => {
if (
validateSearchTerm(nameVal, dispatchError, error, filters, searchType)
validateSearchTermSubmit(
nameVal,
dispatchError,
error,
filters,
searchType,
)
) {
recordEvent({
event: 'gibct-form-change',
Expand Down
23 changes: 8 additions & 15 deletions src/applications/gi/containers/search/LocationSearchForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { TABS } from '../../constants';
import { INITIAL_STATE } from '../../reducers/search';
import {
isProductionOrTestProdEnv,
validateSearchTerm,
validateSearchTermSubmit,
} from '../../utils/helpers';

export function LocationSearchForm({
Expand Down Expand Up @@ -84,26 +84,20 @@ export function LocationSearchForm({
[search.loadFromUrl],
);

// const validateSearchTerm = searchTerm => {
// const invalidZipCodePattern = /^\d{6,}$/;

// if (searchTerm.trim() === '') {
// setError('Please fill in a city, state, or postal code.');
// } else if (invalidZipCodePattern.test(searchTerm)) {
// setError('Please enter a valid postal code.');
// } else if (error !== null) {
// setError(null);
// }
// };

const onResetSearchClick = () => {
inputRef.current.focus();
};
const doSearch = event => {
if (event) {
event.preventDefault();
if (
validateSearchTerm(location, dispatchError, error, filters, 'location')
validateSearchTermSubmit(
location,
dispatchError,
error,
filters,
'location',
)
) {
let paramLocation = location;
dispatchMapChanged({ changed: false, distance: null });
Expand Down Expand Up @@ -280,7 +274,6 @@ export function LocationSearchForm({
onSelection={selected => setAutocompleteSelection(selected)}
onUpdateAutocompleteSearchTerm={onUpdateAutocompleteSearchTerm}
suggestions={[...autocomplete.locationSuggestions]}
// validateSearchTerm={validateSearchTerm}
version={version}
/>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/applications/gi/containers/search/NameSearchForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { FILTERS_SCHOOL_TYPE_EXCLUDE_FLIP } from '../../selectors/filters';
import FilterBeforeResults from './FilterBeforeResults';
import {
isProductionOrTestProdEnv,
validateSearchTerm,
validateSearchTermSubmit,
} from '../../utils/helpers';

export function NameSearchForm({
Expand Down Expand Up @@ -121,7 +121,7 @@ export function NameSearchForm({

const handleSubmit = event => {
event.preventDefault();
if (validateSearchTerm(name, dispatchError, error, filters, 'name')) {
if (validateSearchTermSubmit(name, dispatchError, error, filters, 'name')) {
recordEvent({
event: 'gibct-form-change',
'gibct-form-field': 'nameSearch',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ describe('<NameSearchForm>', () => {
});
});
it('validates empty search term correctly', async () => {
const validateSearchTermSpy = sinon.spy();
const validateSearchTermSubmitSpy = sinon.spy();
const props = {
autocomplete: { nameSuggestions: [] },
filters: {
Expand All @@ -99,7 +99,10 @@ describe('<NameSearchForm>', () => {
search: { query: { name: 'some name' }, tab: null, loadFromUrl: false },
};
const screen = renderWithStoreAndRouter(
<NameSearchForm validateSearchTerm={validateSearchTermSpy} {...props} />,
<NameSearchForm
validateSearchTermSubmit={validateSearchTermSubmitSpy}
{...props}
/>,
{
initialState: {
constants: mockConstants(),
Expand All @@ -111,7 +114,7 @@ describe('<NameSearchForm>', () => {
const submitButton = screen.getByRole('button', { name: 'Search' });
userEvent.click(submitButton);
await waitFor(() => {
expect(validateSearchTermSpy.calledWith('')).to.be.false;
expect(validateSearchTermSubmitSpy.calledWith('')).to.be.false;
expect(
screen.getByText(
'Please fill in a school, employer, or training provider.',
Expand All @@ -120,11 +123,11 @@ describe('<NameSearchForm>', () => {
});
});
it('validates with no filters selected', async () => {
const validateSearchTermSpy = sinon.spy();
const validateSearchTermSubmitSpy = sinon.spy();
const doSearchSpy = sinon.spy();
const screen = renderWithStoreAndRouter(
<NameSearchForm
validateSearchTerm={validateSearchTermSpy}
validateSearchTermSubmit={validateSearchTermSubmitSpy}
doSearch={doSearchSpy}
filters={{
...noFilters,
Expand Down Expand Up @@ -154,12 +157,12 @@ describe('<NameSearchForm>', () => {
userEvent.click(submitButton);
});
await waitFor(() => {
expect(validateSearchTermSpy.calledWith('')).to.be.false;
expect(validateSearchTermSubmitSpy.calledWith('')).to.be.false;
expect(screen.queryByText('Please select at least one filter.')).to.exist;
});
});
it('should call doSearch with search?.query?.name', () => {
const validateSearchTermSpy = sinon.spy();
const validateSearchTermSubmitSpy = sinon.spy();
const doSearchSpy = sinon.spy();
const props = {
autocomplete: { nameSuggestions: [] },
Expand All @@ -172,7 +175,7 @@ describe('<NameSearchForm>', () => {
};
renderWithStoreAndRouter(
<NameSearchForm
validateSearchTerm={validateSearchTermSpy}
validateSearchTermSubmit={validateSearchTermSubmitSpy}
doSearch={doSearchSpy}
{...props}
/>,
Expand All @@ -186,7 +189,7 @@ describe('<NameSearchForm>', () => {
expect(doSearchSpy.calledWith('some name')).to.be.false;
});
it('should not call doSearch with search?.query?.name is null', () => {
const validateSearchTermSpy = sinon.spy();
const validateSearchTermSubmitSpy = sinon.spy();
const doSearchSpy = sinon.spy();
const props = {
autocomplete: { nameSuggestions: [] },
Expand All @@ -199,7 +202,7 @@ describe('<NameSearchForm>', () => {
};
renderWithStoreAndRouter(
<NameSearchForm
validateSearchTerm={validateSearchTermSpy}
validateSearchTermSubmit={validateSearchTermSubmitSpy}
doSearch={doSearchSpy}
{...props}
/>,
Expand Down
Loading

0 comments on commit fbd418b

Please sign in to comment.