Skip to content

Commit

Permalink
add levenstein test to help users if they use a wrong key
Browse files Browse the repository at this point in the history
  • Loading branch information
jdeniau committed Aug 29, 2024
1 parent e933672 commit e8b21fb
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
26 changes: 24 additions & 2 deletions __tests__/RestClientSdk.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@ import tokenStorage from '../__mocks__/tokenStorage';

const mapping = new Mapping('/v2');
const testMetadata = new ClassMetadata('test');
const cartMetadata = new ClassMetadata('cart');
const cartItemMetadata = new ClassMetadata('cartItem');
const orderMetadata = new ClassMetadata('order');

testMetadata.setAttributeList([new Attribute('@id', '@id', 'string', true)]);
mapping.setMapping([testMetadata]);
mapping.setMapping([
testMetadata,
cartMetadata,
cartItemMetadata,
orderMetadata,
]);

describe('Mapado Sdk tests', () => {
test('Test wrong SDK configuration', () => {
Expand Down Expand Up @@ -75,7 +84,20 @@ describe('Mapado Sdk tests', () => {
);

expect(() => sdk.getRepository('toast')).toThrowError(
'Unable to get metadata for repository toast'
'Unable to get metadata for repository "toast". Did you mean "test"?'
);

expect(() => sdk.getRepository('Cart')).toThrowError(
'Unable to get metadata for repository "Cart". Did you mean "cart"?'
);

expect(() => sdk.getRepository('cart_items')).toThrowError(
'Unable to get metadata for repository "cart_items". Did you mean "cartItem"?'
);

// word is too far from any other words
expect(() => sdk.getRepository('zargiblou')).toThrowError(
'Unable to get metadata for repository "zargiblou".'
);
});
});
9 changes: 8 additions & 1 deletion src/RestClientSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import UnitOfWork from './UnitOfWork';
import AbstractClient from './client/AbstractClient';
import JsSerializer from './serializer/JsSerializer';
import SerializerInterface from './serializer/SerializerInterface';
import { findClosestWord } from './utils/levenshtein';
import { Logger } from './utils/logging';
import { generateRepository } from './utils/repositoryGenerator';

Expand Down Expand Up @@ -80,7 +81,13 @@ class RestClientSdk<M extends SdkMetadata>
const metadata = this.mapping.getClassMetadataByKey(key);

if (!metadata) {
throw new Error(`Unable to get metadata for repository ${key}`);
const closeKey = findClosestWord(key, this.mapping.getMappingKeys(), 5);

const suggestions = closeKey ? ` Did you mean "${closeKey}"?` : '';

throw new Error(
`Unable to get metadata for repository "${key}".${suggestions}`
);
}

// eslint-disable-next-line new-cap
Expand Down
53 changes: 53 additions & 0 deletions src/utils/levenshtein.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
function levenshteinDistance(a: string, b: string): number {
const matrix: number[][] = [];

// Increment along the first column of each row
for (let i = 0; i <= b.length; i += 1) {
matrix[i] = [i];
}

// Increment each column in the first row
for (let j = 0; j <= a.length; j += 1) {
matrix[0][j] = j;
}

// Fill in the rest of the matrix
for (let i = 1; i <= b.length; i += 1) {
for (let j = 1; j <= a.length; j += 1) {
if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1, // substitution
matrix[i][j - 1] + 1, // insertion
matrix[i - 1][j] + 1 // deletion
);
}
}
}

return matrix[b.length][a.length];
}

// eslint-disable-next-line import/prefer-default-export
export function findClosestWord(
word: string,
list: string[],
maxDistance = Infinity
): string | null {
let closestWord: string | null = null;
let minDistance = Infinity;

// eslint-disable-next-line no-plusplus
for (let i = 0; i < list.length; i += 1) {
const candidate = list[i];
const distance = levenshteinDistance(word, candidate);

if (distance < minDistance && distance <= maxDistance) {
minDistance = distance;
closestWord = candidate;
}
}

return closestWord;
}

0 comments on commit e8b21fb

Please sign in to comment.