@diplodoc/cli-tests 0.0.0-rc-fix-lint-202505271406 → 0.0.0-rc-toc-translation-202506181609
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/e2e/__snapshots__/include-toc.test.ts.snap +98 -106
- package/e2e/__snapshots__/load-custom-resources.spec.ts.snap +66 -56
- package/e2e/__snapshots__/metadata.spec.ts.snap +19 -14
- package/e2e/__snapshots__/plugin-corner-cases.spec.ts.snap +0 -0
- package/e2e/__snapshots__/regression.test.ts.snap +764 -760
- package/e2e/__snapshots__/restricted-access.test.ts.snap +234 -0
- package/e2e/__snapshots__/rtl.spec.ts.snap +57 -47
- package/e2e/__snapshots__/translation.spec.ts.snap +1296 -110
- package/e2e/errors.spec.ts +37 -0
- package/e2e/restricted-access.test.ts +21 -0
- package/e2e/translation.spec.ts +14 -3
- package/fixtures/cliAdapter.ts +39 -20
- package/fixtures/runners/binary.ts +21 -3
- package/fixtures/runners/index.ts +3 -1
- package/fixtures/runners/source.ts +5 -5
- package/fixtures/runners/types.ts +7 -1
- package/fixtures/utils/file.ts +3 -3
- package/fixtures/utils/test.ts +6 -1
- package/mocks/errors/unreachable-link/input/exists.md +1 -0
- package/mocks/errors/unreachable-link/input/index.md +2 -0
- package/mocks/errors/unreachable-link/input/toc.yaml +1 -0
- package/mocks/regression/input/1.md +0 -4
- package/mocks/regression/input/_assets/5_1.png +0 -0
- package/mocks/regression/input/images.md +2 -0
- package/mocks/regression/input/includes.md +1 -0
- package/mocks/restricted-access/test1/input/index.md +0 -0
- package/mocks/restricted-access/test1/input/plugins/index.md +0 -0
- package/mocks/restricted-access/test1/input/plugins/index2.md +0 -0
- package/mocks/restricted-access/test1/input/plugins/index3.md +0 -0
- package/mocks/restricted-access/test1/input/plugins/index4.md +4 -0
- package/mocks/restricted-access/test1/input/toc.yaml +28 -0
- package/mocks/restricted-access/test2/input/index.md +0 -0
- package/mocks/restricted-access/test2/input/plugins/index.md +0 -0
- package/mocks/restricted-access/test2/input/project/index.md +0 -0
- package/mocks/restricted-access/test2/input/toc.yaml +21 -0
- package/mocks/restricted-access/test3/input/a1.md +1 -0
- package/mocks/restricted-access/test3/input/folder1/a1.md +1 -0
- package/mocks/restricted-access/test3/input/folder1/folder2/a1.md +1 -0
- package/mocks/restricted-access/test3/input/folder1/folder2/toc.yaml +8 -0
- package/mocks/restricted-access/test3/input/folder1/toc.yaml +10 -0
- package/mocks/restricted-access/test3/input/index.md +0 -0
- package/mocks/restricted-access/test3/input/toc.yaml +16 -0
- package/mocks/translation/dir-files/input/.yfm +5 -0
- package/mocks/translation/dir-files/input/ru/aboba.md +1 -3
- package/mocks/translation/dir-files/input/ru/nested/a1.md +3 -0
- package/mocks/translation/dir-files/input/ru/nested/folder1/a1.md +3 -0
- package/mocks/translation/dir-files/input/ru/nested/folder1/toc-i.yaml +3 -0
- package/mocks/translation/dir-files/input/ru/nested/toc.yaml +1 -0
- package/mocks/translation/dir-files/input/ru/no-var-page.md +3 -0
- package/mocks/translation/dir-files/input/ru/to-be-excluded.md +1 -0
- package/mocks/translation/dir-files/input/ru/toc.yaml +7 -1
- package/package.json +4 -3
- package/vitest.config.ts +1 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type {Report} from '../fixtures/runners/types';
|
|
2
|
+
|
|
3
|
+
import {describe, expect, it} from 'vitest';
|
|
4
|
+
import {TestAdapter, getTestPaths} from '../fixtures';
|
|
5
|
+
|
|
6
|
+
type TestResult = {
|
|
7
|
+
md: Report;
|
|
8
|
+
html: Report;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function test(path: string, expect: Function) {
|
|
12
|
+
it(path, async () => {
|
|
13
|
+
const {inputPath, outputPath} = getTestPaths(path);
|
|
14
|
+
|
|
15
|
+
const md = await TestAdapter.build.run(inputPath, outputPath, ['-j2', '-f', 'md']);
|
|
16
|
+
const html = await TestAdapter.build.run(outputPath, outputPath + '-html', ['-j2', '-f', 'html']);
|
|
17
|
+
|
|
18
|
+
return expect({md, html});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('Errors', () => {
|
|
23
|
+
test('mocks/errors/unreachable-link', ({html}: TestResult) => {
|
|
24
|
+
expectErrors(html, [
|
|
25
|
+
'ERR index.md: 1: YFM003 / unreachable-link Link is unreachable [Context: "[Unreachable link: "exists.html"][existing file](./exists.md)"]',
|
|
26
|
+
'ERR index.md: 2: YFM003 / unreachable-link Link is unreachable [Context: "[Unreachable link: "missed.html"][missed file](./missed.md)"]'
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
function expectErrors(report: Report, errors: string[]) {
|
|
32
|
+
expect(report.code).toEqual(1);
|
|
33
|
+
|
|
34
|
+
for (const error of errors) {
|
|
35
|
+
expect(report.errors).toContain(error);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {describe, test} from 'vitest';
|
|
2
|
+
import {TestAdapter, compareDirectories, getTestPaths} from '../fixtures';
|
|
3
|
+
|
|
4
|
+
const generateFilesYamlTestTemplate = (
|
|
5
|
+
testTitle: string,
|
|
6
|
+
testRootPath: string
|
|
7
|
+
) => {
|
|
8
|
+
test(testTitle, async () => {
|
|
9
|
+
const {inputPath, outputPath} = getTestPaths(testRootPath);
|
|
10
|
+
await TestAdapter.testBuildPass(inputPath, outputPath, {md2md:true});
|
|
11
|
+
await compareDirectories(outputPath);
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
describe('Restricted access', () => {
|
|
16
|
+
generateFilesYamlTestTemplate('Simple restricted access', 'mocks/restricted-access/test1');
|
|
17
|
+
|
|
18
|
+
generateFilesYamlTestTemplate('Nested restricted access', 'mocks/restricted-access/test2');
|
|
19
|
+
|
|
20
|
+
generateFilesYamlTestTemplate('Nested toc restricted access', 'mocks/restricted-access/test3');
|
|
21
|
+
});
|
package/e2e/translation.spec.ts
CHANGED
|
@@ -6,12 +6,12 @@ const generateMapTestTemplate = (
|
|
|
6
6
|
testRootPath: string,
|
|
7
7
|
args: TranslateRunArgs,
|
|
8
8
|
) => {
|
|
9
|
-
test
|
|
9
|
+
test(testTitle, async () => {
|
|
10
10
|
const {inputPath, outputPath} = getTestPaths(testRootPath);
|
|
11
11
|
|
|
12
12
|
await TestAdapter.testTranslatePass(inputPath, outputPath, args);
|
|
13
13
|
|
|
14
|
-
await compareDirectories(outputPath
|
|
14
|
+
await compareDirectories(outputPath);
|
|
15
15
|
});
|
|
16
16
|
};
|
|
17
17
|
|
|
@@ -43,7 +43,18 @@ describe('Translate command', () => {
|
|
|
43
43
|
subcommand: 'extract',
|
|
44
44
|
source: 'ru-RU',
|
|
45
45
|
target: 'es-ES',
|
|
46
|
-
additionalArgs: '--exclude ru/
|
|
46
|
+
additionalArgs: '--exclude ru/to-be-excluded.md',
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
generateMapTestTemplate(
|
|
51
|
+
'filter files on extract with --strict-vars options',
|
|
52
|
+
'mocks/translation/dir-files',
|
|
53
|
+
{
|
|
54
|
+
subcommand: 'extract',
|
|
55
|
+
source: 'ru-RU',
|
|
56
|
+
target: 'es-ES',
|
|
57
|
+
additionalArgs: '--strict-vars',
|
|
47
58
|
},
|
|
48
59
|
);
|
|
49
60
|
|
package/fixtures/cliAdapter.ts
CHANGED
|
@@ -14,8 +14,30 @@ export interface TranslateRunArgs {
|
|
|
14
14
|
additionalArgs?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
class Build {
|
|
18
|
+
private readonly runner: Runner;
|
|
19
|
+
|
|
20
|
+
constructor(runner: Runner) {
|
|
21
|
+
this.runner = runner;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
run(input: string, output: string, args: string[]) {
|
|
25
|
+
return this.runner.runYfmDocs([
|
|
26
|
+
'--input',
|
|
27
|
+
input,
|
|
28
|
+
'--output',
|
|
29
|
+
output,
|
|
30
|
+
'--quiet',
|
|
31
|
+
'--allowHTML',
|
|
32
|
+
...args,
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
17
37
|
export class CliTestAdapter {
|
|
18
|
-
|
|
38
|
+
readonly runner: Runner = createRunner();
|
|
39
|
+
|
|
40
|
+
readonly build = new Build(this.runner);
|
|
19
41
|
|
|
20
42
|
async testBuildPass(
|
|
21
43
|
inputPath: string,
|
|
@@ -23,30 +45,27 @@ export class CliTestAdapter {
|
|
|
23
45
|
{md2md = true, md2html = true, args = ''}: BuildRunArgs = {},
|
|
24
46
|
): Promise<void> {
|
|
25
47
|
await cleanupDirectory(outputPath);
|
|
48
|
+
await cleanupDirectory(`${outputPath}-md`);
|
|
49
|
+
await cleanupDirectory(`${outputPath}-html`);
|
|
26
50
|
|
|
27
|
-
const baseArgs =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
'--quiet',
|
|
31
|
-
'--allowHTML',
|
|
32
|
-
...args.split(' ').filter(Boolean),
|
|
33
|
-
];
|
|
51
|
+
const baseArgs = args.split(' ').filter(Boolean);
|
|
52
|
+
|
|
53
|
+
const tasks = [];
|
|
34
54
|
|
|
35
55
|
if (md2md && md2html) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
await this.runner.runYfmDocs([...baseArgs, '--output', outputPath, '-f', 'md']);
|
|
39
|
-
await this.runner.runYfmDocs([
|
|
40
|
-
...baseArgs,
|
|
41
|
-
'--output',
|
|
42
|
-
`${outputPath}-html`,
|
|
43
|
-
'-f',
|
|
44
|
-
'html',
|
|
45
|
-
]);
|
|
56
|
+
tasks.push(() => this.build.run(inputPath, outputPath,[...baseArgs, '-f', 'md']));
|
|
57
|
+
tasks.push(() => this.build.run(inputPath, `${outputPath}-html`, [...baseArgs, '-f', 'html']));
|
|
46
58
|
} else if (md2md) {
|
|
47
|
-
|
|
59
|
+
tasks.push(() => this.build.run(inputPath, outputPath, [...baseArgs, '-f', 'md']));
|
|
48
60
|
} else {
|
|
49
|
-
|
|
61
|
+
tasks.push(() => this.build.run(inputPath, outputPath, [...baseArgs, '-f', 'html']));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (const task of tasks) {
|
|
65
|
+
const report = await task();
|
|
66
|
+
if (report.code > 0) {
|
|
67
|
+
throw report;
|
|
68
|
+
}
|
|
50
69
|
}
|
|
51
70
|
}
|
|
52
71
|
|
|
@@ -9,9 +9,27 @@ export class BinaryRunner implements Runner {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
async runYfmDocs(argv: string[]) {
|
|
12
|
-
const {
|
|
12
|
+
const {stderr, exitCode} = await execa(this.binaryPath, argv, {all: true, reject: false});
|
|
13
|
+
const report = {
|
|
14
|
+
code: exitCode || 0,
|
|
15
|
+
warns: fillLog(/^WARN/, stderr),
|
|
16
|
+
errors: fillLog(/^ERR/, stderr),
|
|
17
|
+
};
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
const restLog = fillLog(/^(?!INFO|WARN|ERR)/, stderr);
|
|
20
|
+
if (restLog.length) {
|
|
21
|
+
for (const line of restLog) {
|
|
22
|
+
console.log(line);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return report;
|
|
16
27
|
}
|
|
17
28
|
}
|
|
29
|
+
|
|
30
|
+
function fillLog(filter: RegExp, source: string) {
|
|
31
|
+
return source.split('\n')
|
|
32
|
+
.filter((line) => line.match(filter))
|
|
33
|
+
.map((line) => line.trim())
|
|
34
|
+
.filter(Boolean);
|
|
35
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import {resolve} from 'node:path';
|
|
2
|
+
|
|
1
3
|
import {SourceRunner} from './source';
|
|
2
4
|
import {BinaryRunner} from './binary';
|
|
3
5
|
import {Runner} from './types';
|
|
@@ -5,7 +7,7 @@ import {Runner} from './types';
|
|
|
5
7
|
export {Runner};
|
|
6
8
|
|
|
7
9
|
export function createRunner(): Runner {
|
|
8
|
-
const binaryPath = process.env.DIPLODOC_BINARY_PATH;
|
|
10
|
+
const binaryPath = process.env.DIPLODOC_BINARY_PATH || resolve(__dirname, '../../../build/index.js');
|
|
9
11
|
|
|
10
12
|
if (binaryPath) {
|
|
11
13
|
return new BinaryRunner(binaryPath);
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import type {Report} from './types';
|
|
2
|
+
|
|
1
3
|
export class SourceRunner {
|
|
2
4
|
readonly MODULE_PATH = require.resolve('../../../');
|
|
3
5
|
|
|
4
|
-
async runYfmDocs(argv: string[])
|
|
6
|
+
async runYfmDocs(argv: string[]) {
|
|
5
7
|
const {run} = await import(this.MODULE_PATH);
|
|
6
8
|
|
|
7
9
|
const baseArgs = ['node', this.MODULE_PATH, ...argv];
|
|
8
10
|
|
|
9
|
-
const
|
|
11
|
+
const report = await run(baseArgs) as Report;
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
throw new Error(`CLI exited with code ${exitCode}`);
|
|
13
|
-
}
|
|
13
|
+
return report;
|
|
14
14
|
}
|
|
15
15
|
}
|
package/fixtures/utils/file.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {readFileSync} from 'node:fs';
|
|
2
2
|
import {join, resolve} from 'node:path';
|
|
3
3
|
import {glob} from 'glob';
|
|
4
|
-
import {bundleless, platformless} from './test';
|
|
4
|
+
import {bundleless, hashless, platformless} from './test';
|
|
5
5
|
import {expect} from 'vitest';
|
|
6
6
|
import {$} from 'execa';
|
|
7
7
|
|
|
@@ -23,12 +23,12 @@ export async function compareDirectories(outputPath: string, ignoreFileContent =
|
|
|
23
23
|
})
|
|
24
24
|
).sort();
|
|
25
25
|
|
|
26
|
-
expect(bundleless(JSON.stringify(filesFromOutput, null, 2))).toMatchSnapshot('filelist');
|
|
26
|
+
expect(hashless(bundleless(JSON.stringify(filesFromOutput, null, 2)))).toMatchSnapshot('filelist');
|
|
27
27
|
|
|
28
28
|
if (!ignoreFileContent) {
|
|
29
29
|
filesFromOutput.filter(uselessFile).forEach((filePath) => {
|
|
30
30
|
const content = getFileContent(resolve(outputPath, filePath));
|
|
31
|
-
expect(content).toMatchSnapshot(
|
|
31
|
+
expect(content).toMatchSnapshot();
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
}
|
package/fixtures/utils/test.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import {readFileSync} from 'node:fs';
|
|
2
2
|
|
|
3
3
|
export function platformless(text: string): string {
|
|
4
|
-
return text
|
|
4
|
+
return hashless(text)
|
|
5
5
|
.replace(/\r\n/g, '\n')
|
|
6
6
|
.replace(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/g, 'UUID')
|
|
7
7
|
.replace(/(content"?[:=]{1}[" ]{1}Diplodoc.*? )v\d+\.\d+\.\d+(?:-[\w-]+)?/g, `$1vDIPLODOC-VERSION`)
|
|
8
8
|
.replace(/(\\(?![/"'])){1,2}/g, '/');
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
export function hashless(text: string): string {
|
|
12
|
+
return text
|
|
13
|
+
.replace(/-[a-z0-9]{12}\./g, '-hash.')
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
export function bundleless(text: string): string {
|
|
12
17
|
const assets = require('@diplodoc/client/manifest') as Record<string, Record<string, string[]>>;
|
|
13
18
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
File exists but not attached to toc
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
href: index.md
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
title: Yandex Flavored Markdown
|
|
2
|
+
items:
|
|
3
|
+
- name: Yandex Flavored Markdown
|
|
4
|
+
href: index.md
|
|
5
|
+
restricted-access: admin
|
|
6
|
+
- name: Plugins
|
|
7
|
+
items:
|
|
8
|
+
- name: Overview
|
|
9
|
+
href: plugins/index.md
|
|
10
|
+
restricted-access:
|
|
11
|
+
- admin
|
|
12
|
+
- name: Plugins 2
|
|
13
|
+
restricted-access: admin
|
|
14
|
+
items:
|
|
15
|
+
- name: Overview 2
|
|
16
|
+
href: plugins/index2.md
|
|
17
|
+
restricted-access:
|
|
18
|
+
- admin
|
|
19
|
+
- user
|
|
20
|
+
- name: Overview 3
|
|
21
|
+
href: plugins/index3.md
|
|
22
|
+
restricted-access:
|
|
23
|
+
- admin
|
|
24
|
+
- name: Overview 4
|
|
25
|
+
href: plugins/index4.md
|
|
26
|
+
restricted-access:
|
|
27
|
+
- admin
|
|
28
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
title: Yandex Flavored Markdown
|
|
2
|
+
items:
|
|
3
|
+
- name: Plugins
|
|
4
|
+
restricted-access:
|
|
5
|
+
- admin
|
|
6
|
+
- manager
|
|
7
|
+
items:
|
|
8
|
+
- name: Overview
|
|
9
|
+
href: plugins/index.md
|
|
10
|
+
restricted-access:
|
|
11
|
+
- userA
|
|
12
|
+
- userB
|
|
13
|
+
- name: Organizing a YFM project
|
|
14
|
+
items:
|
|
15
|
+
- name: Overview
|
|
16
|
+
href: project/index.md
|
|
17
|
+
restricted-access:
|
|
18
|
+
- userA
|
|
19
|
+
- userB
|
|
20
|
+
|
|
21
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This is the /a1.md file content.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This is the /folder1/a1.md file content.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This is the /folder1/folder1/a1.md file content.
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
## Excluded title
|
|
@@ -4,4 +4,10 @@ items:
|
|
|
4
4
|
- name: Aboba
|
|
5
5
|
href: aboba.md
|
|
6
6
|
- name: Не переводить
|
|
7
|
-
|
|
7
|
+
when: skip == 'prod'
|
|
8
|
+
href: _no-translate/exclude.md
|
|
9
|
+
- name: Нет переменной в vars
|
|
10
|
+
when: novar == 'test'
|
|
11
|
+
href: no-var-page.md
|
|
12
|
+
- name: exclude-test
|
|
13
|
+
href: to-be-excluded.md
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diplodoc/cli-tests",
|
|
3
|
-
"version": "0.0.0-rc-
|
|
3
|
+
"version": "0.0.0-rc-toc-translation-202506181609",
|
|
4
4
|
"bin": {
|
|
5
5
|
"diplodoc-cli-test": "bin.mjs"
|
|
6
6
|
},
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "false",
|
|
20
|
-
"test": "vitest run"
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:update": "vitest -u"
|
|
21
22
|
},
|
|
22
23
|
"publishConfig": {
|
|
23
24
|
"access": "public"
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
"@diplodoc/cli": "file:.."
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
|
-
"@diplodoc/client": "^3.3
|
|
30
|
+
"@diplodoc/client": "^3.6.3",
|
|
30
31
|
"@types/node": "18.x",
|
|
31
32
|
"@vitest/coverage-istanbul": "^3.1.1",
|
|
32
33
|
"@vitest/coverage-v8": "^3.1.1",
|
package/vitest.config.ts
CHANGED
|
@@ -17,10 +17,9 @@ export default defineConfig({
|
|
|
17
17
|
environment: 'node',
|
|
18
18
|
include: [
|
|
19
19
|
'e2e/**/*.{test,spec}.ts',
|
|
20
|
-
'units/**/*.{test,spec}.ts',
|
|
21
20
|
...resolvedTestPaths.map((path) => `${path}/**/*.{test,spec}.ts`),
|
|
22
21
|
],
|
|
23
|
-
exclude: ['node_modules'
|
|
22
|
+
exclude: ['node_modules'],
|
|
24
23
|
coverage: {
|
|
25
24
|
enabled: false,
|
|
26
25
|
},
|