fix(smartfuzzy): handle empty search strings safely and update tests for stricter TypeScript compatibility

This commit is contained in:
2026-05-01 16:02:29 +00:00
parent 58109bd7e0
commit 31c7865d88
12 changed files with 3676 additions and 4989 deletions
+37 -22
View File
@@ -1,39 +1,49 @@
import { expect, tap } from '@push.rocks/tapbundle';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as tsclass from '@tsclass/tsclass';
import * as smartfuzzy from '../ts/index.js';
// Create fixed timestamps for consistent test results
const timestamp1 = 1620000000000; // May 2021
const timestamp2 = 1620086400000; // May 2021 + 1 day
const testAuthor: tsclass.content.IAuthor = {
firstName: 'Test',
surName: 'Author',
birthday: {
day: 1,
month: 1,
year: 1980,
},
articles: [],
};
// Test articles with known content
const testArticles: tsclass.content.IArticle[] = [
{
title: 'Berlin has a ambivalent history',
content: 'it is known that Berlin has an interesting history',
author: null,
author: testAuthor,
tags: ['city', 'Europe', 'history', 'travel'],
timestamp: timestamp1,
featuredImageUrl: null,
url: null,
featuredImageUrl: undefined,
url: undefined,
},
{
title: 'Washington is a great city',
content: 'it is known that Washington is one of the greatest cities in the world',
author: null,
author: testAuthor,
tags: ['city', 'USA', 'travel', 'politics'],
timestamp: timestamp2,
featuredImageUrl: null,
url: null,
featuredImageUrl: undefined,
url: undefined,
},
{
title: 'Travel tips for European cities',
content: 'Here are some travel tips for European cities including Berlin and Paris',
author: null,
author: testAuthor,
tags: ['travel', 'Europe', 'tips'],
timestamp: timestamp2,
featuredImageUrl: null,
url: null,
featuredImageUrl: undefined,
url: undefined,
}
];
@@ -59,14 +69,19 @@ tap.test('should search by exact tag match', async () => {
expect(result.length).toBeGreaterThan(0);
// First result should be the Washington article (contains USA tag)
expect(result[0].item.title).toInclude('Washington');
const firstResult = result[0];
if (!firstResult) {
throw new Error('Expected at least one result');
}
expect(firstResult.item.title).toInclude('Washington');
// Should include match information
expect(result[0].matches).toBeDefined();
expect(result[0].matches.length).toBeGreaterThan(0);
const matches = firstResult.matches ?? [];
expect(matches).toBeDefined();
expect(matches.length).toBeGreaterThan(0);
// At least one match should be for the 'USA' tag
const tagMatch = result[0].matches.find(m => m.key === 'tags' && m.value === 'USA');
const tagMatch = matches.find((match) => match.key === 'tags' && match.value === 'USA');
expect(tagMatch).toBeDefined();
});
@@ -79,8 +94,8 @@ tap.test('should search by title and content', async () => {
// The Travel article mentions Berlin in content, so it should be included
// but ranked lower
const berlinArticleIndex = result.findIndex(r => r.item.title.includes('Berlin'));
const travelArticleIndex = result.findIndex(r => r.item.title.includes('Travel'));
const berlinArticleIndex = result.findIndex((searchResult) => searchResult.item.title.includes('Berlin'));
const travelArticleIndex = result.findIndex((searchResult) => searchResult.item.title.includes('Travel'));
expect(berlinArticleIndex).toBeLessThan(travelArticleIndex);
});
@@ -93,11 +108,11 @@ tap.test('should add articles incrementally', async () => {
const newArticle: tsclass.content.IArticle = {
title: 'New Article',
content: 'This is a new article about technology',
author: null,
author: testAuthor,
tags: ['technology', 'new'],
timestamp: Date.now(),
featuredImageUrl: null,
url: null,
featuredImageUrl: undefined,
url: undefined,
};
newSearch.addArticle(newArticle);
@@ -113,11 +128,11 @@ tap.test('should add articles incrementally', async () => {
const anotherArticle: tsclass.content.IArticle = {
title: 'Another Tech Article',
content: 'Another article about technology innovations',
author: null,
author: testAuthor,
tags: ['technology', 'innovation'],
timestamp: Date.now(),
featuredImageUrl: null,
url: null,
featuredImageUrl: undefined,
url: undefined,
};
newSearch.addArticle(anotherArticle);
+3 -3
View File
@@ -1,4 +1,4 @@
import { expect, tap } from '@push.rocks/tapbundle';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as smartfuzzy from '../ts/index.js';
class Car {
@@ -73,11 +73,11 @@ tap.test('should sort objects by multiple field search', async () => {
// fuzzy matching algorithm's threshold setting
// BMW should be the first result
const bmwIndex = result.findIndex(r => r.item.brand === 'BMW');
const bmwIndex = result.findIndex((fuzzyResult) => fuzzyResult.item.brand === 'BMW');
expect(bmwIndex).toEqual(0);
// If Toyota is in results, it should be ranked lower than BMW
const toyotaIndex = result.findIndex(r => r.item.brand === 'Toyota');
const toyotaIndex = result.findIndex((fuzzyResult) => fuzzyResult.item.brand === 'Toyota');
if (toyotaIndex !== -1) {
expect(bmwIndex).toBeLessThan(toyotaIndex);
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { expect, tap } from '@push.rocks/tapbundle';
import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as smartfuzzy from '../ts/index.js';
let testSmartfuzzy: smartfuzzy.Smartfuzzy;