Repository: obsidian-tasks-group/obsidian-tasks
Pull request #2631 (2024-01-31 05:56:44)

refactor: convert `TaskLayoutOptions` to `enum`
# Description

- convert `TaskLayoutOptions` to `enum`
- remove a place to edit when adding new `Task` field (`// NEW_TASK_FIELD_EDIT_REQUIRED`)
- replace `Task` fields `string` values with references to `enum`

## Motivation and Context

- create a single container for `TaskLayoutOptions` value
- strengthen the code by having links to values instead of values
- decrease number of places to edit when adding new `Task` field (`// NEW_TASK_FIELD_EDIT_REQUIRED`)

## How has this been tested?

Unit tests.

## Types of changes

Internal changes:

- [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

- [x] My code follows the code style of this project and passes `yarn run lint`.
- [x] My change has adequate [Unit Test coverage](https://publish.obsidian.md/tasks-contributing/Testing/About+Testing).

## Terms

- [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/Layout/TaskLayoutOptions.ts b/src/Layout/TaskLayoutOptions.ts
index 5cea27ed..ec8a62af 100644
--- a/src/Layout/TaskLayoutOptions.ts
+++ b/src/Layout/TaskLayoutOptions.ts
@@ -1,34 +1,26 @@
-export type TaskLayoutComponent =
+/**
+ * {@link Task} fields used for rendering. Use references to this enum ({@link TaskLayoutComponent.Id})
+ * instead of plain string values (`id`).
+ *
+ * The order here determines the order that task fields are rendered and written to markdown.
+ */
+export enum TaskLayoutComponent {
     // NEW_TASK_FIELD_EDIT_REQUIRED
-    | 'description'
-    | 'priority'
-    | 'recurrenceRule'
-    | 'createdDate'
-    | 'startDate'
-    | 'scheduledDate'
-    | 'dueDate'
-    | 'doneDate'
-    | 'cancelledDate'
-    | 'blockedBy'
-    | 'id'
-    | 'blockLink';
+    Description = 'description',
+    Id = 'id',
+    BlockedBy = 'blockedBy',
+    Priority = 'priority',
+    RecurrenceRule = 'recurrenceRule',
+    CreatedDate = 'createdDate',
+    StartDate = 'startDate',
+    ScheduledDate = 'scheduledDate',
+    DueDate = 'dueDate',
+    CancelledDate = 'cancelledDate',
+    DoneDate = 'doneDate',
+    BlockLink = 'blockLink',
+}
 
-// The order here determines the order that task fields are rendered and written to markdown.
-export const taskLayoutComponents: TaskLayoutComponent[] = [
-    // NEW_TASK_FIELD_EDIT_REQUIRED
-    'description',
-    'id',
-    'blockedBy',
-    'priority',
-    'recurrenceRule',
-    'createdDate',
-    'startDate',
-    'scheduledDate',
-    'dueDate',
-    'cancelledDate',
-    'doneDate',
-    'blockLink',
-];
+export const taskLayoutComponents = Object.values(TaskLayoutComponent);
 
 /**
  * Various rendering options of tasks in a query.
@@ -88,7 +80,7 @@ export class TaskLayoutOptions {
     public get toggleableComponents() {
         return taskLayoutComponents.filter((component) => {
             // Description and blockLink are always shown
-            return component !== 'description' && component !== 'blockLink';
+            return component !== TaskLayoutComponent.Description && component !== TaskLayoutComponent.BlockLink;
         });
     }
 
diff --git a/src/Query/Query.ts b/src/Query/Query.ts
index f00d03b0..e7ea8587 100644
--- a/src/Query/Query.ts
+++ b/src/Query/Query.ts
@@ -1,22 +1,22 @@
-import { TaskLayoutOptions } from '../Layout/TaskLayoutOptions';
+import { getSettings } from '../Config/Settings';
+import type { IQuery } from '../IQuery';
 import { QueryLayoutOptions } from '../Layout/QueryLayoutOptions';
+import { TaskLayoutComponent, TaskLayoutOptions } from '../Layout/TaskLayoutOptions';
+import { errorMessageForException } from '../lib/ExceptionTools';
+import { logging } from '../lib/logging';
 import { expandPlaceholders } from '../Scripting/ExpandPlaceholders';
 import { makeQueryContext } from '../Scripting/QueryContext';
 import type { Task } from '../Task/Task';
-import type { IQuery } from '../IQuery';
-import { getSettings } from '../Config/Settings';
-import { errorMessageForException } from '../lib/ExceptionTools';
-import { logging } from '../lib/logging';
-import { Sort } from './Sort/Sort';
-import type { Sorter } from './Sort/Sorter';
-import { TaskGroups } from './Group/TaskGroups';
+import { Explainer } from './Explain/Explainer';
+import type { Filter } from './Filter/Filter';
 import * as FilterParser from './FilterParser';
 import type { Grouper } from './Group/Grouper';
-import type { Filter } from './Filter/Filter';
+import { TaskGroups } from './Group/TaskGroups';
 import { QueryResult } from './QueryResult';
 import { scan } from './Scanner';
 import { SearchInfo } from './SearchInfo';
-import { Explainer } from './Explain/Explainer';
+import { Sort } from './Sort/Sort';
+import type { Sorter } from './Sort/Sorter';
 
 export class Query implements IQuery {
     /** Note: source is the raw source, before expanding any placeholders */
@@ -283,28 +283,28 @@ Problem line: "${line}"`;
                     this._queryLayoutOptions.hidePostponeButton = hide;
                     break;
                 case 'priority':
-                    this._taskLayoutOptions.setVisibility('priority', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.Priority, !hide);
                     break;
                 case 'cancelled date':
-                    this._taskLayoutOptions.setVisibility('cancelledDate', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.CancelledDate, !hide);
                     break;
                 case 'created date':
-                    this._taskLayoutOptions.setVisibility('createdDate', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.CreatedDate, !hide);
                     break;
                 case 'start date':
-                    this._taskLayoutOptions.setVisibility('startDate', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.StartDate, !hide);
                     break;
                 case 'scheduled date':
-                    this._taskLayoutOptions.setVisibility('scheduledDate', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.ScheduledDate, !hide);
                     break;
                 case 'due date':
-                    this._taskLayoutOptions.setVisibility('dueDate', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.DueDate, !hide);
                     break;
                 case 'done date':
-                    this._taskLayoutOptions.setVisibility('doneDate', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.DoneDate, !hide);
                     break;
                 case 'recurrence rule':
-                    this._taskLayoutOptions.setVisibility('recurrenceRule', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.RecurrenceRule, !hide);
                     break;
                 case 'edit button':
                     this._queryLayoutOptions.hideEditButton = hide;
@@ -316,10 +316,10 @@ Problem line: "${line}"`;
                     this._taskLayoutOptions.setTagsVisibility(!hide);
                     break;
                 case 'id':
-                    this._taskLayoutOptions.setVisibility('id', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.Id, !hide);
                     break;
                 case 'depends on':
-                    this._taskLayoutOptions.setVisibility('blockedBy', !hide);
+                    this._taskLayoutOptions.setVisibility(TaskLayoutComponent.BlockedBy, !hide);
                     break;
                 default:
                     this.setError('do not understand hide/show option', line);
diff --git a/src/Renderer/TaskLineRenderer.ts b/src/Renderer/TaskLineRenderer.ts
index 48c51a15..4652f9a6 100644
--- a/src/Renderer/TaskLineRenderer.ts
+++ b/src/Renderer/TaskLineRenderer.ts
@@ -2,13 +2,13 @@ import type { Moment } from 'moment';
 import { Component, MarkdownRenderer } from 'obsidian';
 import { GlobalFilter } from '../Config/GlobalFilter';
 import { TASK_FORMATS, getSettings } from '../Config/Settings';
-import { replaceTaskWithTasks } from '../Obsidian/File';
-import type { TaskLayoutComponent, TaskLayoutOptions } from '../Layout/TaskLayoutOptions';
 import type { QueryLayoutOptions } from '../Layout/QueryLayoutOptions';
-import type { Task } from '../Task/Task';
-import { StatusMenu } from '../ui/Menus/StatusMenu';
+import { TaskLayoutComponent, type TaskLayoutOptions } from '../Layout/TaskLayoutOptions';
+import { replaceTaskWithTasks } from '../Obsidian/File';
 import { StatusRegistry } from '../Statuses/StatusRegistry';
+import type { Task } from '../Task/Task';
 import { TaskRegularExpressions } from '../Task/TaskRegularExpressions';
+import { StatusMenu } from '../ui/Menus/StatusMenu';
 import { TaskFieldRenderer } from './TaskFieldRenderer';
 
 /**
@@ -195,7 +195,7 @@ export class TaskLineRenderer {
         // So if the priority was not rendered, force it through the pipe of getting the component data for the
         // priority field.
         if (li.dataset.taskPriority === undefined) {
-            fieldRenderer.addDataAttribute(li, task, 'priority');
+            fieldRenderer.addDataAttribute(li, task, TaskLayoutComponent.Priority);
         }
     }
 
@@ -208,7 +208,7 @@ export class TaskLineRenderer {
         component: TaskLayoutComponent,
         task: Task,
     ) {
-        if (component === 'description') {
+        if (component === TaskLayoutComponent.Description) {
             componentString = GlobalFilter.getInstance().removeAsWordFromDependingOnSettings(componentString);
 
             const { debugSettings } = getSettings();
@@ -270,7 +270,7 @@ export class TaskLineRenderer {
             else return null;
         }
 
-        if (component === 'description') {
+        if (component === TaskLayoutComponent.Description) {
             const tags = internalSpan.getElementsByClassName('tag');
             for (let i = 0; i < tags.length; i++) {
                 const tagName = tags[i].textContent;
diff --git a/src/TaskSerializer/DataviewTaskSerializer.ts b/src/TaskSerializer/DataviewTaskSerializer.ts
index d3be4b34..a91c3dc7 100644
--- a/src/TaskSerializer/DataviewTaskSerializer.ts
+++ b/src/TaskSerializer/DataviewTaskSerializer.ts
@@ -1,6 +1,6 @@
-import type { TaskLayoutComponent } from '../Layout/TaskLayoutOptions';
-import type { Task } from '../Task/Task';
+import { TaskLayoutComponent } from '../Layout/TaskLayoutOptions';
 import { Priority } from '../Task/Priority';
+import type { Task } from '../Task/Task';
 import { DefaultTaskSerializer } from './DefaultTaskSerializer';
 
 /**
@@ -119,7 +119,10 @@ export class DataviewTaskSerializer extends DefaultTaskSerializer {
 
     public componentToString(task: Task, shortMode: boolean, component: TaskLayoutComponent) {
         const stringComponent = super.componentToString(task, shortMode, component);
-        const notInlineFieldComponents: TaskLayoutComponent[] = ['blockLink', 'description'];
+        const notInlineFieldComponents: TaskLayoutComponent[] = [
+            TaskLayoutComponent.BlockLink,
+            TaskLayoutComponent.Description,
+        ];
         const shouldMakeInlineField = stringComponent !== '' && !notInlineFieldComponents.includes(component);
         return shouldMakeInlineField
             ? // Having 2 (TWO) leading spaces avoids a rendering issues that makes every other
diff --git a/src/TaskSerializer/DefaultTaskSerializer.ts b/src/TaskSerializer/DefaultTaskSerializer.ts
index 85b4ca7a..117751d4 100644
--- a/src/TaskSerializer/DefaultTaskSerializer.ts
+++ b/src/TaskSerializer/DefaultTaskSerializer.ts
@@ -1,5 +1,5 @@
 import type { Moment } from 'moment';
-import { type TaskLayoutComponent, TaskLayoutOptions } from '../Layout/TaskLayoutOptions';
+import { TaskLayoutComponent, TaskLayoutOptions } from '../Layout/TaskLayoutOptions';
 import { Recurrence } from '../Task/Recurrence';
 import { Task } from '../Task/Task';
 import { Priority } from '../Task/Priority';
@@ -136,9 +136,9 @@ export class DefaultTaskSerializer implements TaskSerializer {
 
         switch (component) {
             // NEW_TASK_FIELD_EDIT_REQUIRED
-            case 'description':
+            case TaskLayoutComponent.Description:
                 return task.description;
-            case 'priority': {
+            case TaskLayoutComponent.Priority: {
                 let priority: string = '';
 
                 if (task.priority === Priority.Highest) {
@@ -154,29 +154,29 @@ export class DefaultTaskSerializer implements TaskSerializer {
                 }
                 return priority;
             }
-            case 'startDate':
+            case TaskLayoutComponent.StartDate:
                 return symbolAndDateValue(shortMode, startDateSymbol, task.startDate);
-            case 'createdDate':
+            case TaskLayoutComponent.CreatedDate:
                 return symbolAndDateValue(shortMode, createdDateSymbol, task.createdDate);
-            case 'scheduledDate':
+            case TaskLayoutComponent.ScheduledDate:
                 if (task.scheduledDateIsInferred) return '';
                 return symbolAndDateValue(shortMode, scheduledDateSymbol, task.scheduledDate);
-            case 'doneDate':
+            case TaskLayoutComponent.DoneDate:
                 return symbolAndDateValue(shortMode, doneDateSymbol, task.doneDate);
-            case 'cancelledDate':
+            case TaskLayoutComponent.CancelledDate:
                 return symbolAndDateValue(shortMode, cancelledDateSymbol, task.cancelledDate);
-            case 'dueDate':
+            case TaskLayoutComponent.DueDate:
                 return symbolAndDateValue(shortMode, dueDateSymbol, task.dueDate);
-            case 'recurrenceRule':
+            case TaskLayoutComponent.RecurrenceRule:
                 if (!task.recurrence) return '';
                 return symbolAndStringValue(shortMode, recurrenceSymbol, task.recurrence.toText());
-            case 'blockedBy': {
+            case TaskLayoutComponent.BlockedBy: {
                 if (task.blockedBy.length === 0) return '';
                 return symbolAndStringValue(shortMode, blockedBySymbol, task.blockedBy.join(','));
             }
-            case 'id':
+            case TaskLayoutComponent.Id:
                 return symbolAndStringValue(shortMode, idSymbol, task.id);
-            case 'blockLink':
+            case TaskLayoutComponent.BlockLink:
                 return task.blockLink ?? '';
             default:
                 throw new Error(`Don't know how to render task component of type '${component}'`);


Test patch:
diff --git a/tests/Layout/TaskLayoutOptions.test.ts b/tests/Layout/TaskLayoutOptions.test.ts
index 96cbfc26..84364e44 100644
--- a/tests/Layout/TaskLayoutOptions.test.ts
+++ b/tests/Layout/TaskLayoutOptions.test.ts
@@ -1,4 +1,4 @@
-import { TaskLayoutOptions } from '../../src/Layout/TaskLayoutOptions';
+import { TaskLayoutComponent, TaskLayoutOptions } from '../../src/Layout/TaskLayoutOptions';
 
 describe('TaskLayoutOptions', () => {
     it('should be constructable', () => {
@@ -26,25 +26,25 @@ describe('TaskLayoutOptions', () => {
     it('should show fields by default', () => {
         const options = new TaskLayoutOptions();
 
-        expect(options.isShown('priority')).toEqual(true);
-        expect(options.isShown('createdDate')).toEqual(true);
+        expect(options.isShown(TaskLayoutComponent.Priority)).toEqual(true);
+        expect(options.isShown(TaskLayoutComponent.CreatedDate)).toEqual(true);
     });
 
     it('should be able to hide a field', () => {
         const options = new TaskLayoutOptions();
-        options.hide('createdDate');
+        options.hide(TaskLayoutComponent.CreatedDate);
 
-        expect(options.isShown('createdDate')).toEqual(false);
+        expect(options.isShown(TaskLayoutComponent.CreatedDate)).toEqual(false);
     });
 
     it('should be settable via a boolean', () => {
         const options = new TaskLayoutOptions();
 
-        options.setVisibility('scheduledDate', false);
-        expect(options.isShown('scheduledDate')).toEqual(false);
+        options.setVisibility(TaskLayoutComponent.ScheduledDate, false);
+        expect(options.isShown(TaskLayoutComponent.ScheduledDate)).toEqual(false);
 
-        options.setVisibility('scheduledDate', true);
-        expect(options.isShown('scheduledDate')).toEqual(true);
+        options.setVisibility(TaskLayoutComponent.ScheduledDate, true);
+        expect(options.isShown(TaskLayoutComponent.ScheduledDate)).toEqual(true);
     });
 
     it('should set tag visibility', () => {
@@ -75,8 +75,8 @@ describe('TaskLayoutOptions', () => {
             blockLink"
         `);
 
-        options.setVisibility('dueDate', false);
-        options.setVisibility('blockLink', false);
+        options.setVisibility(TaskLayoutComponent.DueDate, false);
+        options.setVisibility(TaskLayoutComponent.BlockLink, false);
 
         expect(options.shownComponents.join('\n')).toMatchInlineSnapshot(`
             "description
@@ -96,8 +96,8 @@ describe('TaskLayoutOptions', () => {
         const options = new TaskLayoutOptions();
         expect(options.hiddenComponents.join('\n')).toMatchInlineSnapshot('""');
 
-        options.setVisibility('startDate', false);
-        options.setVisibility('doneDate', false);
+        options.setVisibility(TaskLayoutComponent.StartDate, false);
+        options.setVisibility(TaskLayoutComponent.DoneDate, false);
 
         expect(options.hiddenComponents.join('\n')).toMatchInlineSnapshot(`
             "startDate
@@ -108,26 +108,26 @@ describe('TaskLayoutOptions', () => {
     it('should toggle visibility', () => {
         const options = new TaskLayoutOptions();
 
-        options.setVisibility('cancelledDate', false);
-        options.setVisibility('priority', true);
+        options.setVisibility(TaskLayoutComponent.CancelledDate, false);
+        options.setVisibility(TaskLayoutComponent.Priority, true);
         options.setTagsVisibility(true);
 
         options.toggleVisibilityExceptDescriptionAndBlockLink();
 
-        expect(options.isShown('cancelledDate')).toEqual(true);
-        expect(options.isShown('priority')).toEqual(false);
+        expect(options.isShown(TaskLayoutComponent.CancelledDate)).toEqual(true);
+        expect(options.isShown(TaskLayoutComponent.Priority)).toEqual(false);
         expect(options.areTagsShown()).toEqual(false);
     });
 
     it('should not toggle visibility of description and blockLink', () => {
         const options = new TaskLayoutOptions();
-        options.setVisibility('description', true);
-        options.setVisibility('blockLink', true);
+        options.setVisibility(TaskLayoutComponent.Description, true);
+        options.setVisibility(TaskLayoutComponent.BlockLink, true);
 
         options.toggleVisibilityExceptDescriptionAndBlockLink();
 
-        expect(options.isShown('description')).toEqual(true);
-        expect(options.isShown('blockLink')).toEqual(true);
+        expect(options.isShown(TaskLayoutComponent.Description)).toEqual(true);
+        expect(options.isShown(TaskLayoutComponent.BlockLink)).toEqual(true);
     });
 
     it('should provide toggleable components', () => {
diff --git a/tests/Renderer/TaskFieldRenderer.test.ts b/tests/Renderer/TaskFieldRenderer.test.ts
index 5bd603d1..0c68ce32 100644
--- a/tests/Renderer/TaskFieldRenderer.test.ts
+++ b/tests/Renderer/TaskFieldRenderer.test.ts
@@ -2,6 +2,7 @@
  * @jest-environment jsdom
  */
 import moment from 'moment';
+import { TaskLayoutComponent } from '../../src/Layout/TaskLayoutOptions';
 import { TaskFieldHTMLData, TaskFieldRenderer } from '../../src/Renderer/TaskFieldRenderer';
 import { TaskBuilder } from '../TestingTools/TaskBuilder';
 
@@ -23,7 +24,7 @@ describe('Field Layouts Container tests', () => {
         const task = new TaskBuilder().dueDate('2023-11-20').build();
         const span = document.createElement('span');
 
-        fieldRenderer.addDataAttribute(span, task, 'dueDate');
+        fieldRenderer.addDataAttribute(span, task, TaskLayoutComponent.DueDate);
 
         expect(span).toHaveDataAttributes('taskDue: future-1d');
     });
@@ -32,7 +33,7 @@ describe('Field Layouts Container tests', () => {
         const task = TaskBuilder.createFullyPopulatedTask();
         const span = document.createElement('span');
 
-        fieldRenderer.addDataAttribute(span, task, 'priority');
+        fieldRenderer.addDataAttribute(span, task, TaskLayoutComponent.Priority);
 
         expect(span).toHaveDataAttributes('taskPriority: medium');
     });
@@ -41,7 +42,7 @@ describe('Field Layouts Container tests', () => {
         const task = new TaskBuilder().build();
         const span = document.createElement('span');
 
-        fieldRenderer.addDataAttribute(span, task, 'recurrenceRule');
+        fieldRenderer.addDataAttribute(span, task, TaskLayoutComponent.RecurrenceRule);
 
         expect(span).toHaveDataAttributes('');
     });
@@ -49,7 +50,7 @@ describe('Field Layouts Container tests', () => {
     it('should add a class name for a component', () => {
         const span = document.createElement('span');
 
-        fieldRenderer.addClassName(span, 'startDate');
+        fieldRenderer.addClassName(span, TaskLayoutComponent.StartDate);
 
         expect(span.classList.toString()).toEqual('task-start');
     });
@@ -69,7 +70,7 @@ describe('Field Layout Detail tests', () => {
         });
         const span = document.createElement('span');
 
-        fieldLayoutDetail.addDataAttribute(span, new TaskBuilder().build(), 'priority');
+        fieldLayoutDetail.addDataAttribute(span, new TaskBuilder().build(), TaskLayoutComponent.Priority);
 
         expect(span).toHaveDataAttributes('taskPriority: highest');
     });
@@ -80,7 +81,7 @@ describe('Field Layout Detail tests', () => {
         });
         const span = document.createElement('span');
 
-        fieldLayoutDetail.addDataAttribute(span, new TaskBuilder().build(), 'dueDate');
+        fieldLayoutDetail.addDataAttribute(span, new TaskBuilder().build(), TaskLayoutComponent.DueDate);
 
         expect(span).toHaveDataAttributes('');
     });
@@ -91,7 +92,7 @@ describe('Field Layout Detail tests', () => {
         });
         const span = document.createElement('span');
 
-        fieldLayoutDetail.addDataAttribute(span, new TaskBuilder().build(), 'startDate');
+        fieldLayoutDetail.addDataAttribute(span, new TaskBuilder().build(), TaskLayoutComponent.StartDate);
 
         expect(span).toHaveDataAttributes('');
     });
diff --git a/tests/Renderer/TaskLineRenderer.test.ts b/tests/Renderer/TaskLineRenderer.test.ts
index 30180696..f8c28c27 100644
--- a/tests/Renderer/TaskLineRenderer.test.ts
+++ b/tests/Renderer/TaskLineRenderer.test.ts
@@ -5,16 +5,16 @@ import moment from 'moment';
 import { DebugSettings } from '../../src/Config/DebugSettings';
 import { GlobalFilter } from '../../src/Config/GlobalFilter';
 import { resetSettings, updateSettings } from '../../src/Config/Settings';
-import { type TaskLayoutComponent, TaskLayoutOptions, taskLayoutComponents } from '../../src/Layout/TaskLayoutOptions';
-import { DateParser } from '../../src/Query/DateParser';
 import { QueryLayoutOptions } from '../../src/Layout/QueryLayoutOptions';
-import type { Task } from '../../src/Task/Task';
+import { TaskLayoutComponent, TaskLayoutOptions, taskLayoutComponents } from '../../src/Layout/TaskLayoutOptions';
+import { DateParser } from '../../src/Query/DateParser';
 import type { TextRenderer } from '../../src/Renderer/TaskLineRenderer';
 import { TaskLineRenderer } from '../../src/Renderer/TaskLineRenderer';
-import { fromLine } from '../TestingTools/TestHelpers';
+import type { Task } from '../../src/Task/Task';
+import { TaskRegularExpressions } from '../../src/Task/TaskRegularExpressions';
 import { verifyWithFileExtension } from '../TestingTools/ApprovalTestHelpers';
 import { TaskBuilder } from '../TestingTools/TaskBuilder';
-import { TaskRegularExpressions } from '../../src/Task/TaskRegularExpressions';
+import { fromLine } from '../TestingTools/TestHelpers';
 
 jest.mock('obsidian');
 window.moment = moment;
@@ -185,7 +185,7 @@ describe('task line rendering - layout options', () => {
         });
 
         // Re-enable description
-        taskLayoutOptions.setVisibility('description', true);
+        taskLayoutOptions.setVisibility(TaskLayoutComponent.Description, true);
 
         // Re-enable the requested components:
         shownComponents.forEach((hiddenComponent) => {
@@ -240,43 +240,46 @@ describe('task line rendering - layout options', () => {
     // NEW_TASK_FIELD_EDIT_REQUIRED
 
     it('renders with priority', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' 🔼'], ['priority']);
+        await testLayoutOptions(['Do exercises #todo #health', ' 🔼'], [TaskLayoutComponent.Priority]);
     });
 
     it('renders with recurrence rule', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' 🔁 every day when done'], ['recurrenceRule']);
+        await testLayoutOptions(
+            ['Do exercises #todo #health', ' 🔁 every day when done'],
+            [TaskLayoutComponent.RecurrenceRule],
+        );
     });
 
     it('renders with created date', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' ➕ 2023-07-01'], ['createdDate']);
+        await testLayoutOptions(['Do exercises #todo #health', ' ➕ 2023-07-01'], [TaskLayoutComponent.CreatedDate]);
     });
 
     it('renders with start date', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' 🛫 2023-07-02'], ['startDate']);
+        await testLayoutOptions(['Do exercises #todo #health', ' 🛫 2023-07-02'], [TaskLayoutComponent.StartDate]);
     });
 
     it('renders with scheduled date', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' ⏳ 2023-07-03'], ['scheduledDate']);
+        await testLayoutOptions(['Do exercises #todo #health', ' ⏳ 2023-07-03'], [TaskLayoutComponent.ScheduledDate]);
     });
 
     it('renders with due date', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' 📅 2023-07-04'], ['dueDate']);
+        await testLayoutOptions(['Do exercises #todo #health', ' 📅 2023-07-04'], [TaskLayoutComponent.DueDate]);
     });
 
     it('renders with done date', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' ✅ 2023-07-05'], ['doneDate']);
+        await testLayoutOptions(['Do exercises #todo #health', ' ✅ 2023-07-05'], [TaskLayoutComponent.DoneDate]);
     });
 
     it('renders with cancelled date', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' ❌ 2023-07-06'], ['cancelledDate']);
+        await testLayoutOptions(['Do exercises #todo #health', ' ❌ 2023-07-06'], [TaskLayoutComponent.CancelledDate]);
     });
 
     it('renders with id', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' 🆔 abcdef'], ['id']);
+        await testLayoutOptions(['Do exercises #todo #health', ' 🆔 abcdef'], [TaskLayoutComponent.Id]);
     });
 
     it('renders with depends on', async () => {
-        await testLayoutOptions(['Do exercises #todo #health', ' ⛔️ 123456,abc123'], ['blockedBy']);
+        await testLayoutOptions(['Do exercises #todo #health', ' ⛔️ 123456,abc123'], [TaskLayoutComponent.BlockedBy]);
     });
 });