Refactor queryMatchesTypeahead and add tests

This commit is contained in:
Tom Southall
2022-02-16 19:26:15 +00:00
parent 067a9e9cb8
commit e9135f06e7
5 changed files with 42 additions and 18 deletions

View File

@@ -9,6 +9,7 @@ import { useAutoFocus, useQueryChange } from './effects/containerEffects'
import firstOfType from 'first-of-type'
import undef from '../utils/undef'
import isUndefined from '../utils/isUndefined'
import startsWithCaseInsensitive from '../utils/startsWithCaseInsensitive'
import defaultStyles from './styles/input.styles.js'
// import fetch from 'unfetch' // TODO: may need this if not using Next.js
@@ -224,7 +225,7 @@ export default function Container(props) {
highlightedState &&
hasFocus &&
queryInput.current.value.length > 0 &&
queryMatchesTypeahead(queryInput.current.value, highlightedState.text)
startsWithCaseInsensitive(highlightedState.text, queryInput.current.value)
? highlightedState.text
: ''
const queryValue = formatQuery(queryInput.current.value, typeAheadValue)
@@ -244,13 +245,6 @@ export default function Container(props) {
}
}, [selectedState, setQueryState, onSelect])
const queryMatchesTypeahead = (query, typeahead, caseSensitive = false) => {
return caseSensitive
? typeahead.substring(0, query.length) === query
: typeahead.substring(0, query.length).toLowerCase() ===
query.toLowerCase()
}
const formatQuery = (query, typeahead) => {
const formattedQuery = typeahead.substring(0, query.length)
return formattedQuery.length > 0 &&

View File

@@ -1,5 +1,6 @@
import { useEffect } from 'react'
import setify from 'setify' // Sets input value without changing cursor position
//import startsWithCaseInsensitive from '../../utils/startsWithCaseInsensitive'
export const useAutoFocus = (queryInput, autoFocus) => { // TODO: might be able to use autofus property of input for this - https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-autofocus
useEffect(() => {
@@ -13,7 +14,8 @@ export const useQueryChange = (queryInput, typeaheadInput, queryState, onChange)
const value = (() => {
const currentValue = typeaheadInput.current.value
if (!queryState) return ''
if (!queryMatchesTypeahead(queryState, currentValue, true)) return ''
//if (!queryMatchesTypeahead(queryState, currentValue, true)) return ''
if (!currentValue.startsWith(queryState)) return ''
return currentValue
})()
@@ -22,12 +24,4 @@ export const useQueryChange = (queryInput, typeaheadInput, queryState, onChange)
setify(queryInput.current, queryState)
if (typeof onChange === 'function') onChange(queryState)
}, [queryState, onChange])
}
// TODO export for testing
const queryMatchesTypeahead = (query, typeahead, caseSensitive = false) => {
return caseSensitive
? typeahead.substring(0, query.length) === query
: typeahead.substring(0, query.length).toLowerCase() ===
query.toLowerCase()
}

View File

@@ -1,6 +1,9 @@
import { vi, describe, test, expect, beforeEach } from 'vitest'
import { renderHook } from '@testing-library/react-hooks'
import { useAutoFocus, useQueryChange } from './containerEffects'
import {
useAutoFocus,
useQueryChange
} from './containerEffects'
let inputRef = (value = '') => ( //TODO: Put in a beforeEach when blogging
{

View File

@@ -0,0 +1,8 @@
const startsWithCaseInsensitive = (str, startsWith) => {
if(typeof str !== 'string') return false
if(typeof startsWith !== 'string') return false
return str.toLowerCase().startsWith(startsWith.toLowerCase())
}
export default startsWithCaseInsensitive

View File

@@ -0,0 +1,25 @@
import { describe, test, expect } from 'vitest'
import startsWithCaseInsensitive from './startsWithCaseInsensitive'
describe('startsWithCaseInsensitive', () => {
test('Returns true if they match exactly', () => {
expect(startsWithCaseInsensitive('Foobar', 'foo')).toBe(true)
})
test('Returns true if they match inexactly', () => {
expect(startsWithCaseInsensitive('Foobar', 'foo')).toBe(true)
})
test('Returns false if they do not match', () => {
expect(startsWithCaseInsensitive('Foobar', 'bar')).toBe(false)
})
test('Returns false if either argument is not a string', () => {
expect(startsWithCaseInsensitive(void(0), 'foo')).toBe(false)
expect(startsWithCaseInsensitive('Foobar', void(0))).toBe(false)
})
test('An empty string always matches', () => {
expect(startsWithCaseInsensitive('Foobar', '')).toBe(true)
})
})