From 996b8ac4ab0b19d87fedef11f93769f391824e48 Mon Sep 17 00:00:00 2001
From: antoine lanoe <antoine.lanoe@linkfluence.com>
Date: Fri, 23 Dec 2022 16:44:50 +0100
Subject: [PATCH] feat: start list test

---
 jest.config.js         |   5 ++
 package.json           |   3 +
 src/index.ts           |   2 +
 src/list-diff.ts       |  19 ++++--
 test/list-diff.test.ts | 127 ++++++++++++++++++++++++++++++++++++++++-
 tsconfig.json          |  20 +++++++
 6 files changed, 168 insertions(+), 8 deletions(-)
 create mode 100644 tsconfig.json

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"]
+}