-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨(website) creates lives on the website
Give the possibility to create a live from the website.
- Loading branch information
Showing
9 changed files
with
541 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
...standalone_site/src/features/Contents/features/Live/components/Create/LiveCreate.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { screen } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { render } from 'lib-tests'; | ||
|
||
import LiveCreate from './LiveCreate'; | ||
|
||
jest.mock('./LiveCreateForm', () => ({ | ||
__esModule: true, | ||
default: () => <div>My LiveCreate Form</div>, | ||
})); | ||
|
||
describe('<LiveCreate />', () => { | ||
test('renders LiveCreate', () => { | ||
render(<LiveCreate />); | ||
|
||
const button = screen.getByRole('button', { name: /Create Live/i }); | ||
expect(button).toBeInTheDocument(); | ||
expect( | ||
screen.queryByRole('heading', { name: /Create Live/i }), | ||
).not.toBeInTheDocument(); | ||
|
||
userEvent.click(button); | ||
|
||
expect( | ||
screen.getByRole('heading', { name: /Create Live/i }), | ||
).toBeInTheDocument(); | ||
expect(screen.getByText('My LiveCreate Form')).toBeInTheDocument(); | ||
}); | ||
}); |
80 changes: 80 additions & 0 deletions
80
...apps/standalone_site/src/features/Contents/features/Live/components/Create/LiveCreate.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { Button, Heading, Text } from 'grommet'; | ||
import { Fragment } from 'react'; | ||
import { defineMessages, useIntl } from 'react-intl'; | ||
import { Link, Route, Switch, useHistory } from 'react-router-dom'; | ||
|
||
import { WhiteCard } from 'components/Cards'; | ||
import { Modal } from 'components/Modal'; | ||
import { useResponsive } from 'hooks/useResponsive'; | ||
import { routes } from 'routes'; | ||
|
||
import LiveCreateForm from './LiveCreateForm'; | ||
|
||
const messages = defineMessages({ | ||
LiveTitle: { | ||
defaultMessage: 'Lives', | ||
description: 'Lives title', | ||
id: 'features.Contents.features.Live.Create.LiveTitle', | ||
}, | ||
CreateLiveLabel: { | ||
defaultMessage: 'Create Live', | ||
description: 'Text heading create live.', | ||
id: 'features.Contents.features.Live.Create.CreateLiveLabel', | ||
}, | ||
}); | ||
|
||
const LiveCreate = () => { | ||
const intl = useIntl(); | ||
const { breakpoint } = useResponsive(); | ||
const history = useHistory(); | ||
|
||
const liveRoute = routes.CONTENTS.subRoutes.LIVE; | ||
const livePath = liveRoute.path; | ||
const liveCreatePath = liveRoute.subRoutes?.CREATE?.path || ''; | ||
|
||
return ( | ||
<Fragment> | ||
<WhiteCard | ||
flex="shrink" | ||
direction={breakpoint === 'xxsmall' ? 'column' : 'row'} | ||
gap={breakpoint === 'xxsmall' ? 'small' : 'none'} | ||
justify="between" | ||
align="center" | ||
height={{ min: '5rem' }} | ||
margin={{ bottom: 'medium' }} | ||
> | ||
<Text size="large" weight="bold"> | ||
{intl.formatMessage(messages.LiveTitle)} | ||
</Text> | ||
<Link to={liveCreatePath}> | ||
<Button | ||
primary | ||
label={intl.formatMessage(messages.CreateLiveLabel)} | ||
/> | ||
</Link> | ||
</WhiteCard> | ||
<Switch> | ||
<Route path={liveCreatePath} exact> | ||
<Modal | ||
isOpen | ||
onClose={() => { | ||
history.push(livePath); | ||
}} | ||
> | ||
<Heading | ||
level={2} | ||
margin={{ top: 'xxsmall' }} | ||
textAlign="center" | ||
weight="bold" | ||
> | ||
{intl.formatMessage(messages.CreateLiveLabel)} | ||
</Heading> | ||
<LiveCreateForm /> | ||
</Modal> | ||
</Route> | ||
</Switch> | ||
</Fragment> | ||
); | ||
}; | ||
|
||
export default LiveCreate; |
229 changes: 229 additions & 0 deletions
229
...dalone_site/src/features/Contents/features/Live/components/Create/LiveCreateForm.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
import { screen, fireEvent, waitFor } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import fetchMock from 'fetch-mock'; | ||
import { createMemoryHistory } from 'history'; | ||
import { render, Deferred } from 'lib-tests'; | ||
import { Router } from 'react-router-dom'; | ||
|
||
import LiveCreateForm from './LiveCreateForm'; | ||
|
||
const playlistsResponse = { | ||
count: 1, | ||
next: null, | ||
previous: null, | ||
results: [ | ||
{ id: 'some-playlist-id', title: 'some playlist title' }, | ||
{ id: 'an-other-playlist', title: 'an other title' }, | ||
], | ||
}; | ||
|
||
const consoleError = jest | ||
.spyOn(console, 'error') | ||
.mockImplementation(() => jest.fn()); | ||
|
||
let deferredPlaylists: Deferred<unknown>; | ||
describe('<LiveCreateForm />', () => { | ||
beforeEach(() => { | ||
deferredPlaylists = new Deferred(); | ||
fetchMock.get( | ||
'/api/playlists/?limit=20&offset=0&ordering=-created_on&can_edit=true', | ||
deferredPlaylists.promise, | ||
); | ||
}); | ||
|
||
afterEach(() => { | ||
fetchMock.restore(); | ||
jest.resetAllMocks(); | ||
consoleError.mockClear(); | ||
}); | ||
|
||
test('renders LiveCreateForm', async () => { | ||
render(<LiveCreateForm />); | ||
|
||
deferredPlaylists.resolve(playlistsResponse); | ||
|
||
expect(screen.getByRole('textbox', { name: /title/i })).toBeInTheDocument(); | ||
expect( | ||
await screen.findByRole('button', { | ||
name: 'Choose the playlist.; Selected: some-playlist-id', | ||
}), | ||
).toBeInTheDocument(); | ||
expect( | ||
screen.getByRole('textbox', { name: /description/i }), | ||
).toBeInTheDocument(); | ||
expect( | ||
screen.getByRole('button', { name: /Add Live/i }), | ||
).toBeInTheDocument(); | ||
}); | ||
|
||
test('fields mandatory', async () => { | ||
render(<LiveCreateForm />); | ||
|
||
deferredPlaylists.resolve(playlistsResponse); | ||
|
||
fireEvent.change(screen.getByRole('textbox', { name: /title/i }), { | ||
target: { value: 'my title' }, | ||
}); | ||
|
||
userEvent.click( | ||
await screen.findByRole('button', { | ||
name: 'Choose the playlist.; Selected: some-playlist-id', | ||
}), | ||
); | ||
|
||
userEvent.click( | ||
await screen.findByRole('option', { name: 'an other title' }), | ||
); | ||
|
||
expect( | ||
await screen.findByRole('button', { | ||
name: 'Choose the playlist.; Selected: an-other-playlist', | ||
}), | ||
).toBeInTheDocument(); | ||
|
||
await waitFor(() => | ||
expect( | ||
screen.getByRole('button', { name: /Add Live/i }), | ||
).not.toBeDisabled(), | ||
); | ||
}); | ||
|
||
test('fields are posted correctly', async () => { | ||
const history = createMemoryHistory(); | ||
fetchMock.post('/api/videos/', { | ||
ok: true, | ||
id: '1234', | ||
}); | ||
|
||
fetchMock.mock( | ||
'/api/videos/1234/initiate-live/', | ||
{ | ||
ok: true, | ||
id: '1234', | ||
is_live: true, | ||
}, | ||
{ | ||
method: 'POST', | ||
}, | ||
); | ||
|
||
render( | ||
<Router history={history}> | ||
<LiveCreateForm /> | ||
</Router>, | ||
); | ||
|
||
deferredPlaylists.resolve(playlistsResponse); | ||
|
||
fireEvent.change(screen.getByRole('textbox', { name: /title/i }), { | ||
target: { value: 'my title' }, | ||
}); | ||
|
||
fireEvent.change(screen.getByRole('textbox', { name: /description/i }), { | ||
target: { value: 'my description' }, | ||
}); | ||
|
||
userEvent.click( | ||
await screen.findByRole('button', { | ||
name: 'Choose the playlist.; Selected: some-playlist-id', | ||
}), | ||
); | ||
|
||
userEvent.click( | ||
await screen.findByRole('option', { name: 'an other title' }), | ||
); | ||
|
||
expect( | ||
await screen.findByRole('button', { | ||
name: 'Choose the playlist.; Selected: an-other-playlist', | ||
}), | ||
).toBeInTheDocument(); | ||
|
||
const submit = screen.getByRole('button', { name: /Add Live/i }); | ||
|
||
await waitFor(() => expect(submit).not.toBeDisabled()); | ||
|
||
userEvent.click(submit); | ||
|
||
await waitFor(() => { | ||
expect( | ||
fetchMock.lastCall('/api/videos/', { | ||
method: 'POST', | ||
})?.[1], | ||
).toEqual({ | ||
headers: { 'Content-Type': 'application/json' }, | ||
method: 'POST', | ||
body: JSON.stringify({ | ||
playlist: 'an-other-playlist', | ||
title: 'my title', | ||
live_type: 'jitsi', | ||
description: 'my description', | ||
}), | ||
}); | ||
}); | ||
|
||
await waitFor(() => { | ||
expect(history.location.pathname).toBe('/my-contents/lives/1234'); | ||
}); | ||
}); | ||
|
||
test('post failed', async () => { | ||
fetchMock.post('/api/videos/', 500); | ||
|
||
render(<LiveCreateForm />); | ||
|
||
deferredPlaylists.resolve(playlistsResponse); | ||
|
||
fireEvent.change(screen.getByRole('textbox', { name: /title/i }), { | ||
target: { value: 'my title' }, | ||
}); | ||
|
||
fireEvent.change(screen.getByRole('textbox', { name: /description/i }), { | ||
target: { value: 'my description' }, | ||
}); | ||
|
||
userEvent.click( | ||
await screen.findByRole('button', { | ||
name: 'Choose the playlist.; Selected: some-playlist-id', | ||
}), | ||
); | ||
|
||
userEvent.click( | ||
await screen.findByRole('option', { name: 'an other title' }), | ||
); | ||
|
||
expect( | ||
await screen.findByRole('button', { | ||
name: 'Choose the playlist.; Selected: an-other-playlist', | ||
}), | ||
).toBeInTheDocument(); | ||
|
||
const submit = screen.getByRole('button', { name: /Add Live/i }); | ||
|
||
await waitFor(() => expect(submit).not.toBeDisabled()); | ||
|
||
userEvent.click(submit); | ||
|
||
expect( | ||
await screen.findByText( | ||
/Sorry, an error has occurred. Please try again./i, | ||
), | ||
).toBeInTheDocument(); | ||
|
||
expect(consoleError).toHaveBeenCalled(); | ||
}); | ||
|
||
test('error playlist', async () => { | ||
render(<LiveCreateForm />); | ||
|
||
deferredPlaylists.resolve(500); | ||
|
||
expect( | ||
await screen.findByText( | ||
/Sorry, an error has occurred. Please try again./i, | ||
), | ||
).toBeInTheDocument(); | ||
|
||
expect(consoleError).toHaveBeenCalled(); | ||
}); | ||
}); |
Oops, something went wrong.