Skip to content

Commit

Permalink
Do not allow YouTube video URLs when using the URLPicker (#5503)
Browse files Browse the repository at this point in the history
  • Loading branch information
acelaya authored Jun 22, 2023
1 parent bc0b6ff commit 4726eb3
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export default function ContentSelector({
defaultURL={getDefaultValue('url')}
onCancel={cancelDialog}
onSelectURL={selectURL}
youtubeEnabled={youtubeEnabled}
/>
);
break;
Expand Down
14 changes: 13 additions & 1 deletion lms/static/scripts/frontend_apps/components/URLPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Button, ModalDialog, Input } from '@hypothesis/frontend-shared';
import { useRef, useState } from 'preact/hooks';

import { isYouTubeURL } from '../utils/youtube';
import UIMessage from './UIMessage';

export type URLPickerProps = {
Expand All @@ -10,6 +11,8 @@ export type URLPickerProps = {
onCancel: () => void;
/** Callback invoked with the entered URL when the user accepts the dialog */
onSelectURL: (url: string) => void;
/** Indicates if YouTube transcript annotations are enabled */
youtubeEnabled?: boolean;
};

/**
Expand All @@ -20,6 +23,7 @@ export default function URLPicker({
defaultURL = '',
onCancel,
onSelectURL,
youtubeEnabled = false,
}: URLPickerProps) {
const input = useRef<HTMLInputElement | null>(null);
const form = useRef<HTMLFormElement | null>(null);
Expand All @@ -31,7 +35,9 @@ export default function URLPicker({
const submit = (event: Event) => {
event.preventDefault();
try {
const url = new URL(input.current!.value);
const rawInputValue = input.current!.value;
const url = new URL(rawInputValue);

if (!url.protocol.startsWith('http')) {
if (url.protocol.startsWith('file')) {
setError(
Expand All @@ -40,6 +46,12 @@ export default function URLPicker({
} else {
setError('Please use a URL that starts with "http" or "https"');
}
} else if (isYouTubeURL(rawInputValue)) {
setError(
youtubeEnabled
? 'To annotate a video, go back and choose the YouTube option.'
: 'Annotating YouTube videos is not yet supported. This feature is coming soon.'
);
} else {
onSelectURL(input.current!.value);
}
Expand Down
31 changes: 31 additions & 0 deletions lms/static/scripts/frontend_apps/components/test/URLPicker-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,37 @@ describe('URLPicker', () => {
);
});

[
{
youtubeEnabled: true,
expectedError:
'To annotate a video, go back and choose the YouTube option.',
},
{
youtubeEnabled: false,
expectedError:
'Annotating YouTube videos is not yet supported. This feature is coming soon.',
},
].forEach(({ youtubeEnabled, expectedError }) => {
it('does not invoke `onSelectURL` if URL is for a YouTube video', () => {
const onSelectURL = sinon.stub();

const wrapper = renderUrlPicker({ onSelectURL, youtubeEnabled });
wrapper.find('input').getDOMNode().value = 'https://youtu.be/EU6TDnV5osM';

wrapper
.find('button[data-testid="submit-button"]')
.props()
.onClick(new Event('click'));
wrapper.update();

assert.notCalled(onSelectURL);
const errorMessage = wrapper.find('UIMessage[status="error"]');
assert.isTrue(errorMessage.exists());
assert.include(errorMessage.text(), expectedError);
});
});

it(
'should pass a11y checks',
checkAccessibility({
Expand Down

0 comments on commit 4726eb3

Please sign in to comment.