Functional Weave
Code in Python

collections.diff@1.0.0

vectors.json

5,433 bytes · view raw

[
  {
    "name": "one of each: an addition, a removal, a change and an untouched record",
    "args": [
      [{ "id": 1, "name": "Ada", "team": "core" }, { "id": 2, "name": "Grace", "team": "ops" }, { "id": 3, "name": "Linus", "team": "core" }],
      [{ "id": 1, "name": "Ada", "team": "core" }, { "id": 3, "name": "Linus", "team": "kernel" }, { "id": 4, "name": "Barbara", "team": "ops" }],
      "id"
    ],
    "expect": {
      "added": [{ "id": 4, "name": "Barbara", "team": "ops" }],
      "removed": [{ "id": 2, "name": "Grace", "team": "ops" }],
      "changed": [{ "key": "3", "before": { "id": 3, "name": "Linus", "team": "core" }, "after": { "id": 3, "name": "Linus", "team": "kernel" }, "fields": ["team"] }],
      "unchanged": 1
    }
  },
  {
    "name": "identical lists: nothing added, removed or changed",
    "args": [[{ "k": "a", "v": 1 }, { "k": "b", "v": 2 }], [{ "k": "a", "v": 1 }, { "k": "b", "v": 2 }], "k"],
    "expect": { "added": [], "removed": [], "changed": [], "unchanged": 2 }
  },
  {
    "name": "reordering is not a change",
    "args": [[{ "k": "a", "v": 1 }, { "k": "b", "v": 2 }], [{ "k": "b", "v": 2 }, { "k": "a", "v": 1 }], "k"],
    "expect": { "added": [], "removed": [], "changed": [], "unchanged": 2 }
  },
  {
    "name": "from nothing: everything is added, in after's order",
    "args": [[], [{ "k": "b" }, { "k": "a" }], "k"],
    "expect": { "added": [{ "k": "b" }, { "k": "a" }], "removed": [], "changed": [], "unchanged": 0 }
  },
  {
    "name": "to nothing: everything is removed, in before's order",
    "args": [[{ "k": "b" }, { "k": "a" }], [], "k"],
    "expect": { "added": [], "removed": [{ "k": "b" }, { "k": "a" }], "changed": [], "unchanged": 0 }
  },
  {
    "name": "changed fields are sorted by code point, including a field added and a field removed",
    "args": [[{ "id": "x", "b": 1, "a": 1, "old": true }], [{ "id": "x", "new": 5, "b": 2, "a": 1 }], "id"],
    "expect": { "added": [], "removed": [], "changed": [{ "key": "x", "before": { "id": "x", "b": 1, "a": 1, "old": true }, "after": { "id": "x", "new": 5, "b": 2, "a": 1 }, "fields": ["b", "new", "old"] }], "unchanged": 0 }
  },
  {
    "name": "changed records follow after's order",
    "args": [[{ "k": "a", "v": 1 }, { "k": "b", "v": 1 }], [{ "k": "b", "v": 2 }, { "k": "a", "v": 2 }], "k"],
    "expect": {
      "added": [], "removed": [],
      "changed": [
        { "key": "b", "before": { "k": "b", "v": 1 }, "after": { "k": "b", "v": 2 }, "fields": ["v"] },
        { "key": "a", "before": { "k": "a", "v": 1 }, "after": { "k": "a", "v": 2 }, "fields": ["v"] }
      ],
      "unchanged": 0
    }
  },
  {
    "name": "1 and 1.0 are the same number, so a float round trip is not a change",
    "args": [[{ "k": "a", "qty": 1 }], [{ "k": "a", "qty": 1.0 }], "k"],
    "expect": { "added": [], "removed": [], "changed": [], "unchanged": 1 }
  },
  {
    "name": "a number that became a string did change",
    "args": [[{ "k": "a", "qty": 1 }], [{ "k": "a", "qty": "1" }], "k"],
    "expect": { "added": [], "removed": [], "changed": [{ "key": "a", "before": { "k": "a", "qty": 1 }, "after": { "k": "a", "qty": "1" }, "fields": ["qty"] }], "unchanged": 0 }
  },
  {
    "name": "true is not 1",
    "args": [[{ "k": "a", "on": 1 }], [{ "k": "a", "on": true }], "k"],
    "expect": { "added": [], "removed": [], "changed": [{ "key": "a", "before": { "k": "a", "on": 1 }, "after": { "k": "a", "on": true }, "fields": ["on"] }], "unchanged": 0 }
  },
  {
    "name": "a null field and a missing field are the same, so dropping nulls is not a change",
    "args": [[{ "k": "a", "note": null, "meta": { "x": null, "y": 1 } }], [{ "k": "a", "meta": { "y": 1 } }], "k"],
    "expect": { "added": [], "removed": [], "changed": [], "unchanged": 1 }
  },
  {
    "name": "nested lists and maps are compared deeply; list order matters",
    "args": [[{ "k": "a", "tags": ["x", "y"], "addr": { "city": "Leeds" } }], [{ "k": "a", "tags": ["y", "x"], "addr": { "city": "Leeds" } }], "k"],
    "expect": { "added": [], "removed": [], "changed": [{ "key": "a", "before": { "k": "a", "tags": ["x", "y"], "addr": { "city": "Leeds" } }, "after": { "k": "a", "tags": ["y", "x"], "addr": { "city": "Leeds" } }, "fields": ["tags"] }], "unchanged": 0 }
  },
  {
    "name": "a key of 1 and a key of \"1\" match; the key field itself is reported as changed type",
    "args": [[{ "id": 1, "v": "a" }], [{ "id": "1", "v": "a" }], "id"],
    "expect": { "added": [], "removed": [], "changed": [{ "key": "1", "before": { "id": 1, "v": "a" }, "after": { "id": "1", "v": "a" }, "fields": ["id"] }], "unchanged": 0 }
  },
  {
    "name": "a duplicate key in before is an error, not a guess",
    "args": [[{ "k": "a" }, { "k": "a" }], [], "k"],
    "expectError": "duplicate key \"a\" in before"
  },
  {
    "name": "a duplicate key in after is an error",
    "args": [[], [{ "k": 7 }, { "k": 7 }], "k"],
    "expectError": "duplicate key \"7\" in after"
  },
  {
    "name": "a record with no value at the key is an error",
    "args": [[{ "k": "a" }], [{ "v": 1 }], "k"],
    "expectError": "record 0 in after has no value at \"k\""
  },
  {
    "name": "a fractional key is an error",
    "args": [[{ "k": 1.5 }], [], "k"],
    "expectError": "cannot diff by the fractional number"
  },
  {
    "name": "an empty key name is an error",
    "args": [[], [], ""],
    "expectError": "needs a non-empty key name"
  }
]