Repository: obsidian-tasks-group/obsidian-tasks
Pull request #2548 (2023-12-30 06:33:26)

refactor: replace `className()` method with `addClassName()`
# Description

`TaskFieldRenderer` has a `className()` method acting like a data getter (get a component's class). The data is used later to add to an `HTMLElement`. This PR replaces it with a `addClassName()` method that add the class to the target `HTMLElement`.

Previously `className()` was written in mind with usage in tests as well (As a provider of data). However #2545 removed the relation between the data in `TaskFieldRenderer` and the data in the tests.

## Motivation and Context

- have testable behaviour instead of data in `TaskFieldRendrer`
- hide implementation details of adding classes inside `TaskFieldRenderer`
- have uniform behaviour in `TaskFieldRenderer`: `addClassName()`, `addDataAttribute()`, ...

## How has this been tested?

New unit tests, breaking the code.

## 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/TaskFieldRenderer.ts b/src/TaskFieldRenderer.ts
index 17aa6345..1421da05 100644
--- a/src/TaskFieldRenderer.ts
+++ b/src/TaskFieldRenderer.ts
@@ -24,11 +24,15 @@ export class TaskFieldRenderer {
     }
 
     /**
-     * @returns the component's CSS class describing what this component is (priority, due date etc.).
+     * Adds the component's CSS class describing what this component is (priority, due date etc.) to an HTML element.
+     *
+     * @param element where the class shall be added.
+     *
      * @param component of the task.
      */
-    public className(component: TaskLayoutComponent) {
-        return this.data[component].className;
+    public addClassName(element: HTMLElement, component: TaskLayoutComponent) {
+        const componentClass = this.data[component].className;
+        element.classList.add(...[componentClass]);
     }
 }
 
diff --git a/src/TaskLineRenderer.ts b/src/TaskLineRenderer.ts
index dcc61a35..99b879f8 100644
--- a/src/TaskLineRenderer.ts
+++ b/src/TaskLineRenderer.ts
@@ -179,8 +179,7 @@ export class TaskLineRenderer {
                 this.addInternalClasses(component, internalSpan);
 
                 // Add the component's CSS class describing what this component is (priority, due date etc.)
-                const componentClass = fieldRenderer.className(component);
-                span.classList.add(...[componentClass]);
+                fieldRenderer.addClassName(span, component);
 
                 // Add the component's attribute ('priority-medium', 'due-past-1d' etc.)
                 fieldRenderer.addDataAttribute(span, task, component);


Test patch:
diff --git a/tests/TaskFieldRenderer.test.ts b/tests/TaskFieldRenderer.test.ts
index f0286daa..b28c9080 100644
--- a/tests/TaskFieldRenderer.test.ts
+++ b/tests/TaskFieldRenderer.test.ts
@@ -36,6 +36,7 @@ describe('Field Layouts Container tests', () => {
 
         expect(span).toHaveDataAttributes('taskPriority: medium');
     });
+
     it('should not add any data attributes for a missing component', () => {
         const task = new TaskBuilder().build();
         const span = document.createElement('span');
@@ -44,6 +45,14 @@ describe('Field Layouts Container tests', () => {
 
         expect(span).toHaveDataAttributes('');
     });
+
+    it('should add a class name for a component', () => {
+        const span = document.createElement('span');
+
+        fieldRenderer.addClassName(span, 'startDate');
+
+        expect(span.classList.toString()).toEqual('task-start');
+    });
 });
 
 describe('Field Layout Detail tests', () => {