From 45951d2610f47fc825606e7767469065de603e28 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Mon, 12 May 2025 13:42:49 +0000 Subject: [PATCH] fix(tests): Standardize test syntax and update testing dependencies --- changelog.md | 7 ++++ package.json | 1 + pnpm-lock.yaml | 3 ++ readme.plan.md | 23 +++------- test/test.articlesearch.ts | 2 +- test/test.objectsorter.ts | 86 ++++++++++++++++++++++++++++++++------ test/test.smartfuzzy.ts | 63 +++++++++++++++++++++++----- ts/00_commitinfo_data.ts | 2 +- 8 files changed, 144 insertions(+), 43 deletions(-) diff --git a/changelog.md b/changelog.md index 6b5411d..64df502 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2025-05-12 - 1.1.8 - fix(tests) +Standardize test syntax and update testing dependencies + +- Added @git.zone/tsrun dependency to package.json for improved test runner support +- Refactored test export in test/test.articlesearch.ts to use default export instead of tap.start() +- Updated readme.plan.md to describe testing improvements and syntax standardization + ## 2025-05-12 - 1.1.7 - fix(build) Fix import paths, update CI workflows and upgrade dependencies for ESM compliance diff --git a/package.json b/package.json index 6f6b6b5..fbf012f 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ }, "devDependencies": { "@git.zone/tsbuild": "^2.1.27", + "@git.zone/tsrun": "^1.3.3", "@git.zone/tstest": "^1.0.57", "@push.rocks/tapbundle": "^6.0.3", "@types/node": "^22.15.17" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 169a037..088f9cb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,6 +24,9 @@ importers: '@git.zone/tsbuild': specifier: ^2.1.27 version: 2.3.2 + '@git.zone/tsrun': + specifier: ^1.3.3 + version: 1.3.3 '@git.zone/tstest': specifier: ^1.0.57 version: 1.0.96(@aws-sdk/credential-providers@3.806.0)(socks@2.8.4)(typescript@5.8.3) diff --git a/readme.plan.md b/readme.plan.md index 6d041fa..2bd681a 100644 --- a/readme.plan.md +++ b/readme.plan.md @@ -3,28 +3,22 @@ ## Current Status - ESM imports/exports fixed with .js extensions - Basic fuzzy matching functionality works -- Tests run individually with tsx but fail with pnpm test +- Testing infrastructure fixed with @git.zone/tsrun dependency +- Test syntax needs standardization (converting from chai-style to SmartExpect syntax) - Using older versions of dependencies ## Improvement Plan -### 1. Fix Testing Infrastructure +### 1. Testing Improvements -#### 1.1 Fix Test Runner Configuration -- [ ] Investigate why `pnpm test` fails while individual tests run with `tsx` succeed -- [ ] Check if `tsrun` command is properly installed and available (current error shows "tsrun: command not found") -- [ ] Examine the `tstest` configuration in package.json and update if needed -- [ ] Verify that `@git.zone/tstest` dependency is properly installed and configured -- [ ] Consider updating the test script to use `tsx` directly if `tstest` continues to be problematic - -#### 1.2 Update Test Syntax and Standards +#### 1.1 Update Test Syntax and Standards - [ ] Convert all tests from chai-style syntax (`expect().to.be`) to SmartExpect syntax (`expect().toBeInstanceOf()`) - [ ] Implement consistent test structure across all test files - [ ] Add proper setup and teardown patterns where needed - [ ] Replace console.log statements with proper assertions to validate results - [ ] Add descriptive error messages to assertions to improve test debugging -#### 1.3 Expand Test Coverage +#### 1.2 Expand Test Coverage - [ ] Add tests for empty dictionaries and edge cases - [ ] Test with extremely large dictionaries to verify performance - [ ] Add tests for unicode/special character handling @@ -32,13 +26,6 @@ - [ ] Add tests for error conditions and input validation - [ ] Implement tests for all public APIs and features -#### 1.4 Test Automation and CI -- [ ] Add test coverage reporting -- [ ] Set up continuous integration for automated testing -- [ ] Add performance regression tests -- [ ] Create test fixtures for consistent test data -- [ ] Add browser-based tests for web compatibility - ### 2. Code Quality Improvements - [ ] Add proper TypeScript documentation comments to all public methods - [ ] Implement consistent error handling diff --git a/test/test.articlesearch.ts b/test/test.articlesearch.ts index 5ce74f1..9957457 100644 --- a/test/test.articlesearch.ts +++ b/test/test.articlesearch.ts @@ -31,4 +31,4 @@ tap.test('should sort objects', async () => { console.log(result[0].matches); }); -tap.start(); +export default tap.start(); diff --git a/test/test.objectsorter.ts b/test/test.objectsorter.ts index dbf24e2..416be77 100644 --- a/test/test.objectsorter.ts +++ b/test/test.objectsorter.ts @@ -1,19 +1,81 @@ import { expect, tap } from '@push.rocks/tapbundle'; import * as smartfuzzy from '../ts/index.js'; -tap.test('should sort objects', async () => { - class Car { - constructor(public brand: string) {} - } +class Car { + constructor(public brand: string, public model?: string, public year?: number) {} +} - const testObjectSorter = new smartfuzzy.ObjectSorter([ - new Car('BMW'), - new Car('Mercedes Benz'), - new Car('Volvo'), - ]); +const testCars = [ + new Car('BMW', 'X5', 2022), + new Car('Mercedes Benz', 'S-Class', 2021), + new Car('Volvo', 'XC90', 2023), + new Car('Volkswagen', 'Golf', 2020), + new Car('Audi', 'A4', 2022), +]; - const result = testObjectSorter.sort('Volvo', ['brand']); - console.log(result); +let objectSorter: smartfuzzy.ObjectSorter; + +tap.test('should create an instance of ObjectSorter', async () => { + objectSorter = new smartfuzzy.ObjectSorter(testCars); + expect(objectSorter).toBeInstanceOf(smartfuzzy.ObjectSorter); + expect(objectSorter.objectDictionary).toEqual(testCars); + + // Test empty constructor + const emptyObjectSorter = new smartfuzzy.ObjectSorter(); + expect(emptyObjectSorter.objectDictionary).toEqual([]); }); -tap.start(); +tap.test('should sort objects by exact brand match', async () => { + const result = objectSorter.sort('Volvo', ['brand']); + + // Should return an array of results + expect(result).toBeArray(); + expect(result.length).toBeGreaterThan(0); + + // First result should be the Volvo + expect(result[0].item.brand).toEqual('Volvo'); + + // Should have expected result structure + expect(result[0]).toHaveProperty('item'); + expect(result[0]).toHaveProperty('refIndex'); + expect(result[0].refIndex).toBeTypeofNumber(); + + // Reference index should match the original array position + expect(result[0].refIndex).toEqual(2); // Volvo is at index 2 +}); + +tap.test('should sort objects by fuzzy brand match', async () => { + // "Wolvo" should fuzzy match to "Volvo" + const result = objectSorter.sort('Wolvo', ['brand']); + + expect(result.length).toBeGreaterThan(0); + expect(result[0].item.brand).toEqual('Volvo'); +}); + +tap.test('should sort objects by multiple field search', async () => { + // Add a car with similar model name but different brand + objectSorter = new smartfuzzy.ObjectSorter([ + ...testCars, + new Car('Toyota', 'X5 Replica', 2020), + ]); + + // Search across both brand and model + const result = objectSorter.sort('BMW X5', ['brand', 'model']); + + expect(result.length).toBeGreaterThan(0); + + // BMW X5 should be first result + expect(result[0].item.brand).toEqual('BMW'); + expect(result[0].item.model).toEqual('X5'); + + // Toyota X5 Replica should also be in results but lower ranked + const toyotaResult = result.find(r => r.item.brand === 'Toyota'); + expect(toyotaResult).toBeDefined(); + + // Toyota should be ranked lower than BMW + const bmwIndex = result.findIndex(r => r.item.brand === 'BMW'); + const toyotaIndex = result.findIndex(r => r.item.brand === 'Toyota'); + expect(bmwIndex).toBeLessThan(toyotaIndex); +}); + +export default tap.start(); diff --git a/test/test.smartfuzzy.ts b/test/test.smartfuzzy.ts index d8c40f6..4116da5 100644 --- a/test/test.smartfuzzy.ts +++ b/test/test.smartfuzzy.ts @@ -2,25 +2,66 @@ import { expect, tap } from '@push.rocks/tapbundle'; import * as smartfuzzy from '../ts/index.js'; let testSmartfuzzy: smartfuzzy.Smartfuzzy; +const testDictionary = [ + 'Sony', + 'Deutsche Bahn', + 'Apple Inc.', + "Trader Joe's", +]; tap.test('should create an instance of Smartfuzzy', async () => { - testSmartfuzzy = new smartfuzzy.Smartfuzzy([ - 'Sony', - 'Deutsche Bahn', - 'Apple Inc.', - "Trader Joe's", - ]); + testSmartfuzzy = new smartfuzzy.Smartfuzzy(testDictionary); expect(testSmartfuzzy).toBeInstanceOf(smartfuzzy.Smartfuzzy); + expect(testSmartfuzzy.dictionary).toEqual(testDictionary); }); -tap.test('should compute a score', async () => { +tap.test('should compute a score for a string against the dictionary', async () => { const result = testSmartfuzzy.getChangeScoreForString('Apple'); - console.log(result); + + // Check that we got a dictionary map back + expect(result).toBeTypeOf('object'); + + // Check that every dictionary entry has a score + for (const word of testDictionary) { + expect(result).toHaveProperty(word); + expect(result[word]).toBeTypeofNumber(); + } + + // Check that 'Apple Inc.' has a lower score (better match) than other entries + expect(result['Apple Inc.']).toBeLessThan(result['Sony']); }); -tap.test('should get closest match', async () => { +tap.test('should get closest match for a string', async () => { const result = testSmartfuzzy.getClosestMatchForString('Apple'); - console.log(result); + + // Should return closest match as string + expect(result).toBeTypeofString(); + + // Should match the expected closest entry + expect(result).toEqual('Apple Inc.'); }); -tap.start(); +tap.test('should add words to dictionary', async () => { + const initialLength = testSmartfuzzy.dictionary.length; + + // Add a single word + testSmartfuzzy.addToDictionary('Microsoft'); + expect(testSmartfuzzy.dictionary.length).toEqual(initialLength + 1); + expect(testSmartfuzzy.dictionary).toContain('Microsoft'); + + // Add multiple words + const additionalWords = ['Google', 'Amazon', 'Facebook']; + testSmartfuzzy.addToDictionary(additionalWords); + expect(testSmartfuzzy.dictionary.length).toEqual(initialLength + 4); + for (const word of additionalWords) { + expect(testSmartfuzzy.dictionary).toContain(word); + } +}); + +tap.test('should handle empty query string', async () => { + const result = testSmartfuzzy.getClosestMatchForString(''); + // For empty strings, behavior should be defined (either null or a specific result) + expect(result).toBeNullOrUndefined(); +}); + +export default tap.start(); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 580f1fa..9a0222d 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/smartfuzzy', - version: '1.1.7', + version: '1.1.8', description: 'A library for fuzzy matching strings against word dictionaries or arrays, with support for object and article searching.' }