Skip to content

Commit

Permalink
♻️(lib_video) manage sharing error when one resource is already shared
Browse files Browse the repository at this point in the history
When a user tried to share a resource when another
one was already shared, the sharing was not started and an
error was displayed.
We now stop the sharing of the first resource and start the sharing
of the new one if we get the error 'Video is already sharing' from
the backend.
  • Loading branch information
AntoLC committed Nov 23, 2023
1 parent 5da5470 commit f50d718
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@ import {
useMutation,
useQueryClient,
} from '@tanstack/react-query';
import { SharedLiveMedia, actionOne } from 'lib-components';
import { FetchResponseError, SharedLiveMedia, actionOne } from 'lib-components';

type UseStartSharingData = { sharedlivemedia: string };
type UseStartSharingError =
| { code: 'exception' }
| {
code: 'invalid';
errors: { [key in keyof UseStartSharingData]?: string[] }[];
};
type UseStartSharingError = FetchResponseError<UseStartSharingData>;
type UseStartSharingLiveMediaOptions = UseMutationOptions<
SharedLiveMedia,
UseStartSharingError,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
useJwt,
videoMockFactory,
} from 'lib-components';
import { render } from 'lib-tests';
import { Deferred, render } from 'lib-tests';

import { ToggleSharing } from '.';

Expand Down Expand Up @@ -229,4 +229,89 @@ describe('<ToggleSharing />', () => {
expect(report).toHaveBeenCalled();
screen.getByText('Shared media update has failed !');
});

it('retries to share if failed because a resource is already sharing', async () => {
const mockedSharedLiveMedia = sharedLiveMediaMockFactory({
video: faker.string.uuid(),
});
const mockedVideo = videoMockFactory({
id: mockedSharedLiveMedia.video,
shared_live_medias: [mockedSharedLiveMedia],
});

const deferredStartSharing1 = new Deferred();
const deferredStartSharing2 = new Deferred();
const deferredEndSharing = new Deferred();

fetchMock.patchOnce(
`/api/videos/${mockedVideo.id}/start-sharing/`,
deferredStartSharing1.promise,
);

fetchMock.patchOnce(
`/api/videos/${mockedVideo.id}/end-sharing/`,
deferredEndSharing.promise,
);

render(
<ToggleSharing
isShared={false}
sharedLiveMediaId={mockedSharedLiveMedia.id}
videoId={mockedSharedLiveMedia.video}
/>,
);

const input: HTMLInputElement = screen.getByRole('checkbox', {
name: 'Share support',
});

await userEvent.click(input);

deferredStartSharing1.resolve({
status: 400,
body: {
detail: 'Video is already sharing.',
},
});

await waitFor(() => expect(fetchMock.calls()).toHaveLength(1));
expect(
fetchMock.called(`/api/videos/${mockedVideo.id}/start-sharing/`),
).toBeTruthy();

fetchMock.patchOnce(
`/api/videos/${mockedVideo.id}/start-sharing/`,
deferredStartSharing2.promise,
{
overwriteRoutes: true,
},
);

deferredEndSharing.resolve(mockedVideo);

await waitFor(() =>
expect(fetchMock.lastCall()![0]).toEqual(
`/api/videos/${mockedVideo.id}/end-sharing/`,
),
);

deferredStartSharing2.resolve({
...mockedVideo,
active_shared_live_media: mockedSharedLiveMedia,
active_shared_live_media_page: 1,
});

await waitFor(() => expect(fetchMock.calls()).toHaveLength(3));
expect(fetchMock.lastCall()![0]).toEqual(
`/api/videos/${mockedVideo.id}/start-sharing/`,
);

expect(report).not.toHaveBeenCalled();

expect(
screen.queryByText('Shared media update has failed !'),
).not.toBeInTheDocument();

expect(screen.getByText('Shared media updated.')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -38,50 +38,91 @@ export const ToggleSharing = ({
videoId,
}: ToggleSharingProps) => {
const intl = useIntl();
const shareMediaStart = useStartSharingMedia(videoId, {
onSuccess: () => {
toast.success(intl.formatMessage(messages.updateSharedLiveMediaSucces), {
position: 'bottom-center',
});
},
onError: (err: unknown) => {
report(err);
toast.error(intl.formatMessage(messages.updateSharedLiveMediaFail), {
position: 'bottom-center',
});
setIsLocalShared(isShared);
},
});
const [shouldRetrySharing, setShouldRetrySharing] = useState(false);
const { mutate: startSharing, isLoading: isStartSharingLoading } =
useStartSharingMedia(videoId, {
onSuccess: () => {
toast.success(
intl.formatMessage(messages.updateSharedLiveMediaSucces),
{
position: 'bottom-center',
},
);
},
onError: (err) => {
if (err.detail?.includes('Video is already sharing')) {
setShouldRetrySharing(true);
stopSharing();
return;
}

const shareMediaStop = useStopSharingMedia(videoId, {
onSuccess: () => {
toast.success(intl.formatMessage(messages.updateSharedLiveMediaSucces), {
position: 'bottom-center',
});
},
onError: (err: unknown) => {
report(err);
toast.error(intl.formatMessage(messages.updateSharedLiveMediaFail), {
position: 'bottom-center',
});
setIsLocalShared(isShared);
},
});
report(err);
toast.error(intl.formatMessage(messages.updateSharedLiveMediaFail), {
position: 'bottom-center',
});
setIsLocalShared(isShared);
},
});

const { mutate: stopSharing, isSuccess: isStopSharingSuccess } =
useStopSharingMedia(videoId, {
onSuccess: () => {
if (shouldRetrySharing) {
return;
}

toast.success(
intl.formatMessage(messages.updateSharedLiveMediaSucces),
{
position: 'bottom-center',
},
);
},
onError: (err) => {
setShouldRetrySharing(false);
report(err);
toast.error(intl.formatMessage(messages.updateSharedLiveMediaFail), {
position: 'bottom-center',
});
setIsLocalShared(isShared);
},
});

const [isLocalShared, setIsLocalShared] = useState(isShared);

useEffect(() => {
if (!isStopSharingSuccess || !shouldRetrySharing) {
return;
}

startSharing({
sharedlivemedia: sharedLiveMediaId,
});

setShouldRetrySharing(false);
}, [
isStopSharingSuccess,
startSharing,
sharedLiveMediaId,
shouldRetrySharing,
]);

useEffect(() => {
if (shouldRetrySharing || isStartSharingLoading) {
return;
}

setIsLocalShared(isShared);
}, [isShared]);
}, [isShared, isStartSharingLoading, shouldRetrySharing]);

return (
<Switch
checked={!!isLocalShared}
onChange={() => {
setIsLocalShared(!isLocalShared);
isLocalShared
? shareMediaStop.mutate()
: shareMediaStart.mutate({
? stopSharing()
: startSharing({
sharedlivemedia: sharedLiveMediaId,
});
}}
Expand Down

0 comments on commit f50d718

Please sign in to comment.