Repository: obsidian-tasks-group/obsidian-tasks (ts)

Issue:
'sort by path' handles mixed case differently to 'sort by description'
### Please check that this issue hasn't been reported before.

- [X] I searched previous [Bug Reports](https://github.com/obsidian-tasks-group/obsidian-tasks/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+bug%22+sort%3Acomments-desc) didn't find any similar reports.

### Expected Behavior

I would expect all sorting of text fields to give consistent order when comparing upper and lower case strings.
Either Capitals first or Lower case first.



### Current behaviour

The current behaviour is that they differ, as these two tests show:

```ts
    it('sort by description', () => {
        // Arrange
        const sorter = new DescriptionField().createNormalSorter();

        // Assert
        // ~~case-sensitive - capitals come last~~
        // ~~TODO WHY? In description searches, capitals appear to come first.~~
        // UPDATE: Description sorting ignored case - I didn't have enough tests to realise that.
        expectTaskComparesAfter(sorter, with_description('AAA'), with_description('aaa'));
    });
```

```ts
    it('sort by path', () => {
        // Arrange
        const sorter = new PathField().createNormalSorter();

        // Assert
        // case-sensitive - capitals come first
        expectTaskComparesBefore(sorter, with_path('c/D.md'), with_path('c/d.md'));
    });
```

### Steps to reproduce

See the tests above.

I can't demo this on a Mac as mine has the default behaviour of filenames not being case-sensitive, so I can't make two files in the same path, differing only by case.



### Which Operating Systems are you using?

- [ ] Android
- [ ] iPhone/iPad
- [ ] Linux
- [X] macOS
- [ ] Windows

### Obsidian Version

1.1.9

### Tasks Plugin Version

1.20.0

### Checks

- [ ] I have tried it with all other plugins disabled and the error still occurs

### Possible solution

The issue is the different implementations of sorting for those two fields:

https://github.com/obsidian-tasks-group/obsidian-tasks/blob/b20a44c863a93135ca32b80f4b7d522490b59ab5/src/Query/Filter/DescriptionField.ts#L44-L50

https://github.com/obsidian-tasks-group/obsidian-tasks/blob/b20a44c863a93135ca32b80f4b7d522490b59ab5/src/Query/Filter/PathField.ts#L29-L39

In newer code, I've added this as the default sorting implementation for text fields:

https://github.com/obsidian-tasks-group/obsidian-tasks/blob/b20a44c863a93135ca32b80f4b7d522490b59ab5/src/Query/Filter/TextField.ts#L94-L105

I do think that wherever possible, the sorting of string fields should use locale-aware searches.

So the trivial fix for this is:

1. Remove `PathField`'s own `comparator()` implementation, so that the `TextField` one is used
2. Update the `PathField` test that shows the opposite sorted order to what is expected
3. Remove the comment in `DescriptionField.test.ts` that remarks on the difference in behaviour.

See also the following - further examples of the value of using more sophisticating sorting code, rather than rolling our own:

- https://github.com/obsidian-tasks-group/obsidian-tasks/issues/1429
- https://github.com/obsidian-tasks-group/obsidian-tasks/issues/1430

Pull request description:
fix: Make 'sort by path' sort ignoring capitalisation

<!--- Provide a general summary of your changes in the Title above -->

# Description

Make 'sort by path' ignore capitalisation

Also add more tests of 'sort by description' to show that it ignores case.

## Motivation and Context

Fixes #1432.

## How has this been tested?

Updating unit tests.
Once this PR has built the plugin, I will test it manually as well.

## Screenshots (if appropriate)

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

Changes visible to users:

- [x] **Bug fix** (prefix: `fix` - non-breaking change which fixes an issue)

Internal changes:

- [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/PathField.ts b/src/Query/Filter/PathField.ts
index b8dc28ca..0db74d6e 100644
--- a/src/Query/Filter/PathField.ts
+++ b/src/Query/Filter/PathField.ts
@@ -1,5 +1,4 @@
 import type { Task } from '../../Task';
-import type { Comparator } from '../Sorter';
 import { TextField } from './TextField';
 
 /** Support the 'path' search instruction.
@@ -25,16 +24,4 @@ export class PathField extends TextField {
     public supportsSorting(): boolean {
         return true;
     }
-
-    public comparator(): Comparator {
-        return (a: Task, b: Task) => {
-            if (a.path < b.path) {
-                return -1;
-            } else if (a.path > b.path) {
-                return 1;
-            } else {
-                return 0;
-            }
-        };
-    }
 }


Test patch:
diff --git a/tests/Query/Filter/DescriptionField.test.ts b/tests/Query/Filter/DescriptionField.test.ts
index f8bbcea7..997c255c 100644
--- a/tests/Query/Filter/DescriptionField.test.ts
+++ b/tests/Query/Filter/DescriptionField.test.ts
@@ -270,7 +270,11 @@ describe('sorting by description', () => {
         // Assert
         expectTaskComparesEqual(sorter, with_description('Aaa'), with_description('Aaa'));
         expectTaskComparesBefore(sorter, with_description('AAA'), with_description('ZZZ'));
-        expectTaskComparesAfter(sorter, with_description('AAA'), with_description('aaa')); // case-sensitive - capitals come last - TODO WHY? In description searches, capitals appear to come first.
+
+        // Ignores case if strings differ
+        expectTaskComparesBefore(sorter, with_description('AAA'), with_description('bbb'));
+        expectTaskComparesBefore(sorter, with_description('aaa'), with_description('BBB'));
+        expectTaskComparesBefore(sorter, with_description('aaa'), with_description('AAA'));
     });
 
     it('sort by description reverse', () => {
diff --git a/tests/Query/Filter/PathField.test.ts b/tests/Query/Filter/PathField.test.ts
index ecc6957b..d9ac8859 100644
--- a/tests/Query/Filter/PathField.test.ts
+++ b/tests/Query/Filter/PathField.test.ts
@@ -134,7 +134,11 @@ describe('sorting by path', () => {
         // Assert
         expectTaskComparesEqual(sorter, with_path('a/b.md'), with_path('a/b.md'));
         expectTaskComparesBefore(sorter, with_path('a/b.md'), with_path('c/d.md'));
-        expectTaskComparesBefore(sorter, with_path('c/D.md'), with_path('c/d.md')); // case-sensitive - capitals come first
+
+        // Ignores case if strings differ
+        expectTaskComparesBefore(sorter, with_path('aaaa/bbbb.md'), with_path('CCCC/DDDD.md'));
+        expectTaskComparesBefore(sorter, with_path('AAAA/BBBB.md'), with_path('cccc/dddd.md'));
+        expectTaskComparesBefore(sorter, with_path('aaaa/bbbb.md'), with_path('AAAA/BBBB.md'));
 
         // Beginning with numbers
         expectTaskComparesBefore(sorter, with_path('c/1.md'), with_path('c/9.md'));