From 99158c62773d6903fbc5dba21edbfea25aa1cf1b Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Thu, 4 Dec 2025 17:58:35 +0900 Subject: [PATCH 01/18] test: - addFrame() returns an object --- tests/Renderer/QueryResultsRenderer.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Renderer/QueryResultsRenderer.test.ts b/tests/Renderer/QueryResultsRenderer.test.ts index a760101136..aa2144b015 100644 --- a/tests/Renderer/QueryResultsRenderer.test.ts +++ b/tests/Renderer/QueryResultsRenderer.test.ts @@ -174,7 +174,7 @@ class RendererStoryboard { * Returns the prettified rendered HTML, to allow 'expect' calls to be added. * @param description */ - public async addFrame(description: string): Promise { + public async addFrame(description: string) { this.output += `

${description}:

\n\n`; const container = document.createElement('div'); @@ -183,7 +183,7 @@ class RendererStoryboard { const { tasksAsMarkdown, prettyHTML } = tasksMarkdownAndPrettifiedHtml(container, this.allTasks); this.output += tasksAsMarkdown + prettyHTML; - return prettyHTML; + return { prettyHTML }; } public verify() { @@ -203,7 +203,7 @@ describe('QueryResultsRenderer - sequences', () => { const dueDate = '📅 2025-12-01'; { - const prettyHTML = await storyboard.addFrame('Initial results'); + const { prettyHTML } = await storyboard.addFrame('Initial results'); expect(prettyHTML).toContain(dueDate); } @@ -211,7 +211,7 @@ describe('QueryResultsRenderer - sequences', () => { storyboard.renderer.rereadQueryFromFile(); { - const prettyHTML = await storyboard.addFrame('Check that due date is hidden by global query'); + const { prettyHTML } = await storyboard.addFrame('Check that due date is hidden by global query'); expect(prettyHTML).not.toContain(dueDate); } @@ -224,7 +224,7 @@ describe('QueryResultsRenderer - sequences', () => { const urgency = '10.75'; { - const prettyHTML = await storyboard.addFrame('Initial results'); + const { prettyHTML } = await storyboard.addFrame('Initial results'); expect(prettyHTML).not.toContain(urgency); } @@ -232,7 +232,7 @@ describe('QueryResultsRenderer - sequences', () => { storyboard.renderer.rereadQueryFromFile(); { - const prettyHTML = await storyboard.addFrame('Check that urgency is shown by global query'); + const { prettyHTML } = await storyboard.addFrame('Check that urgency is shown by global query'); expect(prettyHTML).toContain(urgency); } From e5611a5f8372698a406873b2264654815aa25d5a Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Thu, 4 Dec 2025 18:13:49 +0900 Subject: [PATCH 02/18] test: - add test showing filter is lost when results are redrawn --- ...ed_results_retain_the_filter.approved.html | 195 ++++++++++++++++++ tests/Renderer/QueryResultsRenderer.test.ts | 29 ++- 2 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_rerendered_results_retain_the_filter.approved.html diff --git a/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_rerendered_results_retain_the_filter.approved.html b/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_rerendered_results_retain_the_filter.approved.html new file mode 100644 index 0000000000..85e5332f42 --- /dev/null +++ b/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_rerendered_results_retain_the_filter.approved.html @@ -0,0 +1,195 @@ +

Initial results:

+ + + +
+
+ + +
+
+Explanation of this Tasks code block query:
+
+  No filters supplied. All tasks will match the query.
+
+
    +
  • + + + parent + + 📅 2025-12-01 + + + + + ( + / + ) + + + + +
  • +
  • + + + child + 🆔 childID + + + + ( + / + ) + + + +
  • +
+
2 tasks
+
+

Filtered results (parent):

+ + + +
+
+ + +
+
+Explanation of this Tasks code block query:
+
+  No filters supplied. All tasks will match the query.
+
+
    +
  • + + + parent + + 📅 2025-12-01 + + + + + ( + / + ) + + + + +
  • +
+
1 task
+
+

Filtered results after editing Global Query:

+ + + +
+
+ + +
+
+Explanation of the global query:
+
+  No filters supplied. All tasks will match the query.
+
+  sort by function reverse task.description.length
+
+Explanation of this Tasks code block query:
+
+  No filters supplied. All tasks will match the query.
+
+
    +
  • + + + parent + + 📅 2025-12-01 + + + + + ( + / + ) + + + + +
  • +
  • + + + child + 🆔 childID + + + + ( + / + ) + + + +
  • +
+
2 tasks
+
diff --git a/tests/Renderer/QueryResultsRenderer.test.ts b/tests/Renderer/QueryResultsRenderer.test.ts index aa2144b015..e5623d26d7 100644 --- a/tests/Renderer/QueryResultsRenderer.test.ts +++ b/tests/Renderer/QueryResultsRenderer.test.ts @@ -183,7 +183,16 @@ class RendererStoryboard { const { tasksAsMarkdown, prettyHTML } = tasksMarkdownAndPrettifiedHtml(container, this.allTasks); this.output += tasksAsMarkdown + prettyHTML; - return { prettyHTML }; + return { prettyHTML, container }; + } + + public async addFrameOfCurrentState(description: string, container: HTMLDivElement) { + this.output += `

${description}:

\n\n`; + + const { tasksAsMarkdown, prettyHTML } = tasksMarkdownAndPrettifiedHtml(container, this.allTasks); + this.output += tasksAsMarkdown + prettyHTML; + + return { prettyHTML, container }; } public verify() { @@ -238,4 +247,22 @@ describe('QueryResultsRenderer - sequences', () => { storyboard.verify(); }); + + it('rerendered results retain the filter', async () => { + const source = 'explain'; + const storyboard = new RendererStoryboard(source, parentAndChild); + + const { container } = await storyboard.addFrame('Initial results'); + + await storyboard.renderer.applySearchBoxFilter('parent', container); + await storyboard.addFrameOfCurrentState('Filtered results (parent)', container); + + GlobalQuery.getInstance().set('sort by function reverse task.description.length'); + storyboard.renderer.rereadQueryFromFile(); + + // The following renders two tasks, not one because the filter is lost + await storyboard.addFrame('Filtered results after editing Global Query'); + + storyboard.verify(); + }); }); From 7a405f8f054ea83297a1944bd53a1319c89ab35f Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Thu, 4 Dec 2025 18:17:02 +0900 Subject: [PATCH 03/18] test: - extract prettifyContainer() --- tests/Renderer/QueryResultsRenderer.test.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/Renderer/QueryResultsRenderer.test.ts b/tests/Renderer/QueryResultsRenderer.test.ts index e5623d26d7..cf2d82be23 100644 --- a/tests/Renderer/QueryResultsRenderer.test.ts +++ b/tests/Renderer/QueryResultsRenderer.test.ts @@ -180,15 +180,16 @@ class RendererStoryboard { const container = document.createElement('div'); await this.renderer.render(State.Warm, this.allTasks, container); - const { tasksAsMarkdown, prettyHTML } = tasksMarkdownAndPrettifiedHtml(container, this.allTasks); - this.output += tasksAsMarkdown + prettyHTML; - - return { prettyHTML, container }; + return this.prettifyContainer(container); } public async addFrameOfCurrentState(description: string, container: HTMLDivElement) { this.output += `

${description}:

\n\n`; + return this.prettifyContainer(container); + } + + private prettifyContainer(container: HTMLDivElement) { const { tasksAsMarkdown, prettyHTML } = tasksMarkdownAndPrettifiedHtml(container, this.allTasks); this.output += tasksAsMarkdown + prettyHTML; From 70bb44bd0729344d80c8d122bbae595ec214d85d Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Thu, 4 Dec 2025 18:21:28 +0900 Subject: [PATCH 04/18] test: add jsdoc --- tests/Renderer/QueryResultsRenderer.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Renderer/QueryResultsRenderer.test.ts b/tests/Renderer/QueryResultsRenderer.test.ts index cf2d82be23..3a2c2fb99c 100644 --- a/tests/Renderer/QueryResultsRenderer.test.ts +++ b/tests/Renderer/QueryResultsRenderer.test.ts @@ -171,6 +171,7 @@ class RendererStoryboard { } /** + * This simulates QueryRenderer.renderResults() * Returns the prettified rendered HTML, to allow 'expect' calls to be added. * @param description */ From 360e005c9b20286c3ef5006027d4730696b9fbbf Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Thu, 4 Dec 2025 18:24:44 +0900 Subject: [PATCH 05/18] test: - improve structure and clarity of storyboard --- tests/Renderer/QueryResultsRenderer.test.ts | 26 ++++++++------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/tests/Renderer/QueryResultsRenderer.test.ts b/tests/Renderer/QueryResultsRenderer.test.ts index 3a2c2fb99c..944e09cdb6 100644 --- a/tests/Renderer/QueryResultsRenderer.test.ts +++ b/tests/Renderer/QueryResultsRenderer.test.ts @@ -175,22 +175,16 @@ class RendererStoryboard { * Returns the prettified rendered HTML, to allow 'expect' calls to be added. * @param description */ - public async addFrame(description: string) { - this.output += `

${description}:

\n\n`; - + public async renderAndAddFrame(description: string) { const container = document.createElement('div'); await this.renderer.render(State.Warm, this.allTasks, container); - return this.prettifyContainer(container); + return this.addFrame(description, container); } - public async addFrameOfCurrentState(description: string, container: HTMLDivElement) { + public addFrame(description: string, container: HTMLDivElement) { this.output += `

${description}:

\n\n`; - return this.prettifyContainer(container); - } - - private prettifyContainer(container: HTMLDivElement) { const { tasksAsMarkdown, prettyHTML } = tasksMarkdownAndPrettifiedHtml(container, this.allTasks); this.output += tasksAsMarkdown + prettyHTML; @@ -214,7 +208,7 @@ describe('QueryResultsRenderer - sequences', () => { const dueDate = '📅 2025-12-01'; { - const { prettyHTML } = await storyboard.addFrame('Initial results'); + const { prettyHTML } = await storyboard.renderAndAddFrame('Initial results'); expect(prettyHTML).toContain(dueDate); } @@ -222,7 +216,7 @@ describe('QueryResultsRenderer - sequences', () => { storyboard.renderer.rereadQueryFromFile(); { - const { prettyHTML } = await storyboard.addFrame('Check that due date is hidden by global query'); + const { prettyHTML } = await storyboard.renderAndAddFrame('Check that due date is hidden by global query'); expect(prettyHTML).not.toContain(dueDate); } @@ -235,7 +229,7 @@ describe('QueryResultsRenderer - sequences', () => { const urgency = '10.75'; { - const { prettyHTML } = await storyboard.addFrame('Initial results'); + const { prettyHTML } = await storyboard.renderAndAddFrame('Initial results'); expect(prettyHTML).not.toContain(urgency); } @@ -243,7 +237,7 @@ describe('QueryResultsRenderer - sequences', () => { storyboard.renderer.rereadQueryFromFile(); { - const { prettyHTML } = await storyboard.addFrame('Check that urgency is shown by global query'); + const { prettyHTML } = await storyboard.renderAndAddFrame('Check that urgency is shown by global query'); expect(prettyHTML).toContain(urgency); } @@ -254,16 +248,16 @@ describe('QueryResultsRenderer - sequences', () => { const source = 'explain'; const storyboard = new RendererStoryboard(source, parentAndChild); - const { container } = await storyboard.addFrame('Initial results'); + const { container } = await storyboard.renderAndAddFrame('Initial results'); await storyboard.renderer.applySearchBoxFilter('parent', container); - await storyboard.addFrameOfCurrentState('Filtered results (parent)', container); + storyboard.addFrame('Filtered results (parent)', container); GlobalQuery.getInstance().set('sort by function reverse task.description.length'); storyboard.renderer.rereadQueryFromFile(); // The following renders two tasks, not one because the filter is lost - await storyboard.addFrame('Filtered results after editing Global Query'); + await storyboard.renderAndAddFrame('Filtered results after editing Global Query'); storyboard.verify(); }); From 1283075aa8b2cbd55af9035b1e64f054fd50de21 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Thu, 4 Dec 2025 18:28:56 +0900 Subject: [PATCH 06/18] test: - remove explain to shorten approved file --- ...ed_results_retain_the_filter.approved.html | 24 ------------------- tests/Renderer/QueryResultsRenderer.test.ts | 3 +-- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_rerendered_results_retain_the_filter.approved.html b/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_rerendered_results_retain_the_filter.approved.html index 85e5332f42..a460618989 100644 --- a/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_rerendered_results_retain_the_filter.approved.html +++ b/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_rerendered_results_retain_the_filter.approved.html @@ -12,12 +12,6 @@

Initial results:

-
-Explanation of this Tasks code block query:
-
-  No filters supplied. All tasks will match the query.
-
  • Filtered results (parent): -
    -Explanation of this Tasks code block query:
    -
    -  No filters supplied. All tasks will match the query.
    -
    • Filtered results after editing Global Query: -
      -Explanation of the global query:
      -
      -  No filters supplied. All tasks will match the query.
      -
      -  sort by function reverse task.description.length
      -
      -Explanation of this Tasks code block query:
      -
      -  No filters supplied. All tasks will match the query.
      -
      • { }); it('rerendered results retain the filter', async () => { - const source = 'explain'; - const storyboard = new RendererStoryboard(source, parentAndChild); + const storyboard = new RendererStoryboard('', parentAndChild); const { container } = await storyboard.renderAndAddFrame('Initial results'); From 298b5bad0ea2dd6f2807fc1ac39bbcdfa0e3bce6 Mon Sep 17 00:00:00 2001 From: Ilyas Landikov Date: Thu, 4 Dec 2025 18:51:30 +0900 Subject: [PATCH 07/18] refactor: - store filter string --- src/Renderer/QueryResultsRenderer.ts | 3 +++ ...es_global_query_change_to_query_layout_option.approved.html | 2 ++ ...ces_global_query_change_to_task_layout_option.approved.html | 2 ++ ...equences_rerendered_results_retain_the_filter.approved.html | 3 +++ tests/Renderer/QueryResultsRenderer.test.ts | 1 + 5 files changed, 11 insertions(+) diff --git a/src/Renderer/QueryResultsRenderer.ts b/src/Renderer/QueryResultsRenderer.ts index 5c15e1a1a0..9356625145 100644 --- a/src/Renderer/QueryResultsRenderer.ts +++ b/src/Renderer/QueryResultsRenderer.ts @@ -62,6 +62,7 @@ export class QueryResultsRenderer { protected queryType: string; // whilst there is only one query type, there is no point logging this value public queryResult: QueryResult; public filteredQueryResult: QueryResult; + public filterString: string = ''; constructor( className: string, @@ -208,6 +209,8 @@ export class QueryResultsRenderer { return; } + this.filterString = filterString; + // We want to retain the Toolbar, to not lose the search string. // But we need to delete any pre-existing headings, tasks and task count. // The following while loop relies on the Toolbar being the first element. diff --git a/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_global_query_change_to_query_layout_option.approved.html b/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_global_query_change_to_query_layout_option.approved.html index 22fd8993d3..346f3e9bf4 100644 --- a/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_global_query_change_to_query_layout_option.approved.html +++ b/tests/Renderer/QueryResultsRenderer.test.QueryResultsRenderer_-_sequences_global_query_change_to_query_layout_option.approved.html @@ -1,5 +1,6 @@

        Initial results:

        +

        Results filter: ''