Skip to content

Commit 5f12539

Browse files
authored
test: add characterization tests for DocsMarkedRenderer (#19413)
These tests are meant to simply document and verify the existing behavior of the DocsMarkedRenderer. They aren't necessarily meant to be a good example of unit testing best-practices. A characterization test "is a means to describe (characterize) the actual behavior of an existing piece of software, and therefore protect existing behavior of legacy code against unintended changes via automated testing." https://en.wikipedia.org/wiki/Characterization_test
1 parent 8dbee4e commit 5f12539

File tree

3 files changed

+134
-3
lines changed

3 files changed

+134
-3
lines changed

tools/markdown-to-html/BUILD.bazel

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
2-
load("//tools:defaults.bzl", "ts_library")
2+
load("//tools:defaults.bzl", "jasmine_node_test", "ts_library")
33

44
package(default_visibility = ["//visibility:public"])
55

66
ts_library(
77
name = "transform-markdown",
8-
srcs = glob(["**/*.ts"]),
8+
srcs = glob(
9+
["**/*.ts"],
10+
exclude = [
11+
"*.spec.ts",
12+
],
13+
),
914
tsconfig = ":tsconfig.json",
1015
deps = [
1116
"//tools/highlight-files:sources",
@@ -23,3 +28,26 @@ nodejs_binary(
2328
],
2429
entry_point = ":transform-markdown.ts",
2530
)
31+
32+
ts_library(
33+
name = "unit_test_lib",
34+
testonly = True,
35+
srcs = glob(
36+
["*.spec.ts"],
37+
),
38+
tsconfig = ":tsconfig.json",
39+
visibility = ["//visibility:private"],
40+
deps = [
41+
":transform-markdown",
42+
"@npm//@types/jasmine",
43+
"@npm//@types/node",
44+
"@npm//marked",
45+
"@npm//typescript",
46+
],
47+
)
48+
49+
jasmine_node_test(
50+
name = "unit_tests",
51+
srcs = [":unit_test_lib"],
52+
visibility = ["//visibility:private"],
53+
)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import {DocsMarkdownRenderer} from './docs-marked-renderer';
2+
3+
describe('DocsMarkdownRenderer', () => {
4+
let renderer: DocsMarkdownRenderer;
5+
beforeEach(() => {
6+
renderer = new DocsMarkdownRenderer();
7+
});
8+
9+
it('generates regular headings for h1 and h2', () => {
10+
expect(renderer.heading('a', 1, 'ignored')).toEqual('<h1>a</h1>');
11+
expect(renderer.heading('b', 2, 'ignored')).toEqual('<h2>b</h2>');
12+
});
13+
14+
it('creates header link for h3 and h4 headings', () => {
15+
const heading3 = renderer.heading('heading text', 3, 'link-id');
16+
expectEqualIgnoreLeadingWhitespace(heading3, `
17+
<h3 id="link-id" class="docs-header-link">
18+
<span header-link="link-id"></span>
19+
heading text
20+
</h3>
21+
`);
22+
const heading4 = renderer.heading('heading text', 4, 'second-link-id');
23+
expectEqualIgnoreLeadingWhitespace(heading4, `
24+
<h4 id="second-link-id" class="docs-header-link">
25+
<span header-link="second-link-id"></span>
26+
heading text
27+
</h4>
28+
`);
29+
});
30+
31+
it('handles duplicate ids for headings', () => {
32+
expect(renderer.heading('first', 3, 'id')).toContain('id="id"');
33+
expect(renderer.heading('second', 3, 'id')).toContain('id="id-1"');
34+
});
35+
36+
it('generates links', () => {
37+
expect(renderer.link('something', 'some title', 'some text'))
38+
.toEqual('<a href="guide/something" title="some title">some text</a>');
39+
expect(renderer.link('guide/something', 'some title', 'some text'))
40+
.toEqual('<a href="guide/something" title="some title">some text</a>');
41+
expect(renderer.link('#some-hash', 'some title', 'some text'))
42+
.toEqual('<a href="#some-hash" title="some title">some text</a>');
43+
expect(renderer.link('http://google.com', 'some title', 'some text'))
44+
.toEqual('<a href="http://google.com" title="some title">some text</a>');
45+
});
46+
47+
it('generates html using new API', () => {
48+
const result = renderer.html(`<!-- example(
49+
{
50+
"example": "exampleName",
51+
"file": "example-html.html",
52+
"region": "some-region",
53+
}
54+
) -->`);
55+
56+
// TODO(annieyw): I think DocsMarkedRenderer#html needs to be fixed for the new API?
57+
expectEqualIgnoreLeadingWhitespace(result, `<div material-docs-example="
58+
{
59+
"example": "exampleName",
60+
"file": "example-html.html",
61+
"region": "some-region",
62+
}
63+
"></div>`);
64+
});
65+
66+
it('generates html using old API', () => {
67+
expect(renderer.html('<!-- example(name) -->'))
68+
.toEqual('<div material-docs-example="name"></div>');
69+
});
70+
71+
it('allows id links with matching id element', () => {
72+
let output = renderer.link('#my-id', 'link title', 'link text');
73+
output += renderer.heading('heading text', 3, 'my-id');
74+
const result = renderer.finalizeOutput(output, 'filename.html');
75+
expect(result).toEqual(jasmine.stringMatching(/<div class="docs-markdown"/));
76+
});
77+
78+
it('does not allow id links with no matching id element', () => {
79+
spyOn(console, 'error');
80+
spyOn(process, 'exit');
81+
let output = renderer.link('#my-id', 'link title', 'link text');
82+
renderer.finalizeOutput(output, 'filename.html');
83+
expect((console.error as jasmine.Spy).calls.allArgs()).toEqual([
84+
[jasmine.stringMatching(/Could not process file: filename.html.*/)],
85+
[jasmine.stringMatching(/.*Found link to "my-id". This heading does not exist./)]
86+
]);
87+
expect(process.exit).toHaveBeenCalledWith(1);
88+
});
89+
90+
function expectEqualIgnoreLeadingWhitespace(actual: string, expected: string) {
91+
expect(stripLeadingWhitespace(actual)).toEqual(stripLeadingWhitespace(expected));
92+
}
93+
94+
function stripLeadingWhitespace(s: string) {
95+
return s.replace(/^\s*/gm, '');
96+
}
97+
});

tools/markdown-to-html/tsconfig.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44
"module": "commonjs",
55
"target": "es5",
66
"sourceMap": true,
7-
"types": ["node"]
7+
"types": [
8+
"jasmine",
9+
"node"
10+
]
811
},
12+
"exclude": [
13+
"*.spec.ts",
14+
],
915
"bazelOptions": {
1016
"suppressTsconfigOverrideWarnings": true
1117
}

0 commit comments

Comments
 (0)