mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2025-02-19 19:07:47 -05:00
Move timeout id out of state to a member variable and add some unittests.
This commit is contained in:
parent
fac3ccad57
commit
0036550ae8
2 changed files with 48 additions and 19 deletions
|
@ -30,15 +30,14 @@ class Navigation extends React.Component {
|
||||||
'handleSearchSubmit',
|
'handleSearchSubmit',
|
||||||
'pollForMessages'
|
'pollForMessages'
|
||||||
]);
|
]);
|
||||||
this.state = {
|
// Keep the timeout id so we can cancel it (e.g. when we unmount)
|
||||||
messageCountIntervalId: -1 // javascript method interval id for getting messsage count.
|
this.messageCountTimeoutId = -1;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
if (this.props.user) {
|
if (this.props.user) {
|
||||||
// Setup polling for messages to start in 2 minutes.
|
// Setup polling for messages to start in 2 minutes.
|
||||||
const twoMinInMs = 2 * 60 * 1000;
|
const twoMinInMs = 2 * 60 * 1000;
|
||||||
setTimeout(this.pollForMessages.bind(this, twoMinInMs), twoMinInMs);
|
this.messageCountTimeoutId = setTimeout(this.pollForMessages.bind(this, twoMinInMs), twoMinInMs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidUpdate (prevProps) {
|
componentDidUpdate (prevProps) {
|
||||||
|
@ -46,25 +45,21 @@ class Navigation extends React.Component {
|
||||||
this.props.handleCloseAccountNav();
|
this.props.handleCloseAccountNav();
|
||||||
if (this.props.user) {
|
if (this.props.user) {
|
||||||
const twoMinInMs = 2 * 60 * 1000;
|
const twoMinInMs = 2 * 60 * 1000;
|
||||||
setTimeout(this.pollForMessages.bind(this, twoMinInMs), twoMinInMs);
|
this.messageCountTimeoutId = setTimeout(this.pollForMessages.bind(this, twoMinInMs), twoMinInMs);
|
||||||
} else {
|
} else {
|
||||||
// clear message count check, and set to default id.
|
// clear message count check, and set to default id.
|
||||||
clearTimeout(this.state.messageCountIntervalId);
|
clearTimeout(this.messageCountTimeoutId);
|
||||||
this.props.setMessageCount(0);
|
this.props.setMessageCount(0);
|
||||||
this.setState({ // eslint-disable-line react/no-did-update-set-state
|
this.messageCountTimeoutId = -1;
|
||||||
messageCountIntervalId: -1
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
// clear message interval if it exists
|
// clear message interval if it exists
|
||||||
if (this.state.messageCountIntervalId !== -1) {
|
if (this.messageCountTimeoutId !== -1) {
|
||||||
clearTimeout(this.state.messageCountIntervalId);
|
clearTimeout(this.messageCountTimeoutId);
|
||||||
this.props.setMessageCount(0);
|
this.props.setMessageCount(0);
|
||||||
this.setState({
|
this.messageCountTimeoutId = -1;
|
||||||
messageCountIntervalId: -1
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getProfileUrl () {
|
getProfileUrl () {
|
||||||
|
@ -82,9 +77,7 @@ class Navigation extends React.Component {
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
this.pollForMessages(nextFetch);
|
this.pollForMessages(nextFetch);
|
||||||
}, nextFetch);
|
}, nextFetch);
|
||||||
this.setState({ // eslint-disable-line react/no-did-mount-set-state
|
this.messageCountTimeoutId = timeoutId;
|
||||||
messageCountIntervalId: timeoutId
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,14 +128,49 @@ describe('Navigation', () => {
|
||||||
childContextTypes: {store}
|
childContextTypes: {store}
|
||||||
});
|
});
|
||||||
|
|
||||||
intlWrapper.children().find('Navigation')
|
const navInstance = intlWrapper.children().find('Navigation')
|
||||||
.instance();
|
.instance();
|
||||||
const twoMin = 2 * 60 * 1000;
|
const twoMin = 2 * 60 * 1000;
|
||||||
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), twoMin);
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), twoMin);
|
||||||
|
expect(navInstance.messageCountTimeoutId).not.toEqual(-1);
|
||||||
// Advance timers passed the intial two minutes.
|
// Advance timers passed the intial two minutes.
|
||||||
jest.advanceTimersByTime(twoMin + 1);
|
jest.advanceTimersByTime(twoMin + 1);
|
||||||
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), twoMin * 2);
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), twoMin * 2);
|
||||||
expect(props.getMessageCount).toHaveBeenCalled();
|
expect(props.getMessageCount).toHaveBeenCalled();
|
||||||
|
expect(navInstance.messageCountTimeoutId).not.toEqual(-1);
|
||||||
|
});
|
||||||
|
test('Component cancels timers when it unmounts', () => {
|
||||||
|
store = mockStore({
|
||||||
|
navigation: {
|
||||||
|
registrationOpen: false
|
||||||
|
},
|
||||||
|
messageCount: {
|
||||||
|
messageCount: 5
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const props = {
|
||||||
|
user: {
|
||||||
|
thumbnailUrl: 'scratch.mit.edu',
|
||||||
|
username: 'auser'
|
||||||
|
},
|
||||||
|
getMessageCount: jest.fn()
|
||||||
|
};
|
||||||
|
const intlWrapper = mountWithIntl(
|
||||||
|
<Navigation
|
||||||
|
{...props}
|
||||||
|
/>, {context: {store},
|
||||||
|
childContextTypes: {store}
|
||||||
|
});
|
||||||
|
|
||||||
|
const navInstance = intlWrapper.children().find('Navigation')
|
||||||
|
.instance();
|
||||||
|
const twoMin = 2 * 60 * 1000;
|
||||||
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), twoMin);
|
||||||
|
expect(navInstance.messageCountTimeoutId).not.toEqual(-1);
|
||||||
|
debugger;
|
||||||
|
navInstance.componentWillUnmount();
|
||||||
|
expect(clearTimeout).toHaveBeenCalledWith(expect.any(Number));
|
||||||
|
expect(navInstance.messageCountTimeoutId).toEqual(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('pollForMessages polls for messages 5 times', () => {
|
test('pollForMessages polls for messages 5 times', () => {
|
||||||
|
@ -170,8 +205,8 @@ describe('Navigation', () => {
|
||||||
let twoMinInMs = 2 * 60 * 1000; // 2 minutes in ms.
|
let twoMinInMs = 2 * 60 * 1000; // 2 minutes in ms.
|
||||||
navInstance.pollForMessages(twoMinInMs);
|
navInstance.pollForMessages(twoMinInMs);
|
||||||
|
|
||||||
|
expect(navInstance.messageCountTimeoutId).not.toEqual(-1);
|
||||||
// Check that we set the timeout to backoff exponentially
|
// Check that we set the timeout to backoff exponentially
|
||||||
|
|
||||||
for (let count = 1; count < 5; ++count) {
|
for (let count = 1; count < 5; ++count) {
|
||||||
jest.advanceTimersByTime(twoMinInMs + 1);
|
jest.advanceTimersByTime(twoMinInMs + 1);
|
||||||
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), twoMinInMs * 2);
|
expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), twoMinInMs * 2);
|
||||||
|
@ -187,5 +222,6 @@ describe('Navigation', () => {
|
||||||
// setTimeout happens 1 fewer since the original call to
|
// setTimeout happens 1 fewer since the original call to
|
||||||
// pollForMessages isn't counted here.
|
// pollForMessages isn't counted here.
|
||||||
expect(setTimeout).toHaveBeenCalledTimes(4);
|
expect(setTimeout).toHaveBeenCalledTimes(4);
|
||||||
|
expect(navInstance.messageCountTimeoutId).not.toEqual(-1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue