fix(tests): Standardize test syntax and update testing dependencies

This commit is contained in:
Philipp Kunz 2025-05-12 13:42:49 +00:00
parent 283703ec78
commit 45951d2610
8 changed files with 144 additions and 43 deletions

View File

@ -1,5 +1,12 @@
# Changelog # 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) ## 2025-05-12 - 1.1.7 - fix(build)
Fix import paths, update CI workflows and upgrade dependencies for ESM compliance Fix import paths, update CI workflows and upgrade dependencies for ESM compliance

View File

@ -15,6 +15,7 @@
}, },
"devDependencies": { "devDependencies": {
"@git.zone/tsbuild": "^2.1.27", "@git.zone/tsbuild": "^2.1.27",
"@git.zone/tsrun": "^1.3.3",
"@git.zone/tstest": "^1.0.57", "@git.zone/tstest": "^1.0.57",
"@push.rocks/tapbundle": "^6.0.3", "@push.rocks/tapbundle": "^6.0.3",
"@types/node": "^22.15.17" "@types/node": "^22.15.17"

3
pnpm-lock.yaml generated
View File

@ -24,6 +24,9 @@ importers:
'@git.zone/tsbuild': '@git.zone/tsbuild':
specifier: ^2.1.27 specifier: ^2.1.27
version: 2.3.2 version: 2.3.2
'@git.zone/tsrun':
specifier: ^1.3.3
version: 1.3.3
'@git.zone/tstest': '@git.zone/tstest':
specifier: ^1.0.57 specifier: ^1.0.57
version: 1.0.96(@aws-sdk/credential-providers@3.806.0)(socks@2.8.4)(typescript@5.8.3) version: 1.0.96(@aws-sdk/credential-providers@3.806.0)(socks@2.8.4)(typescript@5.8.3)

View File

@ -3,28 +3,22 @@
## Current Status ## Current Status
- ESM imports/exports fixed with .js extensions - ESM imports/exports fixed with .js extensions
- Basic fuzzy matching functionality works - 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 - Using older versions of dependencies
## Improvement Plan ## Improvement Plan
### 1. Fix Testing Infrastructure ### 1. Testing Improvements
#### 1.1 Fix Test Runner Configuration #### 1.1 Update Test Syntax and Standards
- [ ] 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
- [ ] Convert all tests from chai-style syntax (`expect().to.be`) to SmartExpect syntax (`expect().toBeInstanceOf()`) - [ ] Convert all tests from chai-style syntax (`expect().to.be`) to SmartExpect syntax (`expect().toBeInstanceOf()`)
- [ ] Implement consistent test structure across all test files - [ ] Implement consistent test structure across all test files
- [ ] Add proper setup and teardown patterns where needed - [ ] Add proper setup and teardown patterns where needed
- [ ] Replace console.log statements with proper assertions to validate results - [ ] Replace console.log statements with proper assertions to validate results
- [ ] Add descriptive error messages to assertions to improve test debugging - [ ] 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 - [ ] Add tests for empty dictionaries and edge cases
- [ ] Test with extremely large dictionaries to verify performance - [ ] Test with extremely large dictionaries to verify performance
- [ ] Add tests for unicode/special character handling - [ ] Add tests for unicode/special character handling
@ -32,13 +26,6 @@
- [ ] Add tests for error conditions and input validation - [ ] Add tests for error conditions and input validation
- [ ] Implement tests for all public APIs and features - [ ] 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 ### 2. Code Quality Improvements
- [ ] Add proper TypeScript documentation comments to all public methods - [ ] Add proper TypeScript documentation comments to all public methods
- [ ] Implement consistent error handling - [ ] Implement consistent error handling

View File

@ -31,4 +31,4 @@ tap.test('should sort objects', async () => {
console.log(result[0].matches); console.log(result[0].matches);
}); });
tap.start(); export default tap.start();

View File

@ -1,19 +1,81 @@
import { expect, tap } from '@push.rocks/tapbundle'; import { expect, tap } from '@push.rocks/tapbundle';
import * as smartfuzzy from '../ts/index.js'; import * as smartfuzzy from '../ts/index.js';
tap.test('should sort objects', async () => { class Car {
class Car { constructor(public brand: string, public model?: string, public year?: number) {}
constructor(public brand: string) {} }
}
const testObjectSorter = new smartfuzzy.ObjectSorter<Car>([ const testCars = [
new Car('BMW'), new Car('BMW', 'X5', 2022),
new Car('Mercedes Benz'), new Car('Mercedes Benz', 'S-Class', 2021),
new Car('Volvo'), new Car('Volvo', 'XC90', 2023),
]); new Car('Volkswagen', 'Golf', 2020),
new Car('Audi', 'A4', 2022),
];
const result = testObjectSorter.sort('Volvo', ['brand']); let objectSorter: smartfuzzy.ObjectSorter<Car>;
console.log(result);
tap.test('should create an instance of ObjectSorter', async () => {
objectSorter = new smartfuzzy.ObjectSorter<Car>(testCars);
expect(objectSorter).toBeInstanceOf(smartfuzzy.ObjectSorter);
expect(objectSorter.objectDictionary).toEqual(testCars);
// Test empty constructor
const emptyObjectSorter = new smartfuzzy.ObjectSorter<Car>();
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<Car>([
...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();

View File

@ -2,25 +2,66 @@ import { expect, tap } from '@push.rocks/tapbundle';
import * as smartfuzzy from '../ts/index.js'; import * as smartfuzzy from '../ts/index.js';
let testSmartfuzzy: smartfuzzy.Smartfuzzy; let testSmartfuzzy: smartfuzzy.Smartfuzzy;
const testDictionary = [
'Sony',
'Deutsche Bahn',
'Apple Inc.',
"Trader Joe's",
];
tap.test('should create an instance of Smartfuzzy', async () => { tap.test('should create an instance of Smartfuzzy', async () => {
testSmartfuzzy = new smartfuzzy.Smartfuzzy([ testSmartfuzzy = new smartfuzzy.Smartfuzzy(testDictionary);
'Sony',
'Deutsche Bahn',
'Apple Inc.',
"Trader Joe's",
]);
expect(testSmartfuzzy).toBeInstanceOf(smartfuzzy.Smartfuzzy); 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'); 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'); 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();

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartfuzzy', 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.' description: 'A library for fuzzy matching strings against word dictionaries or arrays, with support for object and article searching.'
} }