diff --git a/jest.config.js b/jest.config.js index e69de29..1da90a9 100644 --- a/jest.config.js +++ b/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + transform: { + "^.+\\.(ts|js)$": "ts-jest", + }, +}; diff --git a/package.json b/package.json index f4ee81f..2a36988 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,9 @@ "version": "1.0.0", "main": "index.js", "license": "MIT", + "scripts": { + "test": "jest" + }, "devDependencies": { "@babel/preset-env": "^7.20.2", "@types/jest": "^29.2.4", diff --git a/src/index.ts b/src/index.ts index e69de29..b14e1f0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -0,0 +1,2 @@ +export { getObjectDiff } from "./object-diff"; +export { getListDiff } from "./list-diff"; diff --git a/src/list-diff.ts b/src/list-diff.ts index d2e95cb..4de9365 100644 --- a/src/list-diff.ts +++ b/src/list-diff.ts @@ -1,13 +1,20 @@ -import { STATUS, ListDiff, ListData } from "./model"; +import { STATUS, ListDiff, ListData, DiffStatus } from "./model"; import { isEqual } from "./utils"; function formatSingleListDiff( - listData: ListData, - status: "added" | "removed" + listData: ListData[], + status: DiffStatus ): ListDiff { + console.log("formatsingle", listData); return { type: "list", - diff: listData.map((data) => ({ value: data, status })), + diff: listData.map((data: ListData, i) => ({ + value: data, + prevIndex: status === STATUS.ADDED ? null : i, + newIndex: status === STATUS.ADDED ? i : null, + indexDiff: null, + status, + })), }; } @@ -22,10 +29,10 @@ export const getListDiff = ( }; } if (!prevList) { - return formatSingleListDiff(nextList, "added"); + return formatSingleListDiff(nextList as ListData, STATUS.ADDED); } if (!nextList) { - return formatSingleListDiff(prevList, "removed"); + return formatSingleListDiff(prevList as ListData, STATUS.DELETED); } const diff: ListDiff["diff"] = []; nextList.forEach((nextValue, i) => { diff --git a/test/list-diff.test.ts b/test/list-diff.test.ts index ca69908..1712fd2 100644 --- a/test/list-diff.test.ts +++ b/test/list-diff.test.ts @@ -1,7 +1,130 @@ import { getListDiff } from "../src/list-diff"; describe("getListDiff", () => { - it("", () => { - expect(getListDiff(null, null)).toStrictEqual(null); + it("returns an empty diff if no lists are provided", () => { + expect(getListDiff(null, null)).toStrictEqual({ type: "list", diff: [] }); + }); + it("consider previous list as completely deleted if no next list is provided", () => { + const res = getListDiff(["mbappe", "mendes", "verratti", "ruiz"], null); + console.log("res", JSON.stringify(res, null, 2)); + expect( + getListDiff(["mbappe", "mendes", "verratti", "ruiz"], null) + ).toStrictEqual({ + type: "list", + diff: [ + { + value: "mbappe", + prevIndex: 0, + newIndex: null, + indexDiff: null, + status: "deleted", + }, + { + value: "mendes", + prevIndex: 1, + newIndex: null, + indexDiff: null, + status: "deleted", + }, + { + value: "verratti", + prevIndex: 2, + newIndex: null, + indexDiff: null, + status: "deleted", + }, + { + value: "ruiz", + prevIndex: 3, + newIndex: null, + indexDiff: null, + status: "deleted", + }, + ], + }); + }); + it("consider next list as completely added if no previous list is provided", () => { + expect( + getListDiff(null, ["mbappe", "mendes", "verratti", "ruiz"]) + ).toStrictEqual({ + type: "list", + diff: [ + { + value: "mbappe", + prevIndex: null, + newIndex: 0, + indexDiff: null, + status: "added", + }, + { + value: "mendes", + prevIndex: null, + newIndex: 1, + indexDiff: null, + status: "added", + }, + { + value: "verratti", + prevIndex: null, + newIndex: 2, + indexDiff: null, + status: "added", + }, + { + value: "ruiz", + prevIndex: null, + newIndex: 3, + indexDiff: null, + status: "added", + }, + ], + }); + }); + it("detects changed values in the list", () => { + expect( + getListDiff( + ["mbappe", "mendes", "verratti", "ruiz"], + ["mbappe", "messi", "ruiz"] + ) + ).toStrictEqual({ + type: "list", + diff: [ + { + value: "mbappe", + prevIndex: 0, + newIndex: 0, + indexDiff: 0, + status: "equal", + }, + { + value: "mendes", + prevIndex: 1, + newIndex: null, + indexDiff: null, + status: "deleted", + }, + { + value: "verratti", + prevIndex: 2, + newIndex: null, + indexDiff: null, + status: "deleted", + }, + { + value: "messi", + prevIndex: null, + newIndex: 1, + indexDiff: null, + status: "added", + }, + { + value: "ruiz", + prevIndex: 3, + newIndex: 2, + indexDiff: -1, + status: "moved", + }, + ], + }); }); }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2295728 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "declaration": true, + "declarationDir": "./dist", + "jsx": "react", + "lib": ["esnext", "dom"], + "module": "esnext", + "moduleResolution": "node", + "noUnusedParameters": true, + "esModuleInterop": true, + "noImplicitAny": true, + "outDir": "./dist", + "strict": true, + "target": "es5", + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true + }, + "include": ["src/**/*.tsx"], + "exclude": ["node_modules"] +}