-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathfindForUrl.ts
More file actions
94 lines (87 loc) · 2.94 KB
/
findForUrl.ts
File metadata and controls
94 lines (87 loc) · 2.94 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
import type {ColorSchemePreference, Finding, ReducedMotionPreference} from './types.d.js'
import {AxeBuilder} from '@axe-core/playwright'
import playwright from 'playwright'
import {AuthContext} from './AuthContext.js'
import {generateScreenshots} from './generateScreenshots.js'
import {loadPlugins, invokePlugin} from './pluginManager'
import {getScansContext} from './scansContextProvider.js'
import * as core from '@actions/core'
export async function findForUrl(
url: string,
authContext?: AuthContext,
includeScreenshots: boolean = false,
reducedMotion?: ReducedMotionPreference,
colorScheme?: ColorSchemePreference,
): Promise<Finding[]> {
const browser = await playwright.chromium.launch({
headless: true,
executablePath: process.env.CI ? '/usr/bin/google-chrome' : undefined,
})
const contextOptions = {
...(authContext?.toPlaywrightBrowserContextOptions() ?? {}),
...(reducedMotion ? {reducedMotion} : {}),
...(colorScheme ? {colorScheme} : {}),
}
const context = await browser.newContext(contextOptions)
const page = await context.newPage()
await page.goto(url)
const findings: Finding[] = []
const addFinding = async (findingData: Finding) => {
let screenshotId
if (includeScreenshots) {
screenshotId = await generateScreenshots(page)
}
findings.push({...findingData, screenshotId})
}
try {
const scansContext = getScansContext()
if (scansContext.shouldRunPlugins) {
const plugins = await loadPlugins()
for (const plugin of plugins) {
if (scansContext.scansToPerform.includes(plugin.name)) {
core.info(`Running plugin: ${plugin.name}`)
await invokePlugin({
plugin,
page,
addFinding,
})
} else {
core.info(`Skipping plugin ${plugin.name} because it is not included in the 'scans' input`)
}
}
}
if (scansContext.shouldPerformAxeScan) {
await runAxeScan({page, addFinding})
}
} catch (e) {
core.error(`Error during accessibility scan: ${e}`)
}
await context.close()
await browser.close()
return findings
}
async function runAxeScan({
page,
addFinding,
}: {
page: playwright.Page
addFinding: (findingData: Finding, options?: {includeScreenshots?: boolean}) => Promise<void>
}) {
const url = page.url()
core.info(`Scanning ${url}`)
const rawFindings = await new AxeBuilder({page}).analyze()
if (rawFindings) {
for (const violation of rawFindings.violations) {
await addFinding({
scannerType: 'axe',
url,
html: violation.nodes[0].html.replace(/'/g, '''),
problemShort: violation.help.toLowerCase().replace(/'/g, '''),
problemUrl: violation.helpUrl.replace(/'/g, '''),
ruleId: violation.id,
solutionShort: violation.description.toLowerCase().replace(/'/g, '''),
solutionLong: violation.nodes[0].failureSummary?.replace(/'/g, '''),
})
}
}
}