Repository: obsidian-tasks-group/obsidian-tasks
Pull request #1403 (2022-12-16 13:52:14)

refactor: Break some cyclic dependencies in Sorting code
<!--- Provide a general summary of your changes in the Title above -->

# Description

## Break some cyclic dependencies in Sorting code.

- `Comparator` and `Sorting` have moved from `Sort.ts `to `Sorting.ts`
    - This means that the moved symbols can now be used without having to pull in all of `Sort.ts`
- Move `Sort.compareByDate()` to `DateField.compareByDate()`
- `Sorting` no longer has any code related to the legacy sorting functions and `SortingProperty`
    - This involved moving methods between `Sort` and `Sorting`. See the diffs for details.

## Which enabled me to remove some duplicated code

`Field` implementations now only need to implement the following two methods in order to support sorting:

```ts
    public supportsSorting(): boolean {
        return true;
    }

    /**
     * Return a function to compare two Task objects, for use in sorting by due.
     */
    public comparator(): Comparator {
        return (a: Task, b: Task) => {
            return DateField.compareByDate(this.date(a), this.date(b));
        };
    }
```


## Motivation and Context

This is step 5 in splitting out all the sort functions to the relevant fields, to make it easier to add new sort instructions, and to be able to re-use the sort code to sort groups in reverse order.

## How has this been tested?

- By running existing tests

## Screenshots (if appropriate)

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->


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

<!--- 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://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md#updating-documentation) accordingly.
- [x] My change has adequate [Unit Test coverage](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md#maintaining-the-tests).

## Terms

<!--
By submitting this pull request, you must agree to follow our
[contributing guide](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md) 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://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/CONTRIBUTING.md)
- [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/Query/Filter/DateField.ts b/src/Query/Filter/DateField.ts
index ac694524..a64256c6 100644
--- a/src/Query/Filter/DateField.ts
+++ b/src/Query/Filter/DateField.ts
@@ -119,4 +119,28 @@ export abstract class DateField extends Field {
      * @protected
      */
     protected abstract filterResultIfFieldMissing(): boolean;
+
+    public static compareByDate(a: moment.Moment | null, b: moment.Moment | null): -1 | 0 | 1 {
+        if (a !== null && b === null) {
+            return -1;
+        } else if (a === null && b !== null) {
+            return 1;
+        } else if (a !== null && b !== null) {
+            if (a.isValid() && !b.isValid()) {
+                return -1;
+            } else if (!a.isValid() && b.isValid()) {
+                return 1;
+            }
+
+            if (a.isAfter(b)) {
+                return 1;
+            } else if (a.isBefore(b)) {
+                return -1;
+            } else {
+                return 0;
+            }
+        } else {
+            return 0;
+        }
+    }
 }
diff --git a/src/Query/Filter/DueDateField.ts b/src/Query/Filter/DueDateField.ts
index f50540ac..fc11d2c6 100644
--- a/src/Query/Filter/DueDateField.ts
+++ b/src/Query/Filter/DueDateField.ts
@@ -1,7 +1,6 @@
 import type { Moment } from 'moment';
 import type { Task } from '../../Task';
-import type { Comparator } from '../Sort';
-import { Sort, Sorting } from '../Sort';
+import type { Comparator } from '../Sorting';
 import { DateField } from './DateField';
 
 /**
@@ -27,16 +26,12 @@ export class DueDateField extends DateField {
         return true;
     }
 
-    public createSorter(reverse: boolean): Sorting {
-        return new Sorting(reverse, 1, this.fieldName(), this.comparator());
-    }
-
     /**
      * Return a function to compare two Task objects, for use in sorting by due.
      */
     public comparator(): Comparator {
         return (a: Task, b: Task) => {
-            return Sort.compareByDate(this.date(a), this.date(b));
+            return DateField.compareByDate(this.date(a), this.date(b));
         };
     }
 }
diff --git a/src/Query/Filter/Field.ts b/src/Query/Filter/Field.ts
index 95d37ee9..ab699efc 100644
--- a/src/Query/Filter/Field.ts
+++ b/src/Query/Filter/Field.ts
@@ -1,4 +1,5 @@
-import type { Sorting } from '../Sort';
+import { Sorting } from '../Sorting';
+import type { Comparator } from '../Sorting';
 import type { FilterOrErrorMessage } from './Filter';
 
 /**
@@ -87,13 +88,20 @@ export abstract class Field {
         return false;
     }
 
+    /**
+     * Return a function to compare two Task objects, for use in sorting by this field's value.
+     */
+    public comparator(): Comparator {
+        // TODO Make abstract
+        throw Error(`comparator() unimplemented for ${this.fieldName()}`);
+    }
+
     /**
      * Create a {@link Sorting} object for sorting tasks by this field's value.
      * @param reverse - false for normal sort order, true for reverse sort order.
      */
     public createSorter(reverse: boolean): Sorting {
-        // TODO Make abstract
-        throw Error(`createSorter() unimplemented for ${this.fieldName()} - reverse = ${reverse}`);
+        return new Sorting(reverse, 1, this.fieldName(), this.comparator());
     }
 
     /**
diff --git a/src/Query/Filter/HappensDateField.ts b/src/Query/Filter/HappensDateField.ts
index 0287eea1..b598f055 100644
--- a/src/Query/Filter/HappensDateField.ts
+++ b/src/Query/Filter/HappensDateField.ts
@@ -1,7 +1,6 @@
 import type { Moment } from 'moment';
 import type { Task } from '../../Task';
 import { DateParser } from '../DateParser';
-import { Sort } from '../Sort';
 import { Explanation } from '../Explain/Explanation';
 import { Field } from './Field';
 import { Filter, FilterOrErrorMessage } from './Filter';
@@ -92,7 +91,7 @@ export class HappensDateField extends Field {
      */
     public earliestDate(task: Task): Moment | null {
         const happensDates = new HappensDateField().dates(task);
-        const sortedHappensDates = happensDates.sort(Sort.compareByDate);
+        const sortedHappensDates = happensDates.sort(DateField.compareByDate);
         return sortedHappensDates[0];
     }
 
diff --git a/src/Query/Filter/StatusField.ts b/src/Query/Filter/StatusField.ts
index 8f7a724c..5d6a1df5 100644
--- a/src/Query/Filter/StatusField.ts
+++ b/src/Query/Filter/StatusField.ts
@@ -1,6 +1,5 @@
 import { Status, Task } from '../../Task';
-import type { Comparator } from '../Sort';
-import { Sorting } from '../Sort';
+import type { Comparator } from '../Sorting';
 import { FilterInstructionsBasedField } from './FilterInstructionsBasedField';
 
 export class StatusField extends FilterInstructionsBasedField {
@@ -19,11 +18,6 @@ export class StatusField extends FilterInstructionsBasedField {
         return true;
     }
 
-    // TODO Move createSorter() to Field
-    public createSorter(reverse: boolean): Sorting {
-        return new Sorting(reverse, 1, this.fieldName(), this.comparator());
-    }
-
     /**
      * Return a function to compare two Task objects, for use in sorting by status.
      */
diff --git a/src/Query/FilterParser.ts b/src/Query/FilterParser.ts
index b12d4357..cee5b614 100644
--- a/src/Query/FilterParser.ts
+++ b/src/Query/FilterParser.ts
@@ -15,7 +15,7 @@ import { BooleanField } from './Filter/BooleanField';
 import { FilenameField } from './Filter/FilenameField';
 
 import type { FilterOrErrorMessage } from './Filter/Filter';
-import type { Sorting } from './Sort';
+import type { Sorting } from './Sorting';
 
 const fieldCreators = [
     () => new StatusField(),
diff --git a/src/Query/Query.ts b/src/Query/Query.ts
index e0407304..b8e258d1 100644
--- a/src/Query/Query.ts
+++ b/src/Query/Query.ts
@@ -2,7 +2,8 @@ import { LayoutOptions } from '../LayoutOptions';
 import type { Task } from '../Task';
 import type { IQuery } from '../IQuery';
 import { getSettings } from '../Config/Settings';
-import { Sort, Sorting } from './Sort';
+import { Sort } from './Sort';
+import type { Sorting } from './Sorting';
 import type { TaskGroups } from './TaskGroups';
 import { parseFilter, parseSorter } from './FilterParser';
 import { Group } from './Group';
@@ -244,7 +245,7 @@ export class Query implements IQuery {
         const fieldMatch = line.match(this.sortByRegexp);
         if (fieldMatch !== null) {
             this._sorting.push(
-                new Sorting(
+                Sort.makeLegacySorting(
                     !!fieldMatch[2],
                     isNaN(+fieldMatch[3]) ? 1 : +fieldMatch[3],
                     fieldMatch[1] as SortingProperty,
diff --git a/src/Query/Sort.ts b/src/Query/Sort.ts
index 24fa8998..0c56a60a 100644
--- a/src/Query/Sort.ts
+++ b/src/Query/Sort.ts
@@ -1,76 +1,12 @@
-import type moment from 'moment';
 import type { Task } from '../Task';
 import { getSettings } from '../Config/Settings';
+import { Sorting } from './Sorting';
+import type { Comparator } from './Sorting';
 import type { Query, SortingProperty } from './Query';
 // TODO Remove the cyclic dependency between StatusField and Sort.
 import { StatusField } from './Filter/StatusField';
 import { DueDateField } from './Filter/DueDateField';
-
-/**
- * A sorting function, that takes two Task objects and returns
- * and returns one of:
- * - `-1` or some other negative number, if a is less than b by some ordering criterion.
- * - `+1` or some other positive number, if a is greater than b by the ordering criterion.
- * - `0` or sometimes `-0`, if a equals b by the ordering criterion.
- *
- * Typically Comparator functions are stored in a {@link Sorting} object.
- */
-// TODO Move to Sorting.ts
-export type Comparator = (a: Task, b: Task) => number;
-
-/**
- * Sorting represents a single 'sort by' instruction.
- * It stores the comparison function as a {@link Comparator}.
- */
-// TODO Move to Sorting.ts
-export class Sorting {
-    public readonly property: string;
-    public readonly comparator: Comparator;
-    public readonly propertyInstance: number;
-
-    /**
-     * Constructor.
-     *
-     * TODO Once SortingProperty has been removed, re-order the parameters so the comparator comes first.
-     *
-     * @param reverse - whether the sort order should be reversed.
-     * @param propertyInstance - for tag sorting, this is a 1-based index for the tag number in the task to sort by.
-     *                           TODO eventually, move this number to the comparator used for sorting by tag.
-     * @param property - the name of the property. If {@link comparator} is not supplied, this string must match
-     *                   one of the values in ${@link SortingProperty}.
-     * @param comparator - optional {@link Comparator} function. This will eventually become required, and will then be moved to
-     *                     the first parameter.
-     */
-    constructor(reverse: boolean, propertyInstance: number, property: string, comparator?: Comparator) {
-        this.property = property;
-        this.propertyInstance = propertyInstance;
-        if (comparator) {
-            this.comparator = Sorting.maybeReverse(reverse, comparator);
-        } else {
-            // TODO Move comparator mandatory so can remove reference to this.makeComparator
-            this.comparator = this.makeComparator(reverse);
-        }
-    }
-
-    /**
-     * Legacy function, for creating a Comparator for a SortingProperty value.
-     *
-     * TODO Once SortingProperty in Query.ts has been removed, remove this method.
-     * @param reverse
-     */
-    public makeComparator(reverse: boolean) {
-        // TODO Move this to Sort class
-        const comparator = Sort.comparators[this.property as SortingProperty];
-        if (!comparator) {
-            throw Error('Unrecognised legacy sort keyword: ' + this.property);
-        }
-        return Sorting.maybeReverse(reverse, comparator);
-    }
-
-    private static maybeReverse(reverse: boolean, comparator: Comparator) {
-        return reverse ? Sort.makeReversedComparator(comparator) : comparator;
-    }
-}
+import { DateField } from './Filter/DateField';
 
 export class Sort {
     static tagPropertyInstance: number = 1;
@@ -108,9 +44,35 @@ export class Sort {
         tag: Sort.compareByTag,
     };
 
-    public static makeReversedComparator(comparator: Comparator): Comparator {
-        // Note: This can return -0.
-        return (a, b) => (comparator(a, b) * -1) as -1 | 0 | 1;
+    /**
+     * Legacy function, for creating a Sorting object for a SortingProperty type.
+     *
+     * TODO Once SortingProperty in Query.ts has been removed, remove this method.
+     * @param reverse - whether the sort order should be reversed.
+     * @param propertyInstance - for tag sorting, this is a 1-based index for the tag number in the task to sort by.
+     *                           TODO eventually, move this number to the comparator used for sorting by tag.
+     * @param property - the name of the property. This string must match
+     *                   one of the values in ${@link SortingProperty}.
+     */
+    public static makeLegacySorting(reverse: boolean, propertyInstance: number, property: string): Sorting {
+        const comparator = Sort.makeLegacyComparator(property);
+        return new Sorting(reverse, propertyInstance, property, comparator);
+    }
+
+    /**
+     * Legacy function, for creating a Comparator function for a SortingProperty type.
+     *
+     * TODO Once SortingProperty in Query.ts has been removed, remove this method.
+     * @param property - the name of the property. This string must match
+     *                   one of the values in ${@link SortingProperty}.
+     *                   Throws if property not recognised.
+     */
+    public static makeLegacyComparator(property: string): Comparator {
+        const comparator = Sort.comparators[property as SortingProperty];
+        if (!comparator) {
+            throw Error('Unrecognised legacy sort keyword: ' + property);
+        }
+        return comparator;
     }
 
     private static makeCompositeComparator(comparators: Comparator[]): Comparator {
@@ -135,15 +97,15 @@ export class Sort {
     }
 
     private static compareByStartDate(a: Task, b: Task): -1 | 0 | 1 {
-        return Sort.compareByDate(a.startDate, b.startDate);
+        return DateField.compareByDate(a.startDate, b.startDate);
     }
 
     private static compareByScheduledDate(a: Task, b: Task): -1 | 0 | 1 {
-        return Sort.compareByDate(a.scheduledDate, b.scheduledDate);
+        return DateField.compareByDate(a.scheduledDate, b.scheduledDate);
     }
 
     private static compareByDoneDate(a: Task, b: Task): -1 | 0 | 1 {
-        return Sort.compareByDate(a.doneDate, b.doneDate);
+        return DateField.compareByDate(a.doneDate, b.doneDate);
     }
 
     private static compareByTag(a: Task, b: Task): -1 | 0 | 1 {
@@ -177,31 +139,6 @@ export class Sort {
             return 0;
         }
     }
-
-    public static compareByDate(a: moment.Moment | null, b: moment.Moment | null): -1 | 0 | 1 {
-        if (a !== null && b === null) {
-            return -1;
-        } else if (a === null && b !== null) {
-            return 1;
-        } else if (a !== null && b !== null) {
-            if (a.isValid() && !b.isValid()) {
-                return -1;
-            } else if (!a.isValid() && b.isValid()) {
-                return 1;
-            }
-
-            if (a.isAfter(b)) {
-                return 1;
-            } else if (a.isBefore(b)) {
-                return -1;
-            } else {
-                return 0;
-            }
-        } else {
-            return 0;
-        }
-    }
-
     private static compareByPath(a: Task, b: Task): -1 | 0 | 1 {
         if (a.path < b.path) {
             return -1;
diff --git a/src/Query/Sorting.ts b/src/Query/Sorting.ts
new file mode 100644
index 00000000..3cdbbde6
--- /dev/null
+++ b/src/Query/Sorting.ts
@@ -0,0 +1,49 @@
+import type { Task } from '../Task';
+
+/**
+ * A sorting function, that takes two Task objects and returns
+ * and returns one of:
+ * - `-1` or some other negative number, if a is less than b by some ordering criterion.
+ * - `+1` or some other positive number, if a is greater than b by the ordering criterion.
+ * - `0` or sometimes `-0`, if a equals b by the ordering criterion.
+ *
+ * Typically Comparator functions are stored in a {@link Sorting} object.
+ */
+export type Comparator = (a: Task, b: Task) => number;
+
+/**
+ * Sorting represents a single 'sort by' instruction.
+ * It stores the comparison function as a {@link Comparator}.
+ */
+export class Sorting {
+    public readonly property: string;
+    public readonly comparator: Comparator;
+    public readonly propertyInstance: number;
+
+    /**
+     * Constructor.
+     *
+     * TODO Once SortingProperty has been removed, re-order the parameters so the comparator comes first.
+     *
+     * @param reverse - whether the sort order should be reversed.
+     * @param propertyInstance - for tag sorting, this is a 1-based index for the tag number in the task to sort by.
+     *                           TODO eventually, move this number to the comparator used for sorting by tag.
+     * @param property - the name of the property. If {@link comparator} is not supplied, this string must match
+     *                   one of the values in ${@link SortingProperty}.
+     * @param comparator - {@link Comparator} function.
+     */
+    constructor(reverse: boolean, propertyInstance: number, property: string, comparator: Comparator) {
+        this.property = property;
+        this.propertyInstance = propertyInstance;
+        this.comparator = Sorting.maybeReverse(reverse, comparator);
+    }
+
+    private static maybeReverse(reverse: boolean, comparator: Comparator) {
+        return reverse ? Sorting.makeReversedComparator(comparator) : comparator;
+    }
+
+    private static makeReversedComparator(comparator: Comparator): Comparator {
+        // Note: This can return -0.
+        return (a, b) => (comparator(a, b) * -1) as -1 | 0 | 1;
+    }
+}
diff --git a/src/Recurrence.ts b/src/Recurrence.ts
index 648b61da..0cf66cbf 100644
--- a/src/Recurrence.ts
+++ b/src/Recurrence.ts
@@ -1,6 +1,6 @@
 import type { Moment } from 'moment';
 import { RRule } from 'rrule';
-import { Sort } from './Query/Sort';
+import { DateField } from './Query/Filter/DateField';
 
 export class Recurrence {
     private readonly rrule: RRule;
@@ -195,13 +195,13 @@ export class Recurrence {
         }
 
         // Compare Date fields
-        if (Sort.compareByDate(this.startDate, other.startDate) !== 0) {
+        if (DateField.compareByDate(this.startDate, other.startDate) !== 0) {
             return false;
         }
-        if (Sort.compareByDate(this.scheduledDate, other.scheduledDate) !== 0) {
+        if (DateField.compareByDate(this.scheduledDate, other.scheduledDate) !== 0) {
             return false;
         }
-        if (Sort.compareByDate(this.dueDate, other.dueDate) !== 0) {
+        if (DateField.compareByDate(this.dueDate, other.dueDate) !== 0) {
             return false;
         }
 
diff --git a/src/Task.ts b/src/Task.ts
index 3bef98aa..59db4f5b 100644
--- a/src/Task.ts
+++ b/src/Task.ts
@@ -5,7 +5,7 @@ import { LayoutOptions } from './LayoutOptions';
 import { Recurrence } from './Recurrence';
 import { getSettings } from './Config/Settings';
 import { Urgency } from './Urgency';
-import { Sort } from './Query/Sort';
+import { DateField } from './Query/Filter/DateField';
 import { DateFallback } from './DateFallback';
 
 /**
@@ -791,7 +791,7 @@ export class Task {
         for (const el of args) {
             const date1 = this[el] as Moment | null;
             const date2 = other[el] as Moment | null;
-            if (Sort.compareByDate(date1, date2) !== 0) {
+            if (DateField.compareByDate(date1, date2) !== 0) {
                 return false;
             }
         }


Test patch:
diff --git a/tests/Sort.test.ts b/tests/Sort.test.ts
index 40e762dd..379d8f52 100644
--- a/tests/Sort.test.ts
+++ b/tests/Sort.test.ts
@@ -5,8 +5,10 @@ import moment from 'moment';
 
 window.moment = moment;
 
-import type { Comparator } from '../src/Query/Sort';
-import { Sort, Sorting } from '../src/Query/Sort';
+import type { Comparator } from '../src/Query/Sorting';
+import { Sort } from '../src/Query/Sort';
+import { DateField } from '../src/Query/Filter/DateField';
+import { Sorting } from '../src/Query/Sorting';
 import { resetSettings, updateSettings } from '../src/Config/Settings';
 import { DateParser } from '../src/Query/DateParser';
 import type { Task } from '../src/Task';
@@ -78,7 +80,7 @@ describe('Sort', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(false, 1, 'done')],
+                    sorting: [Sort.makeLegacySorting(false, 1, 'done')],
                 },
                 [three, two, one],
             ),
@@ -86,7 +88,7 @@ describe('Sort', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(false, 1, 'done')],
+                    sorting: [Sort.makeLegacySorting(false, 1, 'done')],
                 },
                 [two, one, three],
             ),
@@ -109,7 +111,7 @@ describe('Sort', () => {
                 {
                     sorting: [
                         new DueDateField().createNormalSorter(),
-                        new Sorting(false, 1, 'path'),
+                        Sort.makeLegacySorting(false, 1, 'path'),
                         new StatusField().createNormalSorter(),
                     ],
                 },
@@ -140,7 +142,10 @@ describe('Sort', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(false, 1, 'description'), new Sorting(false, 1, 'done')],
+                    sorting: [
+                        Sort.makeLegacySorting(false, 1, 'description'),
+                        Sort.makeLegacySorting(false, 1, 'done'),
+                    ],
                 },
                 [three, one, two, four],
             ),
@@ -169,7 +174,7 @@ describe('Sort', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(true, 1, 'description'), new Sorting(false, 1, 'done')],
+                    sorting: [Sort.makeLegacySorting(true, 1, 'description'), Sort.makeLegacySorting(false, 1, 'done')],
                 },
                 [two, four, three, one],
             ),
@@ -192,7 +197,7 @@ describe('Sort', () => {
                     sorting: [
                         new StatusField().createReverseSorter(),
                         new DueDateField().createReverseSorter(),
-                        new Sorting(false, 1, 'path'),
+                        Sort.makeLegacySorting(false, 1, 'path'),
                     ],
                 },
                 [six, five, one, four, three, two],
@@ -222,7 +227,7 @@ describe('Sort', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(false, 1, 'description')],
+                    sorting: [Sort.makeLegacySorting(false, 1, 'description')],
                 },
                 [two, one, five, four, three],
             ),
@@ -243,7 +248,7 @@ expect.extend({
         let b: moment.Moment | null = null;
         if (dateB !== null) b = DateParser.parseDate(dateB);
 
-        const actual = Sort.compareByDate(a, b);
+        const actual = DateField.compareByDate(a, b);
 
         const pass = actual === expected;
         const message = () => `${dateA} < ${dateB}: expected=${expected} actual=${actual}`;
@@ -320,7 +325,7 @@ describe('Sort by tags', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(false, 1, 'tag')],
+                    sorting: [Sort.makeLegacySorting(false, 1, 'tag')],
                 },
                 [t1, t3, t5, t7, t6, t4, t2, t8, t9, t10],
             ),
@@ -345,7 +350,7 @@ describe('Sort by tags', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(true, 1, 'tag')],
+                    sorting: [Sort.makeLegacySorting(true, 1, 'tag')],
                 },
                 [t1, t3, t5, t7, t6, t4, t2, t8, t9, t10],
             ),
@@ -362,7 +367,7 @@ describe('Sort by tags', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(false, 2, 'tag')],
+                    sorting: [Sort.makeLegacySorting(false, 2, 'tag')],
                 },
                 [t4, t3, t2, t1, t5],
             ),
@@ -379,7 +384,7 @@ describe('Sort by tags', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(true, 2, 'tag')],
+                    sorting: [Sort.makeLegacySorting(true, 2, 'tag')],
                 },
                 [t4, t3, t2, t1, t5],
             ),
@@ -410,7 +415,7 @@ describe('Sort by tags', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(false, 1, 'tag')],
+                    sorting: [Sort.makeLegacySorting(false, 1, 'tag')],
                 },
                 [t1, t12, t3, t13, t5, t7, t6, t4, t2, t8, t9, t10, t11],
             ),
@@ -444,7 +449,7 @@ describe('Sort by tags', () => {
         expect(
             Sort.by(
                 {
-                    sorting: [new Sorting(true, 1, 'tag')],
+                    sorting: [Sort.makeLegacySorting(true, 1, 'tag')],
                 },
                 [t1, t12, t3, t13, t5, t7, t6, t4, t2, t8, t9, t10, t11],
             ),
@@ -471,7 +476,7 @@ describe('Sort by tags', () => {
         // Act
         const result = Sort.by(
             {
-                sorting: [new Sorting(false, 2, 'tag')],
+                sorting: [Sort.makeLegacySorting(false, 2, 'tag')],
             },
             [t4, t7, t5, t2, t3, t1, t8, t6],
         );
@@ -500,7 +505,7 @@ describe('Sort by tags', () => {
         // Act
         const result = Sort.by(
             {
-                sorting: [new Sorting(true, 2, 'tag')],
+                sorting: [Sort.makeLegacySorting(true, 2, 'tag')],
             },
             [t4, t7, t5, t2, t3, t1, t8, t6],
         );