Skip to content

Commit b050535

Browse files
committed
fix: Fixes the auto_advance feature for video XBlock
The commit adds eventlistener which picks up the autoAdvance message and triggers the next sequence. This has the same effect of clicking the next button. Signed-off-by: Farhaan Bukhsh <[email protected]>
1 parent ddbc212 commit b050535

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

src/courseware/course/sequence/Unit/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const messageTypes = StrictDict({
1616
modal: 'plugin.modal',
1717
resize: 'plugin.resize',
1818
videoFullScreen: 'plugin.videoFullScreen',
19+
autoAdvance: 'plugin.autoAdvance',
1920
});
2021

2122
export default StrictDict({

src/courseware/course/sequence/Unit/hooks/useIFrameBehavior.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { getConfig } from '@edx/frontend-platform';
22
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
33
import React from 'react';
4-
import { useDispatch } from 'react-redux';
4+
import { useDispatch, useSelector } from 'react-redux';
5+
import { useNavigate } from 'react-router-dom';
56
import { throttle } from 'lodash';
67

78
import { StrictDict, useKeyedState } from '@edx/react-unit-test-utils';
@@ -10,6 +11,9 @@ import { logError } from '@edx/frontend-platform/logging';
1011
import { fetchCourse } from '@src/courseware/data';
1112
import { processEvent } from '@src/course-home/data/thunks';
1213
import { useEventListener } from '@src/generic/hooks';
14+
import { getSequenceId } from '@src/courseware/data/selectors';
15+
import { useModel } from '@src/generic/model-store';
16+
import { useSequenceNavigationMetadata } from '@src/courseware/course/sequence/sequence-navigation/hooks';
1317
import { messageTypes } from '../constants';
1418

1519
import useLoadBearingHook from './useLoadBearingHook';
@@ -19,6 +23,7 @@ export const stateKeys = StrictDict({
1923
hasLoaded: 'hasLoaded',
2024
showError: 'showError',
2125
windowTopOffset: 'windowTopOffset',
26+
sequences: 'sequences',
2227
});
2328

2429
const useIFrameBehavior = ({
@@ -31,6 +36,12 @@ const useIFrameBehavior = ({
3136
useLoadBearingHook(id);
3237

3338
const dispatch = useDispatch();
39+
const activeSequenceId = useSelector(getSequenceId);
40+
const navigate = useNavigate();
41+
const activeSequence = useModel(stateKeys.sequences, activeSequenceId);
42+
const activeUnitId = activeSequence.unitIds.length > 0
43+
? activeSequence.unitIds[activeSequence.activeUnitIndex] : null;
44+
const { isLastUnit, nextLink } = useSequenceNavigationMetadata(activeSequenceId, activeUnitId);
3445

3546
const [iframeHeight, setIframeHeight] = useKeyedState(stateKeys.iframeHeight, 0);
3647
const [hasLoaded, setHasLoaded] = useKeyedState(stateKeys.hasLoaded, false);
@@ -72,6 +83,12 @@ const useIFrameBehavior = ({
7283
// We listen for this message from LMS to know when the page needs to
7384
// be scrolled to another location on the page.
7485
window.scrollTo(0, data.offset + document.getElementById('unit-iframe').offsetTop);
86+
} else if (type === messageTypes.autoAdvance) {
87+
// We are listening to autoAdvance message to move to next sequence automatically.
88+
// In case it is the last unit we need not do anything.
89+
if (!isLastUnit) {
90+
navigate(nextLink);
91+
}
7592
}
7693
}, [
7794
id,

src/courseware/course/sequence/Unit/hooks/useIFrameBehavior.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ import { sendTrackEvent } from '@edx/frontend-platform/analytics';
99
import { fetchCourse } from '@src/courseware/data';
1010
import { processEvent } from '@src/course-home/data/thunks';
1111
import { useEventListener } from '@src/generic/hooks';
12+
import { useSequenceNavigationMetadata } from '@src/courseware/course/sequence/sequence-navigation/hooks';
1213

1314
import { messageTypes } from '../constants';
1415

1516
import useIFrameBehavior, { stateKeys } from './useIFrameBehavior';
1617

18+
const mockNavigate = jest.fn();
19+
1720
jest.mock('@edx/frontend-platform', () => ({
1821
getConfig: jest.fn(),
1922
}));
@@ -28,6 +31,7 @@ jest.mock('react', () => ({
2831

2932
jest.mock('react-redux', () => ({
3033
useDispatch: jest.fn(),
34+
useSelector: jest.fn(),
3135
}));
3236

3337
jest.mock('lodash', () => ({
@@ -50,6 +54,16 @@ jest.mock('@src/course-home/data/thunks', () => ({
5054
jest.mock('@src/generic/hooks', () => ({
5155
useEventListener: jest.fn(),
5256
}));
57+
jest.mock('@src/generic/model-store', () => ({
58+
useModel: () => ({ unitIds: ['unit1', 'unit2'], entranceExamData: { entranceExamPassed: null } }),
59+
}));
60+
jest.mock('react-router-dom', () => ({
61+
...jest.requireActual('react-router-dom'),
62+
useNavigate: () => mockNavigate,
63+
}));
64+
65+
jest.mock('@src/courseware/course/sequence/sequence-navigation/hooks');
66+
useSequenceNavigationMetadata.mockReturnValue({ isLastUnit: false, nextLink: '/next-unit-link' });
5367

5468
const state = mockUseKeyedState(stateKeys);
5569

@@ -373,4 +387,26 @@ describe('useIFrameBehavior hook', () => {
373387
expect(hook.hasLoaded).toEqual(stateVals.hasLoaded);
374388
});
375389
});
390+
describe('navigate link for the next unit on auto advance', () => {
391+
it('test for link when it is not last unit', () => {
392+
hook = useIFrameBehavior(props);
393+
const { cb } = useEventListener.mock.calls[0][1];
394+
const autoAdvanceMessage = () => ({
395+
data: { type: messageTypes.autoAdvance },
396+
});
397+
cb(autoAdvanceMessage());
398+
expect(mockNavigate).toHaveBeenCalledWith('/next-unit-link');
399+
});
400+
it('test for link when it is last unit', () => {
401+
useSequenceNavigationMetadata.mockReset();
402+
useSequenceNavigationMetadata.mockReturnValue({ isLastUnit: true, nextLink: '/next-unit-link' });
403+
hook = useIFrameBehavior(props);
404+
const { cb } = useEventListener.mock.calls[0][1];
405+
const autoAdvanceMessage = () => ({
406+
data: { type: messageTypes.autoAdvance },
407+
});
408+
cb(autoAdvanceMessage());
409+
expect(mockNavigate).not.toHaveBeenCalled();
410+
});
411+
});
376412
});

0 commit comments

Comments
 (0)