-
Notifications
You must be signed in to change notification settings - Fork 83
Expand file tree
/
Copy pathheadings.js
More file actions
113 lines (102 loc) · 3.66 KB
/
headings.js
File metadata and controls
113 lines (102 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
const marked = require('marked')
const describeRule = require('../../test-utils/describe-rule')
/**
* Get headings from a given body of text
* @method getAllHeadingsFromMarkdownBody
* @param {String} body text content of markdown file
* @returns {Array<Object>} list of headings
*/
const getAllHeadingsFromMarkdownBody = body => {
const lexer = new marked.Lexer({})
const tokens = lexer.lex(body)
return tokens.reduce((out, token, index) => {
const { type } = token
if (type === `heading`) {
out.push({
...token,
number: index, // populate with line number, to check for ordering
})
}
return out
}, [])
}
/**
* Extract a number from a given string
* @param {String} str given string
* @returns {Number}
*/
const extractNumberFromGivenString = str => {
const match = str.match(/\d+/)[0]
return parseInt(match)
}
/**
* Check if a given array of numbers is in ascending order & starts with 1
* @param {Array<Number>} arr array of numbers to verify if they are ascending
* @returns {Boolean}
*/
const isAscendingFromOne = arr => {
return arr.every((item, index) => item === index + 1)
}
/**
* Get `text` of headings of given depth
* @param {Array<Object>} headings list of headings
* @param {Number} headingDepth given depth of heading
* @returns {Array<String>} al headings matching given depth
*/
const getHeadingOfDepth = (headings, headingDepth) => {
return headings.filter(({ depth }) => depth === headingDepth).map(({ text }) => text)
}
describeRule('headings', ruleData => {
const { body } = ruleData
const headings = getAllHeadingsFromMarkdownBody(body)
/**
* Check for `required` `h2` headings
*/
const requiredH2 = [`Applicability`, `Background`, `Examples`]
const h2Headings = getHeadingOfDepth(headings, 2)
test.each(requiredH2)('has required `h2` - `%s`', heading => {
expect(h2Headings).toContain(heading)
})
/**
* Check for `required` `h3` headings
*/
const requiredH3 = [`Assumptions`, `Accessibility Support`, `Passed`, `Failed`, `Inapplicable`]
const h3Headings = getHeadingOfDepth(headings, 3)
test.each(requiredH3)('has required `h3` - `%s`', heading => {
expect(h3Headings).toContain(heading)
})
/**
* Check all `h4` headings
*/
/**
* Test if headings have expected string
*/
const h4Headings = getHeadingOfDepth(headings, 4)
const h4PassedHeadings = h4Headings.filter(heading => heading.includes('Pass'))
const h4FailedHeadings = h4Headings.filter(heading => heading.includes('Fail'))
const h4InapplicableHeadings = h4Headings.filter(heading => heading.includes('Inapplicable'))
test.each(h4PassedHeadings)('has keyword "Passed Example" - %s', heading => {
expect(heading.includes('Passed Example')).toBe(true)
})
test.each(h4FailedHeadings)('has keyword "Failed Example" - %s', heading => {
expect(heading.includes('Failed Example')).toBe(true)
})
test.each(h4InapplicableHeadings)('has keyword "Inapplicable Example" - %s', heading => {
expect(heading.includes('Inapplicable Example')).toBe(true)
})
/**
* Test if heading indices are not duplicated
*/
const h4PassedHeadingsIndices = h4PassedHeadings.map(extractNumberFromGivenString)
const h4FailedHeadingsIndices = h4FailedHeadings.map(extractNumberFromGivenString)
const h4InapplicableHeadingsIndices = h4InapplicableHeadings.map(extractNumberFromGivenString)
test('"Passed" headings are in ascending order', () => {
expect(isAscendingFromOne(h4PassedHeadingsIndices)).toBe(true)
})
test('"Failed" headings are in ascending order', () => {
expect(isAscendingFromOne(h4FailedHeadingsIndices)).toBe(true)
})
test('"Inapplicable" headings are in ascending order', () => {
expect(isAscendingFromOne(h4InapplicableHeadingsIndices)).toBe(true)
})
})