From 14a52e350cfb7e309a39810b0db43e8e3aee360e Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 18:25:11 +0600 Subject: [PATCH 01/29] fix: - redraw task results if child added or removed --- src/Task/Task.ts | 4 ++++ tests/Task/Task.test.ts | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/Task/Task.ts b/src/Task/Task.ts index 1533efa304..fb3c3de433 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -875,6 +875,10 @@ export class Task extends ListItem { return false; } + if (this.children.length !== other.children.length) { + return false; + } + return this.file.rawFrontmatterIdenticalTo(other.file); } diff --git a/tests/Task/Task.test.ts b/tests/Task/Task.test.ts index d52ff88700..f296e59cb1 100644 --- a/tests/Task/Task.test.ts +++ b/tests/Task/Task.test.ts @@ -5,6 +5,7 @@ import moment from 'moment'; import { verifyAll } from 'approvals/lib/Providers/Jest/JestApprovals'; import { TasksFile } from '../../src/Scripting/TasksFile'; import { Status } from '../../src/Statuses/Status'; +import { ListItem } from '../../src/Task/ListItem'; import { Task } from '../../src/Task/Task'; import { resetSettings, updateSettings } from '../../src/Config/Settings'; import { GlobalFilter } from '../../src/Config/GlobalFilter'; @@ -1730,6 +1731,14 @@ describe('identicalTo', () => { expect(task2.status.identicalTo(task1.status)).toEqual(true); expect(task2.identicalTo(task1)).toEqual(true); }); + + it('should recognise different numbers of child items', () => { + const task1 = new TaskBuilder().build(); + const task2 = new TaskBuilder().build(); + new ListItem('- child of task2', task2); + + expect(task2.identicalTo(task1)).toEqual(false); + }); }); describe('checking if task lists are identical', () => { From 610869bc582cee3dbeb97bb7dce504cc5f54c248 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 18:32:18 +0600 Subject: [PATCH 02/29] test: - add failing test --- tests/Task/Task.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/Task/Task.test.ts b/tests/Task/Task.test.ts index f296e59cb1..2c063a4224 100644 --- a/tests/Task/Task.test.ts +++ b/tests/Task/Task.test.ts @@ -1739,6 +1739,19 @@ describe('identicalTo', () => { expect(task2.identicalTo(task1)).toEqual(false); }); + + it.failing('should recognise different description in child list items', () => { + const task1 = new TaskBuilder().build(); + const task2 = new TaskBuilder().build(); + new ListItem('- child of task1', task1); + new ListItem('- child of task2', task2); + + expect(task2.identicalTo(task1)).toEqual(false); + expect(1).toEqual(2); + }); + + // 2 list items differ both have children but... + // ...one has a child and one doesn't }); describe('checking if task lists are identical', () => { From 226becddd709c72b91836f6dc388903e7db03e5e Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 18:35:28 +0600 Subject: [PATCH 03/29] refactor: - add identicalTo() method to ListItem --- src/Task/ListItem.ts | 4 ++++ tests/Task/ListItem.test.ts | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index b97584cd54..33b3070493 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -48,4 +48,8 @@ export class ListItem { get isRoot(): boolean { return this.parent === null; } + + identicalTo(_other: ListItem) { + return true; + } } diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 7bd45ab3c0..0ccfc11a06 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -96,3 +96,11 @@ describe('list item tests', () => { } }); }); + +describe('identicalTo', () => { + it('should test the description', () => { + const listItem1 = new ListItem('same description', null); + const listItem2 = new ListItem('same description', null); + expect(listItem1.identicalTo(listItem2)).toEqual(true); + }); +}); From a475d7d3b88357657634f23be75d8d660080bfe8 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 18:39:10 +0600 Subject: [PATCH 04/29] refactor: - teach to detect different markdown --- src/Task/ListItem.ts | 4 ++-- tests/Task/ListItem.test.ts | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 33b3070493..d7ba167405 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -49,7 +49,7 @@ export class ListItem { return this.parent === null; } - identicalTo(_other: ListItem) { - return true; + identicalTo(other: ListItem) { + return this.originalMarkdown === other.originalMarkdown; } } diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 0ccfc11a06..5319799917 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -98,9 +98,15 @@ describe('list item tests', () => { }); describe('identicalTo', () => { - it('should test the description', () => { - const listItem1 = new ListItem('same description', null); - const listItem2 = new ListItem('same description', null); + it('should test same markdown', () => { + const listItem1 = new ListItem('- same description', null); + const listItem2 = new ListItem('- same description', null); expect(listItem1.identicalTo(listItem2)).toEqual(true); }); + + it('should test different markdown', () => { + const listItem1 = new ListItem('- description', null); + const listItem2 = new ListItem('- description two', null); + expect(listItem1.identicalTo(listItem2)).toEqual(false); + }); }); From 0ce016c3da09717cc6a1abfa27482ef30564bd82 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 18:43:03 +0600 Subject: [PATCH 05/29] refactor: - teach to detect different number of children --- src/Task/ListItem.ts | 4 ++++ tests/Task/ListItem.test.ts | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index d7ba167405..5be9025373 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -50,6 +50,10 @@ export class ListItem { } identicalTo(other: ListItem) { + if (this.children.length !== other.children.length) { + return false; + } + return this.originalMarkdown === other.originalMarkdown; } } diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 5319799917..a3a84a5e91 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -109,4 +109,13 @@ describe('identicalTo', () => { const listItem2 = new ListItem('- description two', null); expect(listItem1.identicalTo(listItem2)).toEqual(false); }); + + it('should recognise list items with different number of children', () => { + const item1 = new ListItem('- item', null); + new ListItem('- child of item1', item1); + + const item2 = new ListItem('- item', null); + + expect(item2.identicalTo(item1)).toEqual(false); + }); }); From 743a7f232d79438d148b5db5115bce250fcd432e Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 18:57:17 +0600 Subject: [PATCH 06/29] refactor: - implement ListItem.listItemListsIdentical() --- src/Task/ListItem.ts | 21 +++++++++++++++++++++ tests/Task/ListItem.test.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 5be9025373..1879ea61c4 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -56,4 +56,25 @@ export class ListItem { return this.originalMarkdown === other.originalMarkdown; } + + /** + * Compare two lists of ListItem objects, and report whether their + * tasks are identical in the same order. + * + * This can be useful for optimising code if it is guaranteed that + * there are no possible differences in the tasks in a file + * after an edit, for example. + * + * If any field is different in any task, it will return false. + * + * @param list1 + * @param list2 + */ + static listItemListsIdentical(list1: ListItem[], list2: ListItem[]) { + if (list1.length !== list2.length) { + return false; + } + + return list1.every((item, index) => item.identicalTo(list2[index])); + } } diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index a3a84a5e91..469c785f61 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -119,3 +119,29 @@ describe('identicalTo', () => { expect(item2.identicalTo(item1)).toEqual(false); }); }); + +describe('checking if list item lists are identical', () => { + it('should treat empty lists as identical', () => { + const list1: ListItem[] = []; + const list2: ListItem[] = []; + expect(ListItem.listItemListsIdentical(list1, list2)).toBe(true); + }); + + it('should treat different sized lists as different', () => { + const list1: ListItem[] = []; + const list2: ListItem[] = [new ListItem('- x', null)]; + expect(ListItem.listItemListsIdentical(list1, list2)).toBe(false); + }); + + it('should detect matching tasks as same', () => { + const list1: ListItem[] = [new ListItem('- 1', null)]; + const list2: ListItem[] = [new ListItem('- 1', null)]; + expect(ListItem.listItemListsIdentical(list1, list2)).toBe(true); + }); + + it('- should detect non-matching tasks as different', () => { + const list1: ListItem[] = [new ListItem('- 1', null)]; + const list2: ListItem[] = [new ListItem('- 2', null)]; + expect(ListItem.listItemListsIdentical(list1, list2)).toBe(false); + }); +}); From 6b73d749a60524c94814fdb8cefd10979cad93ce Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:00:28 +0600 Subject: [PATCH 07/29] refactor: - teach ListItem to compare children --- src/Task/ListItem.ts | 4 ++++ tests/Task/ListItem.test.ts | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 1879ea61c4..5675d4718a 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -54,6 +54,10 @@ export class ListItem { return false; } + if (!ListItem.listItemListsIdentical(this.children, other.children)) { + return false; + } + return this.originalMarkdown === other.originalMarkdown; } diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 469c785f61..7cd3cc252a 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -118,6 +118,16 @@ describe('identicalTo', () => { expect(item2.identicalTo(item1)).toEqual(false); }); + + it('should recognise list items with different children', () => { + const item1 = new ListItem('- item', null); + new ListItem('- child of item1', item1); + + const item2 = new ListItem('- item', null); + new ListItem('- child of item2', item2); + + expect(item2.identicalTo(item1)).toEqual(false); + }); }); describe('checking if list item lists are identical', () => { From 496467810c8f7989646d9824911182675cfa23c0 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:06:27 +0600 Subject: [PATCH 08/29] test: - fix test descriptions --- tests/Task/ListItem.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 7cd3cc252a..00a0bb3cdc 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -143,13 +143,13 @@ describe('checking if list item lists are identical', () => { expect(ListItem.listItemListsIdentical(list1, list2)).toBe(false); }); - it('should detect matching tasks as same', () => { + it('should detect matching list items as same', () => { const list1: ListItem[] = [new ListItem('- 1', null)]; const list2: ListItem[] = [new ListItem('- 1', null)]; expect(ListItem.listItemListsIdentical(list1, list2)).toBe(true); }); - it('- should detect non-matching tasks as different', () => { + it('- should detect non-matching list items as different', () => { const list1: ListItem[] = [new ListItem('- 1', null)]; const list2: ListItem[] = [new ListItem('- 2', null)]; expect(ListItem.listItemListsIdentical(list1, list2)).toBe(false); From 56b91eff756234243aef0381d14bf1327d1953ce Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:14:17 +0600 Subject: [PATCH 09/29] refactor: - teach ListItem to recognise Task object as different --- src/Task/ListItem.ts | 4 ++++ tests/Task/ListItem.test.ts | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 5675d4718a..7d7fbd6d75 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -50,6 +50,10 @@ export class ListItem { } identicalTo(other: ListItem) { + if (this.constructor.name !== other.constructor.name) { + return false; + } + if (this.children.length !== other.children.length) { return false; } diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 00a0bb3cdc..85e6e86d96 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -6,6 +6,7 @@ import { TasksFile } from '../../src/Scripting/TasksFile'; import { Task } from '../../src/Task/Task'; import { TaskLocation } from '../../src/Task/TaskLocation'; import { ListItem } from '../../src/Task/ListItem'; +import { fromLine } from '../TestingTools/TestHelpers'; window.moment = moment; @@ -128,6 +129,13 @@ describe('identicalTo', () => { expect(item2.identicalTo(item1)).toEqual(false); }); + + it('should recognise ListItem and Task as different', () => { + const listItem = new ListItem('- [ ] description', null); + const task = fromLine({ line: '- [ ] description' }); + + expect(listItem.identicalTo(task)).toEqual(false); + }); }); describe('checking if list item lists are identical', () => { From 42c3a8936131ca095c86803ee940a0e90ba441d2 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:23:40 +0600 Subject: [PATCH 10/29] fix: - redraw task results when child list items change --- src/Task/Task.ts | 4 ++++ tests/Task/Task.test.ts | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Task/Task.ts b/src/Task/Task.ts index fb3c3de433..da76beeb6c 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -816,6 +816,10 @@ export class Task extends ListItem { * @param other */ public identicalTo(other: Task) { + if (!super.identicalTo(other)) { + return false; + } + // NEW_TASK_FIELD_EDIT_REQUIRED // Based on ideas from koala. AquaCat and javalent in Discord: diff --git a/tests/Task/Task.test.ts b/tests/Task/Task.test.ts index 2c063a4224..188a63d8e1 100644 --- a/tests/Task/Task.test.ts +++ b/tests/Task/Task.test.ts @@ -1740,14 +1740,13 @@ describe('identicalTo', () => { expect(task2.identicalTo(task1)).toEqual(false); }); - it.failing('should recognise different description in child list items', () => { + it('should recognise different description in child list items', () => { const task1 = new TaskBuilder().build(); const task2 = new TaskBuilder().build(); new ListItem('- child of task1', task1); new ListItem('- child of task2', task2); expect(task2.identicalTo(task1)).toEqual(false); - expect(1).toEqual(2); }); // 2 list items differ both have children but... From ab6b0a016acd7ab6877477e536900087c22a808e Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:33:31 +0600 Subject: [PATCH 11/29] refactor: - reimplement Task.tasksListsIdentical() with ListItem equivalent --- src/Task/Task.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Task/Task.ts b/src/Task/Task.ts index da76beeb6c..b63c87611c 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -798,10 +798,7 @@ export class Task extends ListItem { * @param newTasks */ static tasksListsIdentical(oldTasks: Task[], newTasks: Task[]): boolean { - if (oldTasks.length !== newTasks.length) { - return false; - } - return oldTasks.every((oldTask, index) => oldTask.identicalTo(newTasks[index])); + return ListItem.listItemListsIdentical(oldTasks, newTasks); } /** From ee0b5d5e6341c88e14a71fef42d260782eb82892 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:34:45 +0600 Subject: [PATCH 12/29] refactor: . rename method to listsAreIdentical() --- src/Task/ListItem.ts | 4 ++-- src/Task/Task.ts | 2 +- tests/Task/ListItem.test.ts | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 7d7fbd6d75..5280e20788 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -58,7 +58,7 @@ export class ListItem { return false; } - if (!ListItem.listItemListsIdentical(this.children, other.children)) { + if (!ListItem.listsAreIdentical(this.children, other.children)) { return false; } @@ -78,7 +78,7 @@ export class ListItem { * @param list1 * @param list2 */ - static listItemListsIdentical(list1: ListItem[], list2: ListItem[]) { + static listsAreIdentical(list1: ListItem[], list2: ListItem[]) { if (list1.length !== list2.length) { return false; } diff --git a/src/Task/Task.ts b/src/Task/Task.ts index b63c87611c..2d1e842ed3 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -798,7 +798,7 @@ export class Task extends ListItem { * @param newTasks */ static tasksListsIdentical(oldTasks: Task[], newTasks: Task[]): boolean { - return ListItem.listItemListsIdentical(oldTasks, newTasks); + return ListItem.listsAreIdentical(oldTasks, newTasks); } /** diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 85e6e86d96..c43eac4f36 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -142,24 +142,24 @@ describe('checking if list item lists are identical', () => { it('should treat empty lists as identical', () => { const list1: ListItem[] = []; const list2: ListItem[] = []; - expect(ListItem.listItemListsIdentical(list1, list2)).toBe(true); + expect(ListItem.listsAreIdentical(list1, list2)).toBe(true); }); it('should treat different sized lists as different', () => { const list1: ListItem[] = []; const list2: ListItem[] = [new ListItem('- x', null)]; - expect(ListItem.listItemListsIdentical(list1, list2)).toBe(false); + expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); }); it('should detect matching list items as same', () => { const list1: ListItem[] = [new ListItem('- 1', null)]; const list2: ListItem[] = [new ListItem('- 1', null)]; - expect(ListItem.listItemListsIdentical(list1, list2)).toBe(true); + expect(ListItem.listsAreIdentical(list1, list2)).toBe(true); }); it('- should detect non-matching list items as different', () => { const list1: ListItem[] = [new ListItem('- 1', null)]; const list2: ListItem[] = [new ListItem('- 2', null)]; - expect(ListItem.listItemListsIdentical(list1, list2)).toBe(false); + expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); }); }); From 042eeac2e7b608ca8dca9422eca123e10d02ff9c Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:36:40 +0600 Subject: [PATCH 13/29] refactor: . inline tasksListsIdentical() --- src/Obsidian/Cache.ts | 2 +- src/Task/Task.ts | 17 ----------------- tests/Task/Task.test.ts | 8 ++++---- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/Obsidian/Cache.ts b/src/Obsidian/Cache.ts index 02a4fb8b56..3f3387dd6d 100644 --- a/src/Obsidian/Cache.ts +++ b/src/Obsidian/Cache.ts @@ -377,7 +377,7 @@ export class Cache { // If there are no changes in any of the tasks, there's // nothing to do, so just return. - if (Task.tasksListsIdentical(oldTasks, newTasks)) { + if (ListItem.listsAreIdentical(oldTasks, newTasks)) { // This code kept for now, to allow for debugging during development. // It is too verbose to release to users. // if (this.getState() == State.Warm) { diff --git a/src/Task/Task.ts b/src/Task/Task.ts index 2d1e842ed3..a4194e4a1b 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -784,23 +784,6 @@ export class Task extends ListItem { return linkText; } - /** - * Compare two lists of Task objects, and report whether their - * tasks are identical in the same order. - * - * This can be useful for optimising code if it is guaranteed that - * there are no possible differences in the tasks in a file - * after an edit, for example. - * - * If any field is different in any task, it will return false. - * - * @param oldTasks - * @param newTasks - */ - static tasksListsIdentical(oldTasks: Task[], newTasks: Task[]): boolean { - return ListItem.listsAreIdentical(oldTasks, newTasks); - } - /** * Compare all the fields in another Task, to detect any differences from this one. * diff --git a/tests/Task/Task.test.ts b/tests/Task/Task.test.ts index 188a63d8e1..4652f3443f 100644 --- a/tests/Task/Task.test.ts +++ b/tests/Task/Task.test.ts @@ -1757,24 +1757,24 @@ describe('checking if task lists are identical', () => { it('should treat empty lists as identical', () => { const list1: Task[] = []; const list2: Task[] = []; - expect(Task.tasksListsIdentical(list1, list2)).toBe(true); + expect(ListItem.listsAreIdentical(list1, list2)).toBe(true); }); it('should treat different sized lists as different', () => { const list1: Task[] = []; const list2: Task[] = [new TaskBuilder().build()]; - expect(Task.tasksListsIdentical(list1, list2)).toBe(false); + expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); }); it('should detect matching tasks as same', () => { const list1: Task[] = [new TaskBuilder().description('1').build()]; const list2: Task[] = [new TaskBuilder().description('1').build()]; - expect(Task.tasksListsIdentical(list1, list2)).toBe(true); + expect(ListItem.listsAreIdentical(list1, list2)).toBe(true); }); it('should detect non-matching tasks as different', () => { const list1: Task[] = [new TaskBuilder().description('1').build()]; const list2: Task[] = [new TaskBuilder().description('2').build()]; - expect(Task.tasksListsIdentical(list1, list2)).toBe(false); + expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); }); }); From dec42c6a42ea211f8918541d424cb1f1bbbc8352 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:37:45 +0600 Subject: [PATCH 14/29] test: - move describe with ListItem tests to ListItem.test.ts --- tests/Task/ListItem.test.ts | 27 +++++++++++++++++++++++++++ tests/Task/Task.test.ts | 26 -------------------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index c43eac4f36..8ba01c1810 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -6,6 +6,7 @@ import { TasksFile } from '../../src/Scripting/TasksFile'; import { Task } from '../../src/Task/Task'; import { TaskLocation } from '../../src/Task/TaskLocation'; import { ListItem } from '../../src/Task/ListItem'; +import { TaskBuilder } from '../TestingTools/TaskBuilder'; import { fromLine } from '../TestingTools/TestHelpers'; window.moment = moment; @@ -163,3 +164,29 @@ describe('checking if list item lists are identical', () => { expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); }); }); + +describe('checking if task lists are identical', () => { + it('should treat empty lists as identical', () => { + const list1: Task[] = []; + const list2: Task[] = []; + expect(ListItem.listsAreIdentical(list1, list2)).toBe(true); + }); + + it('should treat different sized lists as different', () => { + const list1: Task[] = []; + const list2: Task[] = [new TaskBuilder().build()]; + expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); + }); + + it('should detect matching tasks as same', () => { + const list1: Task[] = [new TaskBuilder().description('1').build()]; + const list2: Task[] = [new TaskBuilder().description('1').build()]; + expect(ListItem.listsAreIdentical(list1, list2)).toBe(true); + }); + + it('should detect non-matching tasks as different', () => { + const list1: Task[] = [new TaskBuilder().description('1').build()]; + const list2: Task[] = [new TaskBuilder().description('2').build()]; + expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); + }); +}); diff --git a/tests/Task/Task.test.ts b/tests/Task/Task.test.ts index 4652f3443f..4b7d40bcea 100644 --- a/tests/Task/Task.test.ts +++ b/tests/Task/Task.test.ts @@ -1752,29 +1752,3 @@ describe('identicalTo', () => { // 2 list items differ both have children but... // ...one has a child and one doesn't }); - -describe('checking if task lists are identical', () => { - it('should treat empty lists as identical', () => { - const list1: Task[] = []; - const list2: Task[] = []; - expect(ListItem.listsAreIdentical(list1, list2)).toBe(true); - }); - - it('should treat different sized lists as different', () => { - const list1: Task[] = []; - const list2: Task[] = [new TaskBuilder().build()]; - expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); - }); - - it('should detect matching tasks as same', () => { - const list1: Task[] = [new TaskBuilder().description('1').build()]; - const list2: Task[] = [new TaskBuilder().description('1').build()]; - expect(ListItem.listsAreIdentical(list1, list2)).toBe(true); - }); - - it('should detect non-matching tasks as different', () => { - const list1: Task[] = [new TaskBuilder().description('1').build()]; - const list2: Task[] = [new TaskBuilder().description('2').build()]; - expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); - }); -}); From 02a03c0e579c61a94cf357048c01deb0bab87ad7 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Fri, 18 Oct 2024 19:41:45 +0600 Subject: [PATCH 15/29] test: - test mixed lists --- tests/Task/ListItem.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 8ba01c1810..9b08fff325 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -190,3 +190,15 @@ describe('checking if task lists are identical', () => { expect(ListItem.listsAreIdentical(list1, list2)).toBe(false); }); }); + +describe('checking if mixed lists are identical', () => { + it('should recognise mixed lists as unequal', () => { + const list1 = [new ListItem('- [ ] description', null)]; + const list2 = [fromLine({ line: '- [ ] description' })]; + + expect(ListItem.listsAreIdentical(list1, list1)).toEqual(true); + expect(ListItem.listsAreIdentical(list1, list2)).toEqual(false); + expect(ListItem.listsAreIdentical(list2, list1)).toEqual(false); + expect(ListItem.listsAreIdentical(list2, list2)).toEqual(true); + }); +}); From 0a14e043ca6f2d138ac8ac3da1cdba6bf5281bc5 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 15:23:52 +0100 Subject: [PATCH 16/29] refactor: - Remove duplicate code. ListItem.listsAreIdentical() checks child count --- src/Task/ListItem.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 5280e20788..86a3b99481 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -54,10 +54,6 @@ export class ListItem { return false; } - if (this.children.length !== other.children.length) { - return false; - } - if (!ListItem.listsAreIdentical(this.children, other.children)) { return false; } From 42ba1b2f1dd7eebba8dcc35b54780cf92f8d9cc2 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 15:26:55 +0100 Subject: [PATCH 17/29] refactor: - Remove duplicate code. super.identicalTo(other) checks child count --- src/Task/Task.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Task/Task.ts b/src/Task/Task.ts index a4194e4a1b..f839dbab4d 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -859,10 +859,6 @@ export class Task extends ListItem { return false; } - if (this.children.length !== other.children.length) { - return false; - } - return this.file.rawFrontmatterIdenticalTo(other.file); } From d5c78632a9301f4c80a1831c1599199865b3477d Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 15:34:02 +0100 Subject: [PATCH 18/29] test: . Remove comments that are no longer needed --- tests/Task/Task.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/Task/Task.test.ts b/tests/Task/Task.test.ts index 4b7d40bcea..eeb830a294 100644 --- a/tests/Task/Task.test.ts +++ b/tests/Task/Task.test.ts @@ -1748,7 +1748,4 @@ describe('identicalTo', () => { expect(task2.identicalTo(task1)).toEqual(false); }); - - // 2 list items differ both have children but... - // ...one has a child and one doesn't }); From c14f06030a9aaa5f8cbec394cc9e24a915f86697 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 15:36:32 +0100 Subject: [PATCH 19/29] refactor: - Convert return statement to if condition --- src/Task/ListItem.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 86a3b99481..b47775798e 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -58,7 +58,11 @@ export class ListItem { return false; } - return this.originalMarkdown === other.originalMarkdown; + if (this.originalMarkdown !== other.originalMarkdown) { + return false; + } + + return true; } /** From 92684acd8bb7368bd2b0e5082145ea4ca2d11efa Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 15:38:13 +0100 Subject: [PATCH 20/29] refactor: . Slide fastest/simplest check up --- src/Task/ListItem.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index b47775798e..5529773f42 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -54,11 +54,11 @@ export class ListItem { return false; } - if (!ListItem.listsAreIdentical(this.children, other.children)) { + if (this.originalMarkdown !== other.originalMarkdown) { return false; } - if (this.originalMarkdown !== other.originalMarkdown) { + if (!ListItem.listsAreIdentical(this.children, other.children)) { return false; } From 33c1d05b76a4f5d19381ddf259b40a979c38c88b Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 15:43:29 +0100 Subject: [PATCH 21/29] refactor: . Specify return type of ListItem.listsAreIdentical() This is required for the next step of simplifying ListItem.identicalTo() to compile. --- src/Task/ListItem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 5529773f42..f32b0a3bed 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -78,7 +78,7 @@ export class ListItem { * @param list1 * @param list2 */ - static listsAreIdentical(list1: ListItem[], list2: ListItem[]) { + static listsAreIdentical(list1: ListItem[], list2: ListItem[]): boolean { if (list1.length !== list2.length) { return false; } From 5562fd9a290ffbbfa64be1e831702375bf26ee92 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 15:45:07 +0100 Subject: [PATCH 22/29] refactor: . Simplify expression in ListItem.identicalTo() --- src/Task/ListItem.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index f32b0a3bed..a2110378c6 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -58,11 +58,7 @@ export class ListItem { return false; } - if (!ListItem.listsAreIdentical(this.children, other.children)) { - return false; - } - - return true; + return ListItem.listsAreIdentical(this.children, other.children); } /** From 961cdd7d1982e3392b0644f86d8bc076f1c7cc04 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 15:47:40 +0100 Subject: [PATCH 23/29] jsdoc: Clarify ListItem.listsAreIdentical() docs --- src/Task/ListItem.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index a2110378c6..8563187a22 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -63,13 +63,13 @@ export class ListItem { /** * Compare two lists of ListItem objects, and report whether their - * tasks are identical in the same order. + * contents, including any children, are identical and in the same order. * * This can be useful for optimising code if it is guaranteed that * there are no possible differences in the tasks in a file * after an edit, for example. * - * If any field is different in any task, it will return false. + * If any field is different in any task or list item, it will return false. * * @param list1 * @param list2 From 3ba2da1357baeb963034718a69a2db6c110e5217 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 16:01:44 +0100 Subject: [PATCH 24/29] test: . Extract createChildListItem() helper. To silence SonarCloud typescript:S1848 --- tests/Task/ListItem.test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 9b08fff325..5e98257af1 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -99,6 +99,12 @@ describe('list item tests', () => { }); }); +function createChildListItem(originalMarkdown: string, item1: ListItem) { + // This exists purely to silence WebStorm about typescript:S1848 + // See https://sonarcloud.io/organizations/obsidian-tasks-group/rules?open=typescript%3AS1848&rule_key=typescript%3AS1848 + new ListItem(originalMarkdown, item1); +} + describe('identicalTo', () => { it('should test same markdown', () => { const listItem1 = new ListItem('- same description', null); @@ -123,7 +129,7 @@ describe('identicalTo', () => { it('should recognise list items with different children', () => { const item1 = new ListItem('- item', null); - new ListItem('- child of item1', item1); + createChildListItem('- child of item1', item1); const item2 = new ListItem('- item', null); new ListItem('- child of item2', item2); From 1637e2f40d7fd918d604ab36ae340bffa1629b33 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 16:17:20 +0100 Subject: [PATCH 25/29] test: . Move createChildListItem() to separate file, for re-use --- tests/Task/ListItem.test.ts | 7 +------ tests/Task/ListItemHelpers.ts | 7 +++++++ 2 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 tests/Task/ListItemHelpers.ts diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 5e98257af1..9f4fbee1b2 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -8,6 +8,7 @@ import { TaskLocation } from '../../src/Task/TaskLocation'; import { ListItem } from '../../src/Task/ListItem'; import { TaskBuilder } from '../TestingTools/TaskBuilder'; import { fromLine } from '../TestingTools/TestHelpers'; +import { createChildListItem } from './ListItemHelpers'; window.moment = moment; @@ -99,12 +100,6 @@ describe('list item tests', () => { }); }); -function createChildListItem(originalMarkdown: string, item1: ListItem) { - // This exists purely to silence WebStorm about typescript:S1848 - // See https://sonarcloud.io/organizations/obsidian-tasks-group/rules?open=typescript%3AS1848&rule_key=typescript%3AS1848 - new ListItem(originalMarkdown, item1); -} - describe('identicalTo', () => { it('should test same markdown', () => { const listItem1 = new ListItem('- same description', null); diff --git a/tests/Task/ListItemHelpers.ts b/tests/Task/ListItemHelpers.ts new file mode 100644 index 0000000000..160bbfc108 --- /dev/null +++ b/tests/Task/ListItemHelpers.ts @@ -0,0 +1,7 @@ +import { ListItem } from '../../src/Task/ListItem'; + +export function createChildListItem(originalMarkdown: string, item1: ListItem) { + // This exists purely to silence WebStorm about typescript:S1848 + // See https://sonarcloud.io/organizations/obsidian-tasks-group/rules?open=typescript%3AS1848&rule_key=typescript%3AS1848 + new ListItem(originalMarkdown, item1); +} From aeab23c6ec3eb7f1f13ac83828c0c3e62a3b7d18 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 16:22:35 +0100 Subject: [PATCH 26/29] test: - Reuse createChildListItem() to silence SonarCloud warning: typescript:S1848 --- tests/Task/ListItem.test.ts | 4 ++-- tests/Task/Task.test.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Task/ListItem.test.ts b/tests/Task/ListItem.test.ts index 9f4fbee1b2..b813e7e6e1 100644 --- a/tests/Task/ListItem.test.ts +++ b/tests/Task/ListItem.test.ts @@ -115,7 +115,7 @@ describe('identicalTo', () => { it('should recognise list items with different number of children', () => { const item1 = new ListItem('- item', null); - new ListItem('- child of item1', item1); + createChildListItem('- child of item1', item1); const item2 = new ListItem('- item', null); @@ -127,7 +127,7 @@ describe('identicalTo', () => { createChildListItem('- child of item1', item1); const item2 = new ListItem('- item', null); - new ListItem('- child of item2', item2); + createChildListItem('- child of item2', item2); expect(item2.identicalTo(item1)).toEqual(false); }); diff --git a/tests/Task/Task.test.ts b/tests/Task/Task.test.ts index eeb830a294..5e7c87f877 100644 --- a/tests/Task/Task.test.ts +++ b/tests/Task/Task.test.ts @@ -5,7 +5,6 @@ import moment from 'moment'; import { verifyAll } from 'approvals/lib/Providers/Jest/JestApprovals'; import { TasksFile } from '../../src/Scripting/TasksFile'; import { Status } from '../../src/Statuses/Status'; -import { ListItem } from '../../src/Task/ListItem'; import { Task } from '../../src/Task/Task'; import { resetSettings, updateSettings } from '../../src/Config/Settings'; import { GlobalFilter } from '../../src/Config/GlobalFilter'; @@ -23,6 +22,7 @@ import type { TasksDate } from '../../src/DateTime/TasksDate'; import { example_kanban } from '../Obsidian/__test_data__/example_kanban'; import { jason_properties } from '../Obsidian/__test_data__/jason_properties'; import { OnCompletion } from '../../src/Task/OnCompletion'; +import { createChildListItem } from './ListItemHelpers'; window.moment = moment; @@ -1735,7 +1735,7 @@ describe('identicalTo', () => { it('should recognise different numbers of child items', () => { const task1 = new TaskBuilder().build(); const task2 = new TaskBuilder().build(); - new ListItem('- child of task2', task2); + createChildListItem('- child of task2', task2); expect(task2.identicalTo(task1)).toEqual(false); }); @@ -1743,8 +1743,8 @@ describe('identicalTo', () => { it('should recognise different description in child list items', () => { const task1 = new TaskBuilder().build(); const task2 = new TaskBuilder().build(); - new ListItem('- child of task1', task1); - new ListItem('- child of task2', task2); + createChildListItem('- child of task1', task1); + createChildListItem('- child of task2', task2); expect(task2.identicalTo(task1)).toEqual(false); }); From aeed58cdb46cc4fc9045dbc3b34587fa13081c70 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 16:31:52 +0100 Subject: [PATCH 27/29] test: . Improve parameter name --- tests/Task/ListItemHelpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Task/ListItemHelpers.ts b/tests/Task/ListItemHelpers.ts index 160bbfc108..a5aa27ce80 100644 --- a/tests/Task/ListItemHelpers.ts +++ b/tests/Task/ListItemHelpers.ts @@ -1,7 +1,7 @@ import { ListItem } from '../../src/Task/ListItem'; -export function createChildListItem(originalMarkdown: string, item1: ListItem) { +export function createChildListItem(originalMarkdown: string, parent: ListItem) { // This exists purely to silence WebStorm about typescript:S1848 // See https://sonarcloud.io/organizations/obsidian-tasks-group/rules?open=typescript%3AS1848&rule_key=typescript%3AS1848 - new ListItem(originalMarkdown, item1); + new ListItem(originalMarkdown, parent); } From 3d51640f12acd23f29bd332ef6f5e58b95ba29e3 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 16:53:11 +0100 Subject: [PATCH 28/29] jsdoc: Document ListItem.identicalTo() --- src/Task/ListItem.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Task/ListItem.ts b/src/Task/ListItem.ts index 8563187a22..df0029fdc0 100644 --- a/src/Task/ListItem.ts +++ b/src/Task/ListItem.ts @@ -49,6 +49,15 @@ export class ListItem { return this.parent === null; } + /** + * Compare all the fields in another ListItem, to detect any differences from this one. + * + * If any field is different in any way, it will return false. + * + * @note Use {@link Task.identicalTo} to compare {@link Task} objects. + * + * @param other - if this is in fact a {@link Task}, the result of false. + */ identicalTo(other: ListItem) { if (this.constructor.name !== other.constructor.name) { return false; From 208599b084326c7bfc27074a14ae3a0635ced935 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Fri, 18 Oct 2024 16:58:54 +0100 Subject: [PATCH 29/29] comment: Explain a super.identicalTo() call --- src/Task/Task.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Task/Task.ts b/src/Task/Task.ts index f839dbab4d..3d516c90ee 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -796,6 +796,7 @@ export class Task extends ListItem { * @param other */ public identicalTo(other: Task) { + // First compare child Task and ListItem objects, and any other data in ListItem: if (!super.identicalTo(other)) { return false; }