fix: encode history term in autocomplete navigation links - #222
Conversation
History rows in the `autocomplete-result-list.v2` block now apply the codebase-internal `encodeUrlString` placeholder (`/` -> `$2F`) to the navigation `value`, mirroring what the "see all" link in `TileList` already does. Without this, terms containing `/` (e.g. `12/3 Romex`) were interpolated verbatim into the route slug by `vtex.render-runtime` `<Link>`, splitting the term into multiple path segments and breaking the search route at click time. The visible label stays decoded (`decodeUrlString`) and the `biggy-search-history` cookie format is unchanged. Also adds a Jest test setup via `@vtex/test-tools` (matching sibling IS apps); `make test` now runs the suite and `make check` includes it. Initial coverage targets the encoding helpers and the new `buildHistoryItemValue` helper. Spec: is-io-specs/specs/fix-autocomplete-history-link-encoding/spec.md
|
Hi! I'm VTEX IO CI/CD Bot and I'll be helping you to publish your app! 🤖 Please select which version do you want to release:
And then you just need to merge your PR when you are ready! There is no need to create a release commit/tag.
|
|
Beep boop 🤖 I noticed you didn't make any changes at the
In order to keep track, I'll create an issue if you decide now is not a good time
|
The platform builder's at-loader was type-checking the new test files under react/utils/__tests__/ and failing with TS2593/TS2304 errors because jest globals (`describe`, `it`, `expect`) aren't recognised without the jest types in scope. Aligns the test-setup convention with sibling repos (notably `vtex.delivery-promise-components`): - `.vtexignore`: exclude `**/__tests__`, `**/__mocks__`, `**/*.test.*` from the platform build (matches sibling `.vtexignore`). - `react/tsconfig.json`: add `"types": ["jest", "node"]` so editor / local tsc passes recognise jest globals (matches sibling tsconfig). Tests still run via `make test` / `yarn test` (vtex-test-tools), all 14 unit tests green. Spec: is-io-specs/specs/fix-autocomplete-history-link-encoding/spec.md
Manual verification showed the previous fix produced `12$2f3%20romex` in the path slug — the codebase-internal `$2F` placeholder used by `encodeUrlString` — instead of the `12%2f3%20romex` emitted by the search bar. Although both forms decode to the same `term` route param, the visible mismatch is the regression the spec's US-1 acceptance criterion was designed to prevent. Switches `buildHistoryItemValue` to standard `encodeURIComponent`, wrapped in `safeEncodeURIComponent` to stay idempotent against legacy cookie entries that may already contain percent-encoded triplets (decode-then-encode round-trip; falls back to verbatim encoding when the input contains a malformed `%XX`). The legacy `encodeUrlString` placeholder remains in use by `TileList`'s "see all" link and is not touched here. Harmonising both code paths is logged as a follow-up in the spec. Tests updated to assert the standard `%2F` form plus two extra cases: lowercase `%2f` recognition (idempotency) and malformed-triplet fallback. All 16 tests green. Spec: is-io-specs/specs/fix-autocomplete-history-link-encoding/spec.md
…inks Replaces legacy $2F encoding with standard percent-encoding (%2F) for both history item links and the "see all" link in autocomplete dropdown, matching the search bar's encoding behavior since vtex.store-components@0e9a0ee5. Changes: - Create react/utils/term-encoding.ts with buildHistoryItemValue and buildSearchTermRouteValue helpers (both backed by safeEncodeURIComponent) - Update Autocomplete#updateHistory to use buildHistoryItemValue for history item values - Update Autocomplete#contentWhenQueryIsNotEmpty to use buildSearchTermRouteValue for the "see all" link - Remove react/utils/history-items.ts (functionality moved to term-encoding.ts) - Add comprehensive test coverage in term-encoding.test.ts - Mark encodeUrlString as deprecated (no live callers after this fix) - Update CHANGELOG.md Spec: is-io-specs/specs/fix-autocomplete-history-link-encoding/spec.md Co-authored-by: Cursor <cursoragent@cursor.com>
2bab39b to
e21e6e7
Compare
…h terms The cookie stored entries as a raw comma-joined string, so any term containing a `,` (e.g. `shoes, size 10`) would silently split into two unrelated history entries on the next read. The same was true for `;` and other cookie-significant characters. Changes: - Extract cookie persistence into a new react/utils/search-history.ts module. Each entry is percent-encoded before being joined and decoded after being split, so any character is now safe. - BiggyClient.searchHistory / prependSearchHistory delegate to the new module (kept as thin pass-throughs for backwards compatibility). - Autocomplete#addTermToHistory uses decodeURIComponent (instead of decodeURI) so the canonical, fully-decoded form is what gets persisted. - Add comprehensive test coverage in search-history.test.ts (term with comma, percent, semicolon, equals, slash, plus de-duplication and limit behavior). - Update CHANGELOG. Spec: is-io-specs/specs/fix-autocomplete-history-link-encoding/spec.md (Decision 4, US-4) Co-authored-by: Cursor <cursoragent@cursor.com>
|
Your PR has been merged! App is being published. 🚀 After the publishing process has been completed (check #vtex-io-releases) and doing A/B tests with the new version, you can deploy your release by running:
After that your app will be updated on all accounts. For more information on the deployment process check the docs. 📖 |
Problem
History links broken for terms with special characters: When shoppers clicked autocomplete history entries containing / (e.g., "12/3 Romex"), the URL was malformed and failed to load the PLP.
Root cause: History links used unencoded path segments (/12/3 Romex), which the router interpreted as multiple segments instead of a single search term. The search bar correctly encodes these (/12%2F3%20romex), but the autocomplete didn't match.
Additional issues discovered:
"See all" link inconsistency: Used legacy $2F encoding instead of standard %2F, diverging from the search bar
Cookie corruption bug: Search terms containing , (or other cookie separators like ;, %, =) would split or corrupt the history list
Solution
Three coordinated fixes in a single PR:
Standardized URL encoding (react/utils/term-encoding.ts):
Created encodeSearchTerm() helper using standard encodeURIComponent (/ → %2F, space → %20)
Idempotent design handles legacy cookie entries without double-encoding
Used by both history rows and "see all" link for consistency
Cookie robustness (react/utils/search-history.ts):
Extracted cookie persistence into dedicated module
Per-entry percent-encoding before storing (any character now survives round-trip)
Changed addTermToHistory from decodeURI → decodeURIComponent for canonical storage
Updated autocomplete component (react/components/Autocomplete/index.tsx):
History rows: value now uses encodeSearchTerm(item)
"See all" link: switched from encodeUrlString to encodeSearchTerm
Both now produce URLs identical to the search bar
Impact
✅ History links now work for terms with /, spaces, and other special characters
✅ "See all" matches search bar - no more $2F vs %2F inconsistency
✅ Cookie survives any character - terms with ,, ;, %, = no longer corrupt history
✅ Backward compatible - legacy cookies read correctly
✅ Test coverage - regression protection for future changes
Before/After
Search term: "12/3 Romex"
/12%2F3%20romex✅/12%2F3%20romex✅/12/3%20Romex❌/12%2F3%20romex✅/12$2F3%20romex/12%2F3%20romex✅Cookie: "shoes, size 10"