feat: aria-labels and buttons contain more media info (#1743)
* feat: aria-labels and buttons contain more media info fixes #1733 * fix lint
This commit is contained in:
parent
bfb1da6bd0
commit
1f0d67fcc4
|
@ -36,11 +36,13 @@ function cleanupText (text) {
|
||||||
export function getAccessibleLabelForStatus (originalAccount, account, plainTextContent,
|
export function getAccessibleLabelForStatus (originalAccount, account, plainTextContent,
|
||||||
timeagoFormattedDate, spoilerText, showContent,
|
timeagoFormattedDate, spoilerText, showContent,
|
||||||
reblog, notification, visibility, omitEmojiInDisplayNames,
|
reblog, notification, visibility, omitEmojiInDisplayNames,
|
||||||
disableLongAriaLabels) {
|
disableLongAriaLabels, showMedia, showPoll) {
|
||||||
const originalAccountDisplayName = getAccountAccessibleName(originalAccount, omitEmojiInDisplayNames)
|
const originalAccountDisplayName = getAccountAccessibleName(originalAccount, omitEmojiInDisplayNames)
|
||||||
const contentTextToShow = (showContent || !spoilerText)
|
const contentTextToShow = (showContent || !spoilerText)
|
||||||
? cleanupText(plainTextContent)
|
? cleanupText(plainTextContent)
|
||||||
: `Content warning: ${cleanupText(spoilerText)}`
|
: `Content warning: ${cleanupText(spoilerText)}`
|
||||||
|
const mediaTextToShow = showMedia && 'has media'
|
||||||
|
const pollTextToShow = showPoll && 'has poll'
|
||||||
const privacyText = getPrivacyText(visibility)
|
const privacyText = getPrivacyText(visibility)
|
||||||
|
|
||||||
if (disableLongAriaLabels) {
|
if (disableLongAriaLabels) {
|
||||||
|
@ -53,6 +55,8 @@ export function getAccessibleLabelForStatus (originalAccount, account, plainText
|
||||||
getNotificationText(notification, omitEmojiInDisplayNames),
|
getNotificationText(notification, omitEmojiInDisplayNames),
|
||||||
originalAccountDisplayName,
|
originalAccountDisplayName,
|
||||||
contentTextToShow,
|
contentTextToShow,
|
||||||
|
mediaTextToShow,
|
||||||
|
pollTextToShow,
|
||||||
timeagoFormattedDate,
|
timeagoFormattedDate,
|
||||||
`@${originalAccount.acct}`,
|
`@${originalAccount.acct}`,
|
||||||
privacyText,
|
privacyText,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<button id={elementId}
|
<button id={elementId}
|
||||||
type="button"
|
type="button"
|
||||||
class="inline-media play-video-button focus-after {$largeInlineMedia ? '' : 'fixed-size'} {type === 'audio' ? 'play-audio-button' : ''}"
|
class="inline-media play-video-button focus-after {$largeInlineMedia ? '' : 'fixed-size'} {type === 'audio' ? 'play-audio-button' : ''}"
|
||||||
aria-label="Play {type === 'video' ? 'video' : 'audio'}: {description}"
|
aria-label={videoOrAudioButtonLabel}
|
||||||
{tabindex}
|
{tabindex}
|
||||||
aria-hidden={ariaHidden}
|
aria-hidden={ariaHidden}
|
||||||
style={inlineMediaStyle}>
|
style={inlineMediaStyle}>
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
<button id={elementId}
|
<button id={elementId}
|
||||||
type="button"
|
type="button"
|
||||||
class="inline-media show-image-button focus-after {$largeInlineMedia ? '' : 'fixed-size'}"
|
class="inline-media show-image-button focus-after {$largeInlineMedia ? '' : 'fixed-size'}"
|
||||||
aria-label="Show image: {description}"
|
aria-label={imageButtonAriaLabel}
|
||||||
title={description}
|
title={description}
|
||||||
on:mouseover="set({mouseover: event})"
|
on:mouseover="set({mouseover: event})"
|
||||||
style={inlineMediaStyle}
|
style={inlineMediaStyle}
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
>
|
>
|
||||||
{#if type === 'gifv' && $autoplayGifs && !blurhash}
|
{#if type === 'gifv' && $autoplayGifs && !blurhash}
|
||||||
<AutoplayVideo
|
<AutoplayVideo
|
||||||
ariaLabel="Animated GIF: {description}"
|
ariaLabel="Animated image: {description}"
|
||||||
poster={previewUrl}
|
poster={previewUrl}
|
||||||
src={url}
|
src={url}
|
||||||
width={inlineWidth}
|
width={inlineWidth}
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
{:elseif type === 'gifv'}
|
{:elseif type === 'gifv'}
|
||||||
<NonAutoplayGifv
|
<NonAutoplayGifv
|
||||||
class={noNativeWidthHeight ? 'no-native-width-height' : ''}
|
class={noNativeWidthHeight ? 'no-native-width-height' : ''}
|
||||||
label="Animated GIF: {description}"
|
label="Animated image: {description}"
|
||||||
poster={previewUrl}
|
poster={previewUrl}
|
||||||
{blurhash}
|
{blurhash}
|
||||||
src={url}
|
src={url}
|
||||||
|
@ -166,7 +166,13 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tabindex: ({ showAsSensitive }) => showAsSensitive ? '-1' : '0',
|
tabindex: ({ showAsSensitive }) => showAsSensitive ? '-1' : '0',
|
||||||
ariaHidden: ({ showAsSensitive }) => showAsSensitive
|
ariaHidden: ({ showAsSensitive }) => showAsSensitive,
|
||||||
|
imageButtonAriaLabel: ({ type, description }) => (
|
||||||
|
`Show ${type === 'gifv' ? 'animated image' : 'image'}: ${description}`
|
||||||
|
),
|
||||||
|
videoOrAudioButtonLabel: ({ type, description }) => (
|
||||||
|
`Play ${type === 'video' ? 'video' : 'audio'}: ${description}`
|
||||||
|
)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClick () {
|
onClick () {
|
||||||
|
|
|
@ -280,11 +280,14 @@
|
||||||
reblog: ({ status }) => status.reblog,
|
reblog: ({ status }) => status.reblog,
|
||||||
ariaLabel: ({
|
ariaLabel: ({
|
||||||
originalAccount, account, plainTextContent, timeagoFormattedDate, spoilerText,
|
originalAccount, account, plainTextContent, timeagoFormattedDate, spoilerText,
|
||||||
showContent, reblog, notification, visibility, $omitEmojiInDisplayNames, $disableLongAriaLabels
|
showContent, reblog, notification, visibility, $omitEmojiInDisplayNames, $disableLongAriaLabels,
|
||||||
|
showMedia, showPoll
|
||||||
}) => (
|
}) => (
|
||||||
getAccessibleLabelForStatus(originalAccount, account, plainTextContent,
|
getAccessibleLabelForStatus(originalAccount, account, plainTextContent,
|
||||||
timeagoFormattedDate, spoilerText, showContent,
|
timeagoFormattedDate, spoilerText, showContent,
|
||||||
reblog, notification, visibility, $omitEmojiInDisplayNames, $disableLongAriaLabels)
|
reblog, notification, visibility, $omitEmojiInDisplayNames, $disableLongAriaLabels,
|
||||||
|
showMedia, showPoll
|
||||||
|
)
|
||||||
),
|
),
|
||||||
showHeader: ({ notification, status, timelineType }) => (
|
showHeader: ({ notification, status, timelineType }) => (
|
||||||
(notification && ['reblog', 'favourite', 'poll'].includes(notification.type)) ||
|
(notification && ['reblog', 'favourite', 'poll'].includes(notification.type)) ||
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
import { closeDialogButton, getNthStatus, getNthStatusSelector, modalDialogContents, scrollToStatus } from '../utils'
|
import {
|
||||||
|
closeDialogButton,
|
||||||
|
getNthStatus,
|
||||||
|
getNthStatusMediaButton,
|
||||||
|
getNthStatusSelector,
|
||||||
|
modalDialogContents,
|
||||||
|
scrollToStatus
|
||||||
|
} from '../utils'
|
||||||
import { loginAsFoobar } from '../roles'
|
import { loginAsFoobar } from '../roles'
|
||||||
import { Selector as $ } from 'testcafe'
|
import { Selector as $ } from 'testcafe'
|
||||||
import { homeTimeline } from '../fixtures'
|
import { homeTimeline } from '../fixtures'
|
||||||
|
@ -13,8 +20,10 @@ test('shows sensitive images and videos', async t => {
|
||||||
const videoIdx = homeTimeline.findIndex(_ => _.content === 'secret video')
|
const videoIdx = homeTimeline.findIndex(_ => _.content === 'secret video')
|
||||||
|
|
||||||
await scrollToStatus(t, 1 + kittenIdx)
|
await scrollToStatus(t, 1 + kittenIdx)
|
||||||
await t.expect($(`${getNthStatusSelector(1 + kittenIdx)} .status-media img`).getAttribute('src')).match(/^blob:http:\/\/localhost/)
|
await t.expect($(`${getNthStatusSelector(1 + kittenIdx)} .status-media img`).getAttribute('src'))
|
||||||
|
.match(/^blob:http:\/\/localhost/)
|
||||||
.click($(`${getNthStatusSelector(1 + kittenIdx)} .status-sensitive-media-button`))
|
.click($(`${getNthStatusSelector(1 + kittenIdx)} .status-sensitive-media-button`))
|
||||||
|
.expect($(getNthStatusMediaButton(1 + kittenIdx)).getAttribute('aria-label')).eql('Show image: kitten')
|
||||||
.expect($(`${getNthStatusSelector(1 + kittenIdx)} .status-media img`).getAttribute('alt')).eql('kitten')
|
.expect($(`${getNthStatusSelector(1 + kittenIdx)} .status-media img`).getAttribute('alt')).eql('kitten')
|
||||||
.expect($(`${getNthStatusSelector(1 + kittenIdx)} .status-media img`).getAttribute('src')).match(/^http:\/\//)
|
.expect($(`${getNthStatusSelector(1 + kittenIdx)} .status-media img`).getAttribute('src')).match(/^http:\/\//)
|
||||||
.hover(getNthStatus(1 + videoIdx))
|
.hover(getNthStatus(1 + videoIdx))
|
||||||
|
@ -31,7 +40,9 @@ test('click and close image and video modals', async t => {
|
||||||
|
|
||||||
await scrollToStatus(t, 1 + videoIdx)
|
await scrollToStatus(t, 1 + videoIdx)
|
||||||
await t.expect(modalDialogContents.exists).notOk()
|
await t.expect(modalDialogContents.exists).notOk()
|
||||||
.click($(`${getNthStatusSelector(1 + videoIdx)} .play-video-button`))
|
.expect($(getNthStatusMediaButton(1 + videoIdx)).getAttribute('aria-label'))
|
||||||
|
.eql('Play video: kitten')
|
||||||
|
.click($(getNthStatusMediaButton(1 + videoIdx)))
|
||||||
.expect(modalDialogContents.exists).ok()
|
.expect(modalDialogContents.exists).ok()
|
||||||
.expect($('.modal-dialog video').getAttribute('src')).contains('mp4')
|
.expect($('.modal-dialog video').getAttribute('src')).contains('mp4')
|
||||||
.expect($('.modal-dialog video').getAttribute('poster')).contains('png')
|
.expect($('.modal-dialog video').getAttribute('poster')).contains('png')
|
||||||
|
@ -39,7 +50,9 @@ test('click and close image and video modals', async t => {
|
||||||
.expect(modalDialogContents.exists).notOk()
|
.expect(modalDialogContents.exists).notOk()
|
||||||
.hover(getNthStatus(1 + kittenIdx - 1))
|
.hover(getNthStatus(1 + kittenIdx - 1))
|
||||||
.hover(getNthStatus(1 + kittenIdx))
|
.hover(getNthStatus(1 + kittenIdx))
|
||||||
.click($(`${getNthStatusSelector(1 + kittenIdx)} .show-image-button`))
|
.expect($(getNthStatusMediaButton(1 + kittenIdx)).getAttribute('aria-label'))
|
||||||
|
.eql('Show animated image: kitten')
|
||||||
|
.click($(getNthStatusMediaButton(1 + kittenIdx)))
|
||||||
.expect(modalDialogContents.exists).ok()
|
.expect(modalDialogContents.exists).ok()
|
||||||
.expect($('.modal-dialog video').getAttribute('src')).contains('mp4')
|
.expect($('.modal-dialog video').getAttribute('src')).contains('mp4')
|
||||||
.expect($('.modal-dialog video').getAttribute('poster')).contains('png')
|
.expect($('.modal-dialog video').getAttribute('poster')).contains('png')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { loginAsFoobar } from '../roles'
|
import { loginAsFoobar } from '../roles'
|
||||||
import { getNthStatus } from '../utils'
|
import { getNthStatus } from '../utils'
|
||||||
import { postAs, postEmptyStatusWithMediaAs } from '../serverActions'
|
import { createPollAs, postAs, postEmptyStatusWithMediaAs } from '../serverActions'
|
||||||
|
|
||||||
fixture`120-status-aria-label.js`
|
fixture`120-status-aria-label.js`
|
||||||
.page`http://localhost:4002`
|
.page`http://localhost:4002`
|
||||||
|
@ -11,7 +11,17 @@ test('aria-labels for statuses with no content text', async t => {
|
||||||
await t
|
await t
|
||||||
.hover(getNthStatus(1))
|
.hover(getNthStatus(1))
|
||||||
.expect(getNthStatus(1).getAttribute('aria-label')).match(
|
.expect(getNthStatus(1).getAttribute('aria-label')).match(
|
||||||
/foobar, (.+ ago|just now), @foobar, Public/i
|
/foobar, has media, (.+ ago|just now), @foobar, Public/i
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('aria-labels for statuses with polls', async t => {
|
||||||
|
await createPollAs('foobar', 'here is my poll', ['yolo', 'whatever'])
|
||||||
|
await loginAsFoobar(t)
|
||||||
|
await t
|
||||||
|
.hover(getNthStatus(1))
|
||||||
|
.expect(getNthStatus(1).getAttribute('aria-label')).match(
|
||||||
|
/foobar, here is my poll, has poll, (.+ ago|just now), @foobar, Public/i
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue