Skip to content

Commit 1e06f18

Browse files
authored
Merge pull request #3194 from obsidian-tasks-group/format-mock-data-as-json
tests: Format mock data as JSON, for a stable order
2 parents bad833e + 5e9d698 commit 1e06f18

File tree

138 files changed

+8861
-8992
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

138 files changed

+8861
-8992
lines changed

contributing/Testing/Using Obsidian API in tests.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,19 @@ The Tasks plugin uses data created by the Obsidian API. The Obsidian API does no
1313
So we need a way to access Obsidian-generated data in our tests. This page tries to describe this mechanism.
1414

1515
1. [resources/sample_vaults/Tasks-Demo/Test Data](https://github.com/obsidian-tasks-group/obsidian-tasks/tree/main/resources/sample_vaults/Tasks-Demo/Test%20Data) contains representative samples Markdown files for different scenarios.
16-
2. The process described in [[#Test data creation sequence]] converts these files to matching TypeScript files in [tests/Obsidian/\_\_test_data\_\_](https://github.com/obsidian-tasks-group/obsidian-tasks/tree/main/tests/Obsidian/__test_data__).
16+
2. The process described in [[#Test data creation sequence]] converts these files to matching JSON files in [tests/Obsidian/\_\_test_data\_\_](https://github.com/obsidian-tasks-group/obsidian-tasks/tree/main/tests/Obsidian/__test_data__).
1717
3. So far the files that use this mechanism are [tests/Obsidian/Cache.test.ts](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/tests/Obsidian/Cache.test.ts) and [tests/Scripting/TasksFile.test.ts](https://github.com/obsidian-tasks-group/obsidian-tasks/blob/main/tests/Scripting/TasksFile.test.ts). Refer to these files for examples.
1818

1919
## Test data creation sequence
2020

21-
If using this on an Obsidian version newer than the one in saved `tests/Obsidian/__test_data__/*.ts`, go to Settings → Files and links → Advanced → Rebuild vault cache.
21+
If using this on an Obsidian version newer than the one in saved `tests/Obsidian/__test_data__/*.json`, go to Settings → Files and links → Advanced → Rebuild vault cache.
2222

2323
- Create a sample markdown file in Tasks demo vault (root/Test Data/) with the simplest content to represent your test case. Choose a meaningful file name in snake case. See example in `Test Data/one_task.md`.
2424
- There is a Templater template that may help with creating a new file, for single-tasks cases: `resources/sample_vaults/Tasks-Demo/_meta/templates/Test Data file.md`.
2525
- Open any other note in the vault, just so that Templater will run.
2626
- The Templater plugin requires a note to be open. The script won't edit the file, so it doesn't matter which file you have open.
2727
- Run the command `Templater: Insert _meta/templates/convert_test_data_markdown_to_js.md`.
2828
- Or type the short-cut `Ctrl + Cmd + Alt + T` / `Ctrl + Ctrl + Alt + T`.
29-
- This will convert all the files `root/Test Data/*.md` to test functions in `tests/Obsidian/__test_data__/*.ts`.
30-
- Run `yarn lint:test-data` to standardise the formatting in the generated TypeScript files.
29+
- This will convert all the files `root/Test Data/*.md` to test functions in `tests/Obsidian/__test_data__/*.json`.
3130
- Use the data in the test with `readTasksFromSimulatedFile()`, the argument is the constant you created in the previous step.
3231
- Remember to commit the markdown file in the demo vault and the file with the simulated data.
33-
34-
> TODO: Make the order of values in the generated code stable.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"build:dev": "node esbuild.config.mjs development",
1313
"lint": "eslint ./src --fix && eslint ./tests --fix && tsc --noEmit --pretty && svelte-check",
1414
"lint:markdown": "markdownlint-cli2 --fix \"**/*.md\" \"#contributing/_meta\" \"#docs/_meta\" \"#docs-snippets\" \"#node_modules\" \"#tests\" \"#resources/sample_vaults/Tasks-Demo/_meta/templates\" \"#resources/sample_vaults/Tasks-Demo/Test Data\" \"#resources/sample_vaults/Tasks-Demo/Manual Testing/Smoke test Kanban Integration.md\" ",
15-
"lint:test-data": "eslint ./tests/Obsidian/__test_data__ --fix",
1615
"test": "jest --ci",
1716
"test:dev": "jest --watch",
1817
"deploy:local": "pwsh -ExecutionPolicy Unrestricted -NoProfile -File ./scripts/Test-TasksInLocalObsidian.ps1",

resources/sample_vaults/Tasks-Demo/_meta/templater_scripts/convert_test_data_markdown_to_js.js

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const fs = require('node:fs');
2-
const util = require('util');
2+
const path = require('node:path');
33

44
const vault = app.vault;
55

@@ -10,20 +10,18 @@ async function getMarkdownFiles() {
1010
}
1111

1212
function getBasename(filePath) {
13-
return filePath.split('/')[1].replace('.md', '');
13+
return path.basename(filePath, '.md');
1414
}
1515

1616
function getOutputFilePath(outputFile) {
1717
const rootOfVault = vault.adapter.getBasePath();
18-
return rootOfVault + '/../../../tests/Obsidian/' + outputFile;
18+
return path.join(rootOfVault, '../../../tests/Obsidian', outputFile);
1919
}
2020

2121
function writeFile(testSourceFile, content) {
2222
fs.writeFile(testSourceFile, content, (err) => {
2323
if (err) {
2424
console.error(err);
25-
} else {
26-
// file written successfully
2725
}
2826
});
2927
}
@@ -32,6 +30,24 @@ function showNotice(message) {
3230
new Notice(message);
3331
}
3432

33+
/**
34+
* Recursively sorts an object's keys in alphabetical order.
35+
*/
36+
function sortObjectKeys(obj) {
37+
if (Array.isArray(obj)) {
38+
return obj.map(sortObjectKeys);
39+
}
40+
if (obj && typeof obj === 'object') {
41+
return Object.keys(obj)
42+
.sort()
43+
.reduce((acc, key) => {
44+
acc[key] = sortObjectKeys(obj[key]);
45+
return acc;
46+
}, {});
47+
}
48+
return obj;
49+
}
50+
3551
async function convertMarkdownFileToTestFunction(filePath, tp) {
3652
const tFile = vault.getAbstractFileByPath(filePath);
3753

@@ -54,18 +70,18 @@ async function convertMarkdownFileToTestFunction(filePath, tp) {
5470
return '';
5571
}
5672

57-
const testSourceFile = getOutputFilePath('__test_data__/' + filename + '.ts');
73+
const testSourceFile = getOutputFilePath(`__test_data__/${filename}.json`);
5874

59-
const options = { depth: null, compact: false };
60-
const dataAsJSSource = util.inspect(data, options);
61-
const content = `export const ${filename} = ${dataAsJSSource};`;
75+
// Sort keys in the data object to ensure stable order
76+
const sortedData = sortObjectKeys(data);
77+
const content = JSON.stringify(sortedData, null, 2);
6278
writeFile(testSourceFile, content);
6379
}
6480

6581
async function writeListOfAllTestFunctions(files) {
6682
const basenames = files.map((file) => getBasename(file));
6783

68-
const imports = basenames.map((filename) => `import { ${filename} } from './__test_data__/${filename}';`);
84+
const imports = basenames.map((filename) => `import ${filename} from './__test_data__/${filename}.json';`);
6985
const functions = basenames.map((filename) => ` ${filename},`);
7086

7187
const content = `// DO NOT EDIT!
@@ -93,7 +109,7 @@ async function export_files(tp) {
93109

94110
await writeListOfAllTestFunctions(markdownFiles);
95111

96-
showNotice('Success - now run "yarn lint:test-data" to format the generated files.');
112+
showNotice('Success.');
97113
return '';
98114
}
99115

tests/Obsidian/AllCacheSampleData.ts

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,68 @@
11
// DO NOT EDIT!
22
// This file is machine-generated in the test vault, by convert_test_data_markdown_to_js.js.
33

4-
import { blockquote } from './__test_data__/blockquote';
5-
import { callout } from './__test_data__/callout';
6-
import { callout_custom } from './__test_data__/callout_custom';
7-
import { callout_labelled } from './__test_data__/callout_labelled';
8-
import { callouts_nested_issue_2890_labelled } from './__test_data__/callouts_nested_issue_2890_labelled';
9-
import { callouts_nested_issue_2890_unlabelled } from './__test_data__/callouts_nested_issue_2890_unlabelled';
10-
import { comments_html_style } from './__test_data__/comments_html_style';
11-
import { comments_markdown_style } from './__test_data__/comments_markdown_style';
12-
import { docs_sample_for_task_properties_reference } from './__test_data__/docs_sample_for_task_properties_reference';
13-
import { empty_yaml } from './__test_data__/empty_yaml';
14-
import { example_kanban } from './__test_data__/example_kanban';
15-
import { inheritance_1parent1child } from './__test_data__/inheritance_1parent1child';
16-
import { inheritance_1parent1child1newroot_after_header } from './__test_data__/inheritance_1parent1child1newroot_after_header';
17-
import { inheritance_1parent1child1sibling_emptystring } from './__test_data__/inheritance_1parent1child1sibling_emptystring';
18-
import { inheritance_1parent2children } from './__test_data__/inheritance_1parent2children';
19-
import { inheritance_1parent2children1grandchild } from './__test_data__/inheritance_1parent2children1grandchild';
20-
import { inheritance_1parent2children1sibling } from './__test_data__/inheritance_1parent2children1sibling';
21-
import { inheritance_1parent2children2grandchildren } from './__test_data__/inheritance_1parent2children2grandchildren';
22-
import { inheritance_1parent2children2grandchildren1sibling } from './__test_data__/inheritance_1parent2children2grandchildren1sibling';
23-
import { inheritance_1parent2children2grandchildren1sibling_start_with_heading } from './__test_data__/inheritance_1parent2children2grandchildren1sibling_start_with_heading';
24-
import { inheritance_2roots_listitem_listitem_task } from './__test_data__/inheritance_2roots_listitem_listitem_task';
25-
import { inheritance_2siblings } from './__test_data__/inheritance_2siblings';
26-
import { inheritance_listitem_listitem_task } from './__test_data__/inheritance_listitem_listitem_task';
27-
import { inheritance_listitem_task } from './__test_data__/inheritance_listitem_task';
28-
import { inheritance_listitem_task_siblings } from './__test_data__/inheritance_listitem_task_siblings';
29-
import { inheritance_rendering_sample } from './__test_data__/inheritance_rendering_sample';
30-
import { inheritance_task_2listitem_3task } from './__test_data__/inheritance_task_2listitem_3task';
31-
import { inheritance_task_listitem } from './__test_data__/inheritance_task_listitem';
32-
import { inheritance_task_listitem_mixed_grandchildren } from './__test_data__/inheritance_task_listitem_mixed_grandchildren';
33-
import { inheritance_task_listitem_task } from './__test_data__/inheritance_task_listitem_task';
34-
import { inheritance_task_mixed_children } from './__test_data__/inheritance_task_mixed_children';
35-
import { jason_properties } from './__test_data__/jason_properties';
36-
import { link_in_file_body } from './__test_data__/link_in_file_body';
37-
import { link_in_file_body_with_custom_display_text } from './__test_data__/link_in_file_body_with_custom_display_text';
38-
import { link_in_heading } from './__test_data__/link_in_heading';
39-
import { link_in_yaml } from './__test_data__/link_in_yaml';
40-
import { link_is_broken } from './__test_data__/link_is_broken';
41-
import { list_statuses } from './__test_data__/list_statuses';
42-
import { list_styles } from './__test_data__/list_styles';
43-
import { multi_line_task_and_list_item } from './__test_data__/multi_line_task_and_list_item';
44-
import { multiple_headings } from './__test_data__/multiple_headings';
45-
import { no_heading } from './__test_data__/no_heading';
46-
import { no_yaml } from './__test_data__/no_yaml';
47-
import { non_tasks } from './__test_data__/non_tasks';
48-
import { one_task } from './__test_data__/one_task';
49-
import { yaml_1_alias } from './__test_data__/yaml_1_alias';
50-
import { yaml_2_aliases } from './__test_data__/yaml_2_aliases';
51-
import { yaml_all_property_types_empty } from './__test_data__/yaml_all_property_types_empty';
52-
import { yaml_all_property_types_populated } from './__test_data__/yaml_all_property_types_populated';
53-
import { yaml_capitalised_property_name } from './__test_data__/yaml_capitalised_property_name';
54-
import { yaml_complex_example } from './__test_data__/yaml_complex_example';
55-
import { yaml_complex_example_standardised } from './__test_data__/yaml_complex_example_standardised';
56-
import { yaml_custom_number_property } from './__test_data__/yaml_custom_number_property';
57-
import { yaml_tags_field_added_by_obsidian_but_not_populated } from './__test_data__/yaml_tags_field_added_by_obsidian_but_not_populated';
58-
import { yaml_tags_had_value_then_was_emptied_by_obsidian } from './__test_data__/yaml_tags_had_value_then_was_emptied_by_obsidian';
59-
import { yaml_tags_has_multiple_values } from './__test_data__/yaml_tags_has_multiple_values';
60-
import { yaml_tags_is_empty } from './__test_data__/yaml_tags_is_empty';
61-
import { yaml_tags_is_empty_list } from './__test_data__/yaml_tags_is_empty_list';
62-
import { yaml_tags_with_one_value_on_new_line } from './__test_data__/yaml_tags_with_one_value_on_new_line';
63-
import { yaml_tags_with_one_value_on_single_line } from './__test_data__/yaml_tags_with_one_value_on_single_line';
64-
import { yaml_tags_with_two_values_on_one_line } from './__test_data__/yaml_tags_with_two_values_on_one_line';
65-
import { yaml_tags_with_two_values_on_two_lines } from './__test_data__/yaml_tags_with_two_values_on_two_lines';
4+
import blockquote from './__test_data__/blockquote.json';
5+
import callout from './__test_data__/callout.json';
6+
import callout_custom from './__test_data__/callout_custom.json';
7+
import callout_labelled from './__test_data__/callout_labelled.json';
8+
import callouts_nested_issue_2890_labelled from './__test_data__/callouts_nested_issue_2890_labelled.json';
9+
import callouts_nested_issue_2890_unlabelled from './__test_data__/callouts_nested_issue_2890_unlabelled.json';
10+
import comments_html_style from './__test_data__/comments_html_style.json';
11+
import comments_markdown_style from './__test_data__/comments_markdown_style.json';
12+
import docs_sample_for_task_properties_reference from './__test_data__/docs_sample_for_task_properties_reference.json';
13+
import empty_yaml from './__test_data__/empty_yaml.json';
14+
import example_kanban from './__test_data__/example_kanban.json';
15+
import inheritance_1parent1child from './__test_data__/inheritance_1parent1child.json';
16+
import inheritance_1parent1child1newroot_after_header from './__test_data__/inheritance_1parent1child1newroot_after_header.json';
17+
import inheritance_1parent1child1sibling_emptystring from './__test_data__/inheritance_1parent1child1sibling_emptystring.json';
18+
import inheritance_1parent2children from './__test_data__/inheritance_1parent2children.json';
19+
import inheritance_1parent2children1grandchild from './__test_data__/inheritance_1parent2children1grandchild.json';
20+
import inheritance_1parent2children1sibling from './__test_data__/inheritance_1parent2children1sibling.json';
21+
import inheritance_1parent2children2grandchildren from './__test_data__/inheritance_1parent2children2grandchildren.json';
22+
import inheritance_1parent2children2grandchildren1sibling from './__test_data__/inheritance_1parent2children2grandchildren1sibling.json';
23+
import inheritance_1parent2children2grandchildren1sibling_start_with_heading from './__test_data__/inheritance_1parent2children2grandchildren1sibling_start_with_heading.json';
24+
import inheritance_2roots_listitem_listitem_task from './__test_data__/inheritance_2roots_listitem_listitem_task.json';
25+
import inheritance_2siblings from './__test_data__/inheritance_2siblings.json';
26+
import inheritance_listitem_listitem_task from './__test_data__/inheritance_listitem_listitem_task.json';
27+
import inheritance_listitem_task from './__test_data__/inheritance_listitem_task.json';
28+
import inheritance_listitem_task_siblings from './__test_data__/inheritance_listitem_task_siblings.json';
29+
import inheritance_rendering_sample from './__test_data__/inheritance_rendering_sample.json';
30+
import inheritance_task_2listitem_3task from './__test_data__/inheritance_task_2listitem_3task.json';
31+
import inheritance_task_listitem from './__test_data__/inheritance_task_listitem.json';
32+
import inheritance_task_listitem_mixed_grandchildren from './__test_data__/inheritance_task_listitem_mixed_grandchildren.json';
33+
import inheritance_task_listitem_task from './__test_data__/inheritance_task_listitem_task.json';
34+
import inheritance_task_mixed_children from './__test_data__/inheritance_task_mixed_children.json';
35+
import jason_properties from './__test_data__/jason_properties.json';
36+
import link_in_file_body from './__test_data__/link_in_file_body.json';
37+
import link_in_file_body_with_custom_display_text from './__test_data__/link_in_file_body_with_custom_display_text.json';
38+
import link_in_heading from './__test_data__/link_in_heading.json';
39+
import link_in_yaml from './__test_data__/link_in_yaml.json';
40+
import link_is_broken from './__test_data__/link_is_broken.json';
41+
import list_statuses from './__test_data__/list_statuses.json';
42+
import list_styles from './__test_data__/list_styles.json';
43+
import multi_line_task_and_list_item from './__test_data__/multi_line_task_and_list_item.json';
44+
import multiple_headings from './__test_data__/multiple_headings.json';
45+
import no_heading from './__test_data__/no_heading.json';
46+
import no_yaml from './__test_data__/no_yaml.json';
47+
import non_tasks from './__test_data__/non_tasks.json';
48+
import one_task from './__test_data__/one_task.json';
49+
import yaml_1_alias from './__test_data__/yaml_1_alias.json';
50+
import yaml_2_aliases from './__test_data__/yaml_2_aliases.json';
51+
import yaml_all_property_types_empty from './__test_data__/yaml_all_property_types_empty.json';
52+
import yaml_all_property_types_populated from './__test_data__/yaml_all_property_types_populated.json';
53+
import yaml_capitalised_property_name from './__test_data__/yaml_capitalised_property_name.json';
54+
import yaml_complex_example from './__test_data__/yaml_complex_example.json';
55+
import yaml_complex_example_standardised from './__test_data__/yaml_complex_example_standardised.json';
56+
import yaml_custom_number_property from './__test_data__/yaml_custom_number_property.json';
57+
import yaml_tags_field_added_by_obsidian_but_not_populated from './__test_data__/yaml_tags_field_added_by_obsidian_but_not_populated.json';
58+
import yaml_tags_had_value_then_was_emptied_by_obsidian from './__test_data__/yaml_tags_had_value_then_was_emptied_by_obsidian.json';
59+
import yaml_tags_has_multiple_values from './__test_data__/yaml_tags_has_multiple_values.json';
60+
import yaml_tags_is_empty from './__test_data__/yaml_tags_is_empty.json';
61+
import yaml_tags_is_empty_list from './__test_data__/yaml_tags_is_empty_list.json';
62+
import yaml_tags_with_one_value_on_new_line from './__test_data__/yaml_tags_with_one_value_on_new_line.json';
63+
import yaml_tags_with_one_value_on_single_line from './__test_data__/yaml_tags_with_one_value_on_single_line.json';
64+
import yaml_tags_with_two_values_on_one_line from './__test_data__/yaml_tags_with_two_values_on_one_line.json';
65+
import yaml_tags_with_two_values_on_two_lines from './__test_data__/yaml_tags_with_two_values_on_two_lines.json';
6666

6767
export function allCacheSampleData() {
6868
return [

0 commit comments

Comments
 (0)