Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add selector at the end of the page and wait for it before testing #9

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions components/AuditForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ if (baseAuditId) {
} else {
setValues({
pages: baseAudit.config.noAxe
? [{ selector: '', url: '' }]
? [{ selector: '', endSelector: '', url: '' }]
: baseAudit.config.pages,
title: baseAudit.config.title,
project: baseAudit.projects?.id,
Expand Down Expand Up @@ -267,7 +267,7 @@ const onAuditProcessingDialogClose = (resetAuditForm: boolean = true) => {
</div>

<div class="w-full">
<label :for="`selector-${index}`">HTML Selector</label>
<label :for="`selector-${index}`">HTML Selector to</label>
<InputText
:id="`selector-${index}`"
v-model="page.value.selector"
Expand All @@ -289,6 +289,33 @@ const onAuditProcessingDialogClose = (resetAuditForm: boolean = true) => {
selector allowed. If empty whole document will be tested.
</small>
</div>
<div class="col-start-2 w-full">
<label :for="`selector-end-${index}`"
>HTML Selector at the end of the page</label
>
<InputText
:id="`selector-end-${index}`"
v-model="page.value.endSelector"
:name="`pages[${index}].endSelector`"
class="w-full"
:aria-describedby="`selector-end-help-${index}`"
:data-testid="`audit-page-selector-end-field-${index}`"
:class="[
{
'p-invalid':
(errors[`pages[${index}].endSelector` as `pages.${number}.endSelector`] ||
errors[`pages[${index}]` as `pages.${number}`]) &&
isSubmitted,
},
]"
/>
<small :id="`selector-end-help-${index}`">
Sometimes dynamic page is not fully loaded when automatic
tests are conducted. To make sure all elements on the page are
available, provide the element at the end of the page, use
.class or #id to choose selector, just one selector allowed.
</small>
</div>
<small
v-if="errors[`pages[${index}]` as `pages.${number}`] && isSubmitted"
class="p-error w-full"
Expand Down Expand Up @@ -321,7 +348,7 @@ const onAuditProcessingDialogClose = (resetAuditForm: boolean = true) => {
:pt="{
icon: { 'aria-hidden': true },
}"
@click="pushPage({ url: '', selector: '' })"
@click="pushPage({ url: '', selector: '', endSelector: '' })"
/>
</AccordionTab>
<AccordionTab header="General">
Expand Down
8 changes: 8 additions & 0 deletions pages/audit/report/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ const completeReport = async () => {
{{ page.selector }}
</code>
</template>
<template v-if="page.endSelector?.length">
- selector of the element at the end of the page:
<code
class="break-words rounded-md bg-gray-100 px-2 py-1"
>
{{ page.endSelector }}
</code>
</template>
</li>
</ul>
</template>
Expand Down
24 changes: 22 additions & 2 deletions server/axe-runner/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const doTest = async function (

await page.setViewportSize(size)

for await (const { url, selector } of pages) {
for await (const { url, selector, endSelector } of pages) {
let result: AxeResults | undefined
const errors: ResultError[] = []

Expand All @@ -73,6 +73,24 @@ export const doTest = async function (

const axe = await new AxeBuilder({ page })

if (endSelector) {
await page
.locator(endSelector)
.waitFor()
.then(async () => {
await page.evaluate(() =>
window.scrollTo(0, document.body.scrollHeight)
)
})
.catch(() =>
errors.push({
url,
message:
'Selector of element at the end of the page does not exist.',
})
)
}

if (selector) {
await page
.locator(selector)
Expand All @@ -95,7 +113,9 @@ export const doTest = async function (
result = await axe.analyze()
}

results.push(parseResults(auditId, size, errors, result))
results.push(
parseResults(auditId, size, errors, result, selector, endSelector)
)
}

if (process.env.dev) {
Expand Down
4 changes: 3 additions & 1 deletion server/axe-runner/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ export const parseResults = function (
size: ViewportSize,
errors?: ResultError[],
results?: AxeResults,
selector?: string
selector?: string,
endSelector?: string
): TestResult {
return {
audit_id: auditId,
selector: selector || null,
end_selector: endSelector || null,
size: `${size.width},${size.height}`,
results: results ? trimResults(results) : null,
errors,
Expand Down
1 change: 1 addition & 0 deletions sql/02_tables/05_axe.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ create table axe (
created_at timestamp default current_timestamp not null,
audit_id serial references public.audits on delete cascade not null,
selector text,
end_selector text,
size text,
results JSONB not null DEFAULT '{}'::jsonb,
form_data JSONB not null DEFAULT '{}'::jsonb,
Expand Down
1 change: 1 addition & 0 deletions types/audit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { auditTemplate } from '~/data/auditTemplate'

export interface Page {
selector?: string | undefined
endSelector?: string | undefined
url: string
}

Expand Down
2 changes: 2 additions & 0 deletions types/axe-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type ResultError = {
export interface TestResult {
audit_id: string
selector: string | null
end_selector: string | null
size: string
results: TrimmedResults | null
errors?: ResultError[]
Expand All @@ -31,6 +32,7 @@ export type BasicAuth = {

export type Page = {
selector?: string
endSelector?: string
url: string
}

Expand Down
3 changes: 3 additions & 0 deletions types/supabase-latest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export interface Database {
id: number
results: Json | null
selector: string | null
end_selector: string | null
size: string | null
}
Insert: {
Expand All @@ -80,6 +81,7 @@ export interface Database {
id?: number
results?: Json | null
selector?: string | null
end_selector?: string | null
size?: string | null
}
Update: {
Expand All @@ -90,6 +92,7 @@ export interface Database {
id?: number
results?: Json | null
selector?: string | null
end_selector?: string | null
size?: string | null
}
Relationships: [
Expand Down
3 changes: 3 additions & 0 deletions types/supabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export interface Database {
results: Results
errors: Json[] | null
selector: string | null
end_selector: string | null
size: string | null
form_data: FormData | null
}
Expand All @@ -114,6 +115,7 @@ export interface Database {
id?: number
results?: Results
selector?: string | null
end_selector?: string | null
size?: string | null
form_data?: FormData | null
}
Expand All @@ -123,6 +125,7 @@ export interface Database {
id?: number
results?: Results
selector?: string | null
end_selector?: string | null
size?: string | null
form_data?: FormData | null
}
Expand Down
5 changes: 5 additions & 0 deletions validation/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ export const auditFormSchema = object({
object().shape({
url: string(),
selector: string(),
endSelector: string(),
})
)
.default([
{
endSelector: '',
selector: '',
url: '',
},
Expand All @@ -48,12 +50,14 @@ export const auditFormSchema = object({
.shape({
url: string().url().required(),
selector: string(),
endSelector: string(),
})
.test('isUnique', `The entry is not unique`, function (currentPage) {
const pages = this.parent
const count = pages.filter(
(page: Page) =>
page.selector === currentPage.selector &&
page.endSelector === currentPage.endSelector &&
page.url === currentPage.url
).length
return count <= 1
Expand All @@ -63,6 +67,7 @@ export const auditFormSchema = object({
.default([
{
selector: '',
endSelector: '',
url: '',
},
])
Expand Down