Skip to content

Commit 95a0df4

Browse files
authored
Adds prettier and eslint (#138)
Closes #135. * Adds Prettier & ESLint * Adds new CI check for linting * Updates all current files based on linting / formatting feedback I've confirmed this still runs on an internal repo.
2 parents 91072df + 889e90b commit 95a0df4

30 files changed

+1939
-695
lines changed

.github/actions/auth/src/index.ts

Lines changed: 52 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,96 @@
1-
import type { AuthContextOutput } from "./types.d.js";
2-
import crypto from "node:crypto";
3-
import process from "node:process";
4-
import * as url from "node:url";
5-
import core from "@actions/core";
6-
import playwright from "playwright";
1+
import type {AuthContextOutput} from './types.d.js'
2+
import process from 'node:process'
3+
import core from '@actions/core'
4+
import playwright from 'playwright'
75

86
export default async function () {
9-
core.info("Starting 'auth' action");
7+
core.info("Starting 'auth' action")
108

11-
let browser: playwright.Browser | undefined;
12-
let context: playwright.BrowserContext | undefined;
13-
let page: playwright.Page | undefined;
9+
let browser: playwright.Browser | undefined
10+
let context: playwright.BrowserContext | undefined
11+
let page: playwright.Page | undefined
1412
try {
1513
// Get inputs
16-
const loginUrl = core.getInput("login_url", { required: true });
17-
const username = core.getInput("username", { required: true });
18-
const password = core.getInput("password", { required: true });
19-
core.setSecret(password);
20-
21-
// Determine storage path for authenticated session state
22-
// Playwright will create missing directories, if needed
23-
const actionDirectory = `${url.fileURLToPath(new URL(import.meta.url))}/..`;
24-
const sessionStatePath = `${
25-
process.env.RUNNER_TEMP ?? actionDirectory
26-
}/.auth/${crypto.randomUUID()}/sessionState.json`;
14+
const loginUrl = core.getInput('login_url', {required: true})
15+
const username = core.getInput('username', {required: true})
16+
const password = core.getInput('password', {required: true})
17+
core.setSecret(password)
2718

2819
// Launch a headless browser
2920
browser = await playwright.chromium.launch({
3021
headless: true,
31-
executablePath: process.env.CI ? "/usr/bin/google-chrome" : undefined,
32-
});
22+
executablePath: process.env.CI ? '/usr/bin/google-chrome' : undefined,
23+
})
3324
context = await browser.newContext({
3425
// Try HTTP Basic authentication
3526
httpCredentials: {
3627
username,
3728
password,
3829
},
39-
});
40-
page = await context.newPage();
30+
})
31+
page = await context.newPage()
4132

4233
// Navigate to login page
43-
core.info("Navigating to login page");
44-
await page.goto(loginUrl);
34+
core.info('Navigating to login page')
35+
await page.goto(loginUrl)
4536

4637
// Check for a login form.
4738
// If no login form is found, then either HTTP Basic auth succeeded, or the page does not require authentication.
48-
core.info("Checking for login form");
39+
core.info('Checking for login form')
4940
const [usernameField, passwordField] = await Promise.all([
5041
page.getByLabel(/user ?name/i).first(),
5142
page.getByLabel(/password/i).first(),
52-
]);
53-
const [usernameFieldExists, passwordFieldExists] = await Promise.all([
54-
usernameField.count(),
55-
passwordField.count(),
56-
]);
43+
])
44+
const [usernameFieldExists, passwordFieldExists] = await Promise.all([usernameField.count(), passwordField.count()])
5745
if (usernameFieldExists && passwordFieldExists) {
5846
// Try form authentication
59-
core.info("Filling username");
60-
await usernameField.fill(username);
61-
core.info("Filling password");
62-
await passwordField.fill(password);
63-
core.info("Logging in");
47+
core.info('Filling username')
48+
await usernameField.fill(username)
49+
core.info('Filling password')
50+
await passwordField.fill(password)
51+
core.info('Logging in')
6452
await page
6553
.getByLabel(/password/i)
66-
.locator("xpath=ancestor::form")
67-
.evaluate((form) => (form as HTMLFormElement).submit());
54+
.locator('xpath=ancestor::form')
55+
.evaluate(form => (form as HTMLFormElement).submit())
6856
} else {
69-
core.info("No login form detected");
57+
core.info('No login form detected')
7058
// This occurs if HTTP Basic auth succeeded, or if the page does not require authentication.
7159
}
7260

7361
// Output authenticated session state
74-
const { cookies, origins } = await context.storageState();
62+
const {cookies, origins} = await context.storageState()
7563
const authContextOutput: AuthContextOutput = {
7664
username,
7765
password,
7866
cookies,
79-
localStorage: origins.reduce((acc, { origin, localStorage }) => {
80-
acc[origin] = localStorage.reduce((acc, { name, value }) => {
81-
acc[name] = value;
82-
return acc;
83-
}, {} as Record<string, string>);
84-
return acc;
85-
}, {} as Record<string, Record<string, string>>),
86-
};
87-
core.setOutput("auth_context", JSON.stringify(authContextOutput));
88-
core.debug("Output: 'auth_context'");
67+
localStorage: origins.reduce(
68+
(acc, {origin, localStorage}) => {
69+
acc[origin] = localStorage.reduce(
70+
(acc, {name, value}) => {
71+
acc[name] = value
72+
return acc
73+
},
74+
{} as Record<string, string>,
75+
)
76+
return acc
77+
},
78+
{} as Record<string, Record<string, string>>,
79+
),
80+
}
81+
core.setOutput('auth_context', JSON.stringify(authContextOutput))
82+
core.debug("Output: 'auth_context'")
8983
} catch (error) {
9084
if (page) {
91-
core.info(`Errored at page URL: ${page.url()}`);
85+
core.info(`Errored at page URL: ${page.url()}`)
9286
}
93-
core.setFailed(`${error}`);
94-
process.exit(1);
87+
core.setFailed(`${error}`)
88+
process.exit(1)
9589
} finally {
9690
// Clean up
97-
await context?.close();
98-
await browser?.close();
91+
await context?.close()
92+
await browser?.close()
9993
}
10094

101-
core.info("Finished 'auth' action");
95+
core.info("Finished 'auth' action")
10296
}
Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
export type Cookie = {
2-
name: string;
3-
value: string;
4-
domain: string;
5-
path: string;
6-
expires?: number;
7-
httpOnly?: boolean;
8-
secure?: boolean;
9-
sameSite?: "Strict" | "Lax" | "None";
10-
};
2+
name: string
3+
value: string
4+
domain: string
5+
path: string
6+
expires?: number
7+
httpOnly?: boolean
8+
secure?: boolean
9+
sameSite?: 'Strict' | 'Lax' | 'None'
10+
}
1111

1212
export type LocalStorage = {
1313
[origin: string]: {
14-
[key: string]: string;
15-
};
16-
};
14+
[key: string]: string
15+
}
16+
}
1717

1818
export type AuthContextOutput = {
19-
username?: string;
20-
password?: string;
21-
cookies?: Cookie[];
22-
localStorage?: LocalStorage;
23-
};
19+
username?: string
20+
password?: string
21+
cookies?: Cookie[]
22+
localStorage?: LocalStorage
23+
}

.github/actions/file/src/Issue.ts

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,44 @@
1-
import type { Issue as IssueInput } from "./types.d.js";
1+
import type {Issue as IssueInput} from './types.d.js'
22

33
export class Issue implements IssueInput {
4-
#url!: string;
4+
#url!: string
55
#parsedUrl!: {
6-
owner: string;
7-
repository: string;
8-
issueNumber: number;
9-
};
10-
nodeId: string;
11-
id: number;
12-
title: string;
13-
state?: "open" | "reopened" | "closed";
14-
15-
constructor({ url, nodeId, id, title, state }: IssueInput) {
16-
this.url = url;
17-
this.nodeId = nodeId;
18-
this.id = id;
19-
this.title = title;
20-
this.state = state;
6+
owner: string
7+
repository: string
8+
issueNumber: number
9+
}
10+
nodeId: string
11+
id: number
12+
title: string
13+
state?: 'open' | 'reopened' | 'closed'
14+
15+
constructor({url, nodeId, id, title, state}: IssueInput) {
16+
this.url = url
17+
this.nodeId = nodeId
18+
this.id = id
19+
this.title = title
20+
this.state = state
2121
}
2222

2323
set url(newUrl: string) {
24-
this.#url = newUrl;
25-
this.#parsedUrl = this.#parseUrl();
24+
this.#url = newUrl
25+
this.#parsedUrl = this.#parseUrl()
2626
}
2727

2828
get url(): string {
29-
return this.#url;
29+
return this.#url
3030
}
3131

3232
get owner(): string {
33-
return this.#parsedUrl.owner;
33+
return this.#parsedUrl.owner
3434
}
3535

3636
get repository(): string {
37-
return this.#parsedUrl.repository;
37+
return this.#parsedUrl.repository
3838
}
3939

4040
get issueNumber(): number {
41-
return this.#parsedUrl.issueNumber;
41+
return this.#parsedUrl.issueNumber
4242
}
4343

4444
/**
@@ -47,17 +47,15 @@ export class Issue implements IssueInput {
4747
* @throws The provided URL is unparseable due to its unexpected format.
4848
*/
4949
#parseUrl(): {
50-
owner: string;
51-
repository: string;
52-
issueNumber: number;
50+
owner: string
51+
repository: string
52+
issueNumber: number
5353
} {
54-
const { owner, repository, issueNumber } =
55-
/\/(?<owner>[^/]+)\/(?<repository>[^/]+)\/issues\/(?<issueNumber>\d+)(?:[/?#]|$)/.exec(
56-
this.#url
57-
)?.groups || {};
54+
const {owner, repository, issueNumber} =
55+
/\/(?<owner>[^/]+)\/(?<repository>[^/]+)\/issues\/(?<issueNumber>\d+)(?:[/?#]|$)/.exec(this.#url)?.groups || {}
5856
if (!owner || !repository || !issueNumber) {
59-
throw new Error(`Could not parse issue URL: ${this.#url}`);
57+
throw new Error(`Could not parse issue URL: ${this.#url}`)
6058
}
61-
return { owner, repository, issueNumber: Number(issueNumber) };
59+
return {owner, repository, issueNumber: Number(issueNumber)}
6260
}
6361
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import type { Octokit } from '@octokit/core';
2-
import { Issue } from './Issue.js';
1+
import type {Octokit} from '@octokit/core'
2+
import {Issue} from './Issue.js'
33

4-
export async function closeIssue(octokit: Octokit, { owner, repository, issueNumber }: Issue) {
4+
export async function closeIssue(octokit: Octokit, {owner, repository, issueNumber}: Issue) {
55
return octokit.request(`PATCH /repos/${owner}/${repository}/issues/${issueNumber}`, {
66
owner,
77
repository,
88
issue_number: issueNumber,
9-
state: 'closed'
10-
});
11-
}
9+
state: 'closed',
10+
})
11+
}
Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,28 @@
1-
import type { Finding } from "./types.d.js";
1+
import type {Finding} from './types.d.js'
22

3-
export function generateIssueBody(finding: Finding, repoWithOwner: string): string {
3+
export function generateIssueBody(finding: Finding): string {
44
const solutionLong = finding.solutionLong
5-
?.split("\n")
6-
.map((line: string) =>
7-
!line.trim().startsWith("Fix any") &&
8-
!line.trim().startsWith("Fix all") &&
9-
line.trim() !== ""
10-
? `- ${line}`
11-
: line
12-
)
13-
.join("\n");
14-
const acceptanceCriteria = `## Acceptance Criteria
5+
?.split('\n')
6+
.map((line: string) =>
7+
!line.trim().startsWith('Fix any') && !line.trim().startsWith('Fix all') && line.trim() !== ''
8+
? `- ${line}`
9+
: line,
10+
)
11+
.join('\n')
12+
const acceptanceCriteria = `## Acceptance Criteria
1513
- [ ] The specific axe violation reported in this issue is no longer reproducible.
1614
- [ ] The fix MUST meet WCAG 2.1 guidelines OR the accessibility standards specified by the repository or organization.
1715
- [ ] A test SHOULD be added to ensure this specific axe violation does not regress.
1816
- [ ] This PR MUST NOT introduce any new accessibility issues or regressions.
19-
`;
20-
const body = `## What
17+
`
18+
const body = `## What
2119
An accessibility scan flagged the element \`${finding.html}\` on ${finding.url} because ${finding.problemShort}. Learn more about why this was flagged by visiting ${finding.problemUrl}.
2220
2321
To fix this, ${finding.solutionShort}.
2422
${solutionLong ? `\nSpecifically:\n\n${solutionLong}` : ''}
2523
2624
${acceptanceCriteria}
27-
`;
25+
`
2826

29-
return body;
27+
return body
3028
}
31-

0 commit comments

Comments
 (0)