Repository: obsidian-tasks-group/obsidian-tasks
Pull request #2233 (2023-08-26 20:57:45)

test: Add tests for logic in EditorSuggestor.onTrigger()
<!--- Provide a general summary of your changes in the Title above -->

# Description

I want to change the behaviour of `EditorSuggestor.onTrigger()` to stop the Auto Suggest menu popping up in inconvenient locations like in the middle of a checkbox, or the start of the line.

Before doing so, this PR adds tests for the existing logic, by separating it out to a new function `canSuggestForLine()`, which is in `Suggestor.ts` so that it can be called from test code.

## Motivation and Context

See above.

## How has this been tested?

- By adding tests
- By running the changed code in the Tasks-Demo test vault, to confirm that the behaviour is unchanged.

## Screenshots (if appropriate)

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->



- [x] **Refactor** (prefix: `refactor` - non-breaking change which only improves the design or structure of existing code, and making no changes to its external behaviour)
- [x] **Tests** (prefix: `test` - additions and improvements to unit tests and the smoke tests)

## Checklist

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [ ] My change requires a change to the documentation.
- [ ] I have [updated the documentation](https://publish.obsidian.md/tasks-contributing/Documentation/About+Documentation) accordingly.
- [x] My change has adequate [Unit Test coverage](https://publish.obsidian.md/tasks-contributing/Testing/About+Testing).

## Terms

<!--
By submitting this pull request, you must agree to follow our
[contributing guide](https://publish.obsidian.md/tasks-contributing) and
[Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md).
Put an x in the boxes to confirm you agree.
-->

- [x] My contribution follow this project's [contributing guide](https://publish.obsidian.md/tasks-contributing)
- [x] I agree to follow this project's [Code of Conduct](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CODE_OF_CONDUCT.md)



Patch:
diff --git a/src/Suggestor/EditorSuggestorPopup.ts b/src/Suggestor/EditorSuggestorPopup.ts
index 4b4797a5..914b6b1f 100644
--- a/src/Suggestor/EditorSuggestorPopup.ts
+++ b/src/Suggestor/EditorSuggestorPopup.ts
@@ -1,9 +1,7 @@
 import { App, Editor, EditorSuggest, TFile } from 'obsidian';
 import type { EditorPosition, EditorSuggestContext, EditorSuggestTriggerInfo } from 'obsidian';
-
-import { GlobalFilter } from '../Config/GlobalFilter';
 import { type Settings, getUserSelectedTaskFormat } from '../Config/Settings';
-import * as task from '../Task';
+import { canSuggestForLine } from './Suggestor';
 import type { SuggestInfo } from '.';
 
 export type SuggestInfoWithContext = SuggestInfo & {
@@ -21,7 +19,7 @@ export class EditorSuggestor extends EditorSuggest<SuggestInfoWithContext> {
     onTrigger(cursor: EditorPosition, editor: Editor, _file: TFile): EditorSuggestTriggerInfo | null {
         if (!this.settings.autoSuggestInEditor) return null;
         const line = editor.getLine(cursor.line);
-        if (GlobalFilter.includedIn(line) && line.match(task.TaskRegularExpressions.taskRegex)) {
+        if (canSuggestForLine(line)) {
             return {
                 start: { line: cursor.line, ch: 0 },
                 end: {
diff --git a/src/Suggestor/Suggestor.ts b/src/Suggestor/Suggestor.ts
index cd605fbb..8f53c6bd 100644
--- a/src/Suggestor/Suggestor.ts
+++ b/src/Suggestor/Suggestor.ts
@@ -3,7 +3,9 @@ import { DateParser } from '../Query/DateParser';
 import { doAutocomplete } from '../DateAbbreviations';
 import { Recurrence } from '../Recurrence';
 import type { DefaultTaskSerializerSymbols } from '../TaskSerializer/DefaultTaskSerializer';
+import * as task from '../Task';
 import { TaskRegularExpressions } from '../Task';
+import { GlobalFilter } from '../Config/GlobalFilter';
 import type { SuggestInfo, SuggestionBuilder } from '.';
 
 /**
@@ -400,3 +402,16 @@ export function onlySuggestIfBracketOpen(fn: SuggestionBuilder, brackets: [strin
         return fn(line, cursorPos, settings);
     };
 }
+
+/**
+ * Return true if the Auto-Suggest menu may be shown on the current line,
+ * and false value otherwise.
+ *
+ * This checks for simple pre-conditions:
+ *  - Is the global filter (if set) in the line?
+ *  - Is the line a task line (with a checkbox)
+ * @param line
+ */
+export function canSuggestForLine(line: string) {
+    return GlobalFilter.includedIn(line) && line.match(task.TaskRegularExpressions.taskRegex) !== null;
+}


Test patch:
diff --git a/tests/Suggestor/Suggestor.test.ts b/tests/Suggestor/Suggestor.test.ts
index 277090c8..a589dea3 100644
--- a/tests/Suggestor/Suggestor.test.ts
+++ b/tests/Suggestor/Suggestor.test.ts
@@ -5,10 +5,15 @@ import moment from 'moment';
 import * as chrono from 'chrono-node';
 import { getSettings } from '../../src/Config/Settings';
 import type { SuggestInfo, SuggestionBuilder } from '../../src/Suggestor';
-import { makeDefaultSuggestionBuilder, onlySuggestIfBracketOpen } from '../../src/Suggestor/Suggestor';
+import {
+    canSuggestForLine,
+    makeDefaultSuggestionBuilder,
+    onlySuggestIfBracketOpen,
+} from '../../src/Suggestor/Suggestor';
 import { DEFAULT_SYMBOLS } from '../../src/TaskSerializer/DefaultTaskSerializer';
 import { DATAVIEW_SYMBOLS } from '../../src/TaskSerializer/DataviewTaskSerializer';
 import { MarkdownTable } from '../TestingTools/VerifyMarkdownTable';
+import { GlobalFilter } from '../../src/Config/GlobalFilter';
 
 window.moment = moment;
 
@@ -222,3 +227,24 @@ describe('onlySuggestIfBracketOpen', () => {
         expect(suggestions).toEqual(emptySuggestion);
     });
 });
+
+describe('canSuggestForLine', () => {
+    afterEach(() => {
+        GlobalFilter.reset();
+    });
+
+    it('should suggest if there is no global filter', () => {
+        GlobalFilter.reset();
+        expect(canSuggestForLine('- [ ] global filter is not set')).toEqual(true);
+    });
+
+    it('should suggest if global filter missing from line', () => {
+        GlobalFilter.set('#todo');
+        expect(canSuggestForLine('- [ ] #todo has global filter')).toEqual(true);
+    });
+
+    it('should not suggest if global filter missing from line', () => {
+        GlobalFilter.set('#todo');
+        expect(canSuggestForLine('- [ ] no global filter')).toEqual(false);
+    });
+});