diff --git a/ee/app/assets/javascripts/vulnerabilities/components/footer.vue b/ee/app/assets/javascripts/vulnerabilities/components/footer.vue index cf9b29c70dd363a165d2bb2ebfc3fa8114b25298..fef5b11bdbedf396fa7ff41a6814392e8d7f7300 100644 --- a/ee/app/assets/javascripts/vulnerabilities/components/footer.vue +++ b/ee/app/assets/javascripts/vulnerabilities/components/footer.vue @@ -71,6 +71,7 @@ export default { this.discussionsLoading = false; this.notifyHeaderForStateChangeIfRequired(); this.startPolling(); + this.bindVisibilityListener(); }, error() { this.showGraphQLError(); @@ -114,6 +115,7 @@ export default { }, beforeDestroy() { this.stopPolling(); + this.unbindVisibilityListener(); }, updated() { this.$nextTick(() => { @@ -129,6 +131,17 @@ export default { if (!Visibility.hidden()) { this.pollInterval = setInterval(this.fetchDiscussions, TEN_SECONDS); } + }, + stopPolling() { + if (typeof this.pollInterval !== 'undefined') { + clearInterval(this.pollInterval); + this.pollInterval = undefined; + } + }, + bindVisibilityListener() { + if (this.visibilityListener) { + return; + } this.visibilityListener = Visibility.change(() => { if (Visibility.hidden()) { @@ -138,12 +151,7 @@ export default { } }); }, - stopPolling() { - if (typeof this.pollInterval !== 'undefined') { - clearInterval(this.pollInterval); - this.pollInterval = undefined; - } - + unbindVisibilityListener() { if (typeof this.visibilityListener !== 'undefined') { Visibility.unbind(this.visibilityListener); this.visibilityListener = undefined; diff --git a/ee/spec/frontend/vulnerabilities/footer_spec.js b/ee/spec/frontend/vulnerabilities/footer_spec.js index b31abe34dd477f1fb6064f90b8e5c2e2db1a08c3..1e199675827725296a7fd9522c3ee072a4252b24 100644 --- a/ee/spec/frontend/vulnerabilities/footer_spec.js +++ b/ee/spec/frontend/vulnerabilities/footer_spec.js @@ -174,6 +174,23 @@ describe('Vulnerability Footer', () => { expect(visibilityUnbindSpy).toHaveBeenCalled(); }); + it('does not remove the listener when the visibility changes', async () => { + const clearIntervalSpy = jest.spyOn(window, 'clearInterval'); + const visibilityUnbindSpy = jest.spyOn(Visibility, 'unbind'); + const visibilityHiddenSpy = jest + .spyOn(Visibility, 'hidden') + .mockImplementationOnce(() => false) // This is called in startPolling + .mockImplementationOnce(() => true); // This is called in visibilityChangeListener + const visibilityChangeSpy = jest + .spyOn(Visibility, 'change') + .mockImplementation((callback) => callback()); + await createWrapperAndFetchDiscussions({ discussions: [] }); + expect(visibilityHiddenSpy).toHaveBeenCalled(); + expect(visibilityChangeSpy).toHaveBeenCalled(); + expect(clearIntervalSpy).toHaveBeenCalled(); + expect(visibilityUnbindSpy).not.toHaveBeenCalled(); + }); + it('emits the vulnerability-state-change event when the system note is new', async () => { const eventName = 'vulnerability-state-change'; const queryHandler = discussionsHandler({ discussions: [discussion1] }); // first call