From a527d44e12d51b0efdeebe534847ac80d5835b07 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 22 Jan 2021 14:12:07 -0800 Subject: [PATCH] Handle removing last word of empty text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sooo, I added this more graceful regex and error logging… then realized that this shouldn't be happening in the first place, because we should only be removing the last word of the query if you picked the filter via typing, not advanced search! I'm glad to have the assertion error and the new handler, but I'll fix the cause too in the next change :p --- src/app/WardrobePage/SearchToolbar.js | 29 +++++++++++++++++++++++---- src/app/util.js | 12 +++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/app/WardrobePage/SearchToolbar.js b/src/app/WardrobePage/SearchToolbar.js index c3094a3..ac0fc17 100644 --- a/src/app/WardrobePage/SearchToolbar.js +++ b/src/app/WardrobePage/SearchToolbar.js @@ -22,6 +22,7 @@ import { ClassNames } from "@emotion/react"; import Autosuggest from "react-autosuggest"; import useCurrentUser from "../components/useCurrentUser"; +import { logAndCapture } from "../util"; export const emptySearchQuery = { value: "", @@ -192,12 +193,9 @@ function SearchToolbar({ } }} onSuggestionSelected={(e, { suggestion }) => { - const valueWithoutLastWord = query.value - ? query.value.match(/^(.*?)\s*\S+$/)[1] - : query.value; onChange({ ...query, - value: valueWithoutLastWord, + value: removeLastWord(query.value), filterToZoneLabel: suggestion.zoneLabel || query.filterToZoneLabel, filterToItemKind: suggestion.itemKind || query.filterToItemKind, filterToCurrentUserOwnsOrWants: @@ -425,4 +423,27 @@ function pluralizeZoneLabel(zoneLabel) { } } +/** + * removeLastWord returns a copy of the text, with the last word and any + * preceding space removed. + */ +function removeLastWord(text) { + // This regex matches the full text, and assigns the last word and any + // preceding text to subgroup 2, and all preceding text to subgroup 1. If + // there's no last word, we'll still match, and the full string will be in + // subgroup 1, including any space - no changes made! + const match = text.match(/^(.*?)(\s*\S+)?$/); + if (!match) { + logAndCapture( + new Error( + `Assertion failure: pattern should match any input text, ` + + `but failed to match ${JSON.stringify(text)}` + ) + ); + return text; + } + + return match[1]; +} + export default SearchToolbar; diff --git a/src/app/util.js b/src/app/util.js index 5a65e09..adbc144 100644 --- a/src/app/util.js +++ b/src/app/util.js @@ -1,6 +1,7 @@ import React from "react"; import { Box, Heading, useColorModeValue } from "@chakra-ui/react"; import loadableLibrary from "@loadable/component"; +import * as Sentry from "@sentry/react"; /** * Delay hides its content at first, then shows it after the given delay. @@ -317,3 +318,14 @@ export function loadable(load, options) { options ); } + +/** + * logAndCapture will print an error to the console, and send it to Sentry. + * + * This is useful when there's a graceful recovery path, but it's still a + * genuinely unexpected error worth logging. + */ +export function logAndCapture(e) { + console.error(e); + Sentry.captureException(e); +}