diff --git a/services/web/frontend/stories/binary-file.stories.js b/services/web/frontend/stories/binary-file.stories.js
index 6d3c7252d8..fb459c47eb 100644
--- a/services/web/frontend/stories/binary-file.stories.js
+++ b/services/web/frontend/stories/binary-file.stories.js
@@ -1,23 +1,24 @@
import React from 'react'
import BinaryFile from '../js/features/binary-file/components/binary-file'
-import fetchMock from 'fetch-mock'
+import useFetchMock from './hooks/use-fetch-mock'
window.project_id = 'proj123'
-fetchMock.restore()
-fetchMock.head('express:/project/:project_id/file/:file_id', {
- status: 201,
- headers: { 'Content-Length': 10000 },
-})
-fetchMock.get('express:/project/:project_id/file/:file_id', 'Text file content')
-fetchMock.post('express:/project/:project_id/linked_file/:file_id/refresh', {
- status: 204,
-})
-
-fetchMock.post('express:/project/:project_id/references/indexAll', {
- status: 204,
-})
+const setupFetchMock = fetchMock => {
+ fetchMock
+ .head('express:/project/:project_id/file/:file_id', {
+ status: 201,
+ headers: { 'Content-Length': 10000 },
+ })
+ .get('express:/project/:project_id/file/:file_id', 'Text file content')
+ .post('express:/project/:project_id/linked_file/:file_id/refresh', {
+ status: 204,
+ })
+ .post('express:/project/:project_id/references/indexAll', {
+ status: 204,
+ })
+}
window.project_id = '1234'
@@ -173,10 +174,14 @@ export default {
storeReferencesKeys: () => {},
},
decorators: [
- BinaryFile => (
+ Story => {
+ useFetchMock(setupFetchMock)
+ return
+ },
+ Story => (
<>
-
+
>
),
],
diff --git a/services/web/frontend/stories/chat.stories.js b/services/web/frontend/stories/chat.stories.js
index 884e170e40..c662ebfea4 100644
--- a/services/web/frontend/stories/chat.stories.js
+++ b/services/web/frontend/stories/chat.stories.js
@@ -1,11 +1,11 @@
import React from 'react'
-import fetchMock from 'fetch-mock'
import { v4 as uuid } from 'uuid'
import { ContextRoot } from '../js/shared/context/root-context'
import ChatPane from '../js/features/chat/components/chat-pane'
import { stubMathJax } from '../../test/frontend/features/chat/components/stubs'
import { setupContext } from './fixtures/context'
+import useFetchMock from './hooks/use-fetch-mock'
const ONE_MINUTE = 60 * 1000
@@ -43,31 +43,30 @@ function generateMessages(count) {
stubMathJax()
setupContext()
-export const Conversation = args =>
-Conversation.parameters = {
- setupMocks: () => {
- fetchMock.restore()
- fetchMock.get(/messages/, generateMessages(35))
- fetchMock.post(/messages/, {})
- },
+export const Conversation = args => {
+ useFetchMock(fetchMock => {
+ fetchMock.get(/messages/, generateMessages(35)).post(/messages/, {})
+ })
+
+ return
}
-export const NoMessages = args =>
-NoMessages.parameters = {
- setupMocks: () => {
- fetchMock.restore()
+export const NoMessages = args => {
+ useFetchMock(fetchMock => {
fetchMock.get(/messages/, [])
- },
+ })
+
+ return
}
-export const Loading = args =>
-Loading.parameters = {
- setupMocks: () => {
- fetchMock.restore()
+export const Loading = args => {
+ useFetchMock(fetchMock => {
fetchMock.get(/messages/, generateMessages(6), {
delay: 1000 * 10,
})
- },
+ })
+
+ return
}
export default {
@@ -80,10 +79,6 @@ export default {
resetUnreadMessages: () => {},
},
decorators: [
- (Story, { parameters: { setupMocks } }) => {
- if (setupMocks) setupMocks()
- return
- },
Story => (
<>
diff --git a/services/web/frontend/stories/clone-project-modal.stories.js b/services/web/frontend/stories/clone-project-modal.stories.js
index 86437822e0..7d20ea6d93 100644
--- a/services/web/frontend/stories/clone-project-modal.stories.js
+++ b/services/web/frontend/stories/clone-project-modal.stories.js
@@ -1,27 +1,29 @@
import React from 'react'
-import fetchMock from 'fetch-mock'
import PropTypes from 'prop-types'
import CloneProjectModal from '../js/features/clone-project-modal/components/clone-project-modal'
+import useFetchMock from './hooks/use-fetch-mock'
export const Interactive = ({
mockResponse = 200,
mockResponseDelay = 500,
...args
}) => {
- fetchMock.restore().post(
- 'express:/project/:projectId/clone',
- () => {
- switch (mockResponse) {
- case 400:
- return { status: 400, body: 'The project name is not valid' }
+ useFetchMock(fetchMock => {
+ fetchMock.post(
+ 'express:/project/:projectId/clone',
+ () => {
+ switch (mockResponse) {
+ case 400:
+ return { status: 400, body: 'The project name is not valid' }
- default:
- return mockResponse
- }
- },
- { delay: mockResponseDelay }
- )
+ default:
+ return mockResponse
+ }
+ },
+ { delay: mockResponseDelay }
+ )
+ })
return
}
diff --git a/services/web/frontend/stories/file-tree.stories.js b/services/web/frontend/stories/file-tree.stories.js
index 6b8e0d54a4..ef4c589fb0 100644
--- a/services/web/frontend/stories/file-tree.stories.js
+++ b/services/web/frontend/stories/file-tree.stories.js
@@ -1,11 +1,11 @@
import React from 'react'
-import fetchMock from 'fetch-mock'
import MockedSocket from 'socket.io-mock'
import { rootFolderBase } from './fixtures/file-tree-base'
import { rootFolderLimit } from './fixtures/file-tree-limit'
import FileTreeRoot from '../js/features/file-tree/components/file-tree-root'
import FileTreeError from '../js/features/file-tree/components/file-tree-error'
+import useFetchMock from './hooks/use-fetch-mock'
const MOCK_DELAY = 2000
@@ -13,9 +13,8 @@ window._ide = {
socket: new MockedSocket(),
}
-function defaultSetupMocks() {
+function defaultSetupMocks(fetchMock) {
fetchMock
- .restore()
.post(
/\/project\/\w+\/(file|doc|folder)\/\w+\/rename/,
(path, req) => {
@@ -78,8 +77,11 @@ function defaultSetupMocks() {
})
}
-export const FullTree = args =>
-FullTree.parameters = { setupMocks: defaultSetupMocks }
+export const FullTree = args => {
+ useFetchMock(defaultSetupMocks)
+
+ return
+}
export const ReadOnly = args =>
ReadOnly.args = { hasWritePermissions: false }
@@ -87,28 +89,34 @@ ReadOnly.args = { hasWritePermissions: false }
export const Disconnected = args =>
Disconnected.args = { isConnected: false }
-export const NetworkErrors = args =>
-NetworkErrors.parameters = {
- setupMocks: () => {
+export const NetworkErrors = args => {
+ useFetchMock(fetchMock => {
fetchMock
- .restore()
.post(/\/project\/\w+\/folder/, 500, {
delay: MOCK_DELAY,
})
.post(/\/project\/\w+\/(file|doc|folder)\/\w+\/rename/, 500, {
delay: MOCK_DELAY,
})
+ .post(/\/project\/\w+\/(file|doc|folder)\/\w+\/move/, 500, {
+ delay: MOCK_DELAY,
+ })
.delete(/\/project\/\w+\/(file|doc|folder)\/\w+/, 500, {
delay: MOCK_DELAY,
})
- },
+ })
+
+ return
}
export const FallbackError = args =>
-export const FilesLimit = args =>
+export const FilesLimit = args => {
+ useFetchMock(defaultSetupMocks)
+
+ return
+}
FilesLimit.args = { rootFolder: rootFolderLimit }
-FilesLimit.parameters = { setupMocks: defaultSetupMocks }
export default {
title: 'File Tree',
@@ -136,10 +144,6 @@ export default {
onSelect: { action: 'onSelect' },
},
decorators: [
- (Story, { parameters: { setupMocks } }) => {
- if (setupMocks) setupMocks()
- return
- },
Story => (
<>
diff --git a/services/web/frontend/stories/git-bridge-modal.stories.js b/services/web/frontend/stories/git-bridge-modal.stories.js
index 800c58c25d..f3e9a23d88 100644
--- a/services/web/frontend/stories/git-bridge-modal.stories.js
+++ b/services/web/frontend/stories/git-bridge-modal.stories.js
@@ -2,6 +2,7 @@ import React from 'react'
import { ContextRoot } from '../js/shared/context/root-context'
import { setupContext } from './fixtures/context'
import importOverleafModules from '../macros/import-overleaf-module.macro'
+import useFetchMock from './hooks/use-fetch-mock'
const [
{
@@ -21,7 +22,11 @@ CollaboratorModal.args = {
type: 'collaborator',
}
-export const TeaserModal = args =>
+export const TeaserModal = args => {
+ useFetchMock(fetchMock => fetchMock.post('express:/event/:key', 202))
+
+ return
+}
TeaserModal.args = {
type: 'teaser',
}
@@ -34,7 +39,6 @@ export default {
},
argTypes: {
handleHide: { action: 'handleHide' },
- startFreeTrial: { action: 'startFreeTrial' },
},
decorators: [
Story => (
diff --git a/services/web/frontend/stories/hooks/use-fetch-mock.js b/services/web/frontend/stories/hooks/use-fetch-mock.js
new file mode 100644
index 0000000000..0998f70a30
--- /dev/null
+++ b/services/web/frontend/stories/hooks/use-fetch-mock.js
@@ -0,0 +1,21 @@
+import { useEffect } from 'react'
+import fetchMock from 'fetch-mock'
+
+/**
+ * Run callback to mock fetch routes, call restore() when unmounted
+ */
+export default function useFetchMock(callback) {
+ useEffect(() => {
+ return () => {
+ fetchMock.restore()
+ }
+ }, [])
+
+ // Running fetchMock.restore() here as well,
+ // in case there was an error before the component was unmounted.
+ fetchMock.restore()
+
+ // The callback has to be run here, rather than in useEffect,
+ // so it's run before the component is rendered.
+ callback(fetchMock)
+}
diff --git a/services/web/frontend/stories/share-project-modal.stories.js b/services/web/frontend/stories/share-project-modal.stories.js
index 7f8819b0dd..5d34cad6b0 100644
--- a/services/web/frontend/stories/share-project-modal.stories.js
+++ b/services/web/frontend/stories/share-project-modal.stories.js
@@ -1,6 +1,6 @@
import React, { useEffect } from 'react'
-import fetchMock from 'fetch-mock'
import ShareProjectModal from '../js/features/share-project-modal/components/share-project-modal'
+import useFetchMock from './hooks/use-fetch-mock'
const contacts = [
// user with edited name
@@ -44,11 +44,10 @@ const contacts = [
},
]
-const setupFetchMock = () => {
+const setupFetchMock = fetchMock => {
const delay = 1000
fetchMock
- .restore()
// list contacts
.get('express:/user/contacts', { contacts }, { delay })
// change privacy setting
@@ -86,7 +85,7 @@ const ideWithProject = project => {
}
export const LinkSharingOff = args => {
- setupFetchMock()
+ useFetchMock(setupFetchMock)
const project = {
...args.project,
@@ -97,7 +96,7 @@ export const LinkSharingOff = args => {
}
export const LinkSharingOn = args => {
- setupFetchMock()
+ useFetchMock(setupFetchMock)
const project = {
...args.project,
@@ -108,7 +107,7 @@ export const LinkSharingOn = args => {
}
export const LinkSharingLoading = args => {
- setupFetchMock()
+ useFetchMock(setupFetchMock)
const project = {
...args.project,
@@ -167,7 +166,7 @@ export const RestrictedTokenMember = args => {
}
export const LegacyLinkSharingReadAndWrite = args => {
- setupFetchMock()
+ useFetchMock(setupFetchMock)
const project = {
...args.project,
@@ -178,7 +177,7 @@ export const LegacyLinkSharingReadAndWrite = args => {
}
export const LegacyLinkSharingReadOnly = args => {
- setupFetchMock()
+ useFetchMock(setupFetchMock)
const project = {
...args.project,
@@ -189,7 +188,7 @@ export const LegacyLinkSharingReadOnly = args => {
}
export const LimitedCollaborators = args => {
- setupFetchMock()
+ useFetchMock(setupFetchMock)
const project = {
...args.project,
diff --git a/services/web/frontend/stories/word-count-modal.stories.js b/services/web/frontend/stories/word-count-modal.stories.js
index d0e1cc6d24..e3cbd1e80b 100644
--- a/services/web/frontend/stories/word-count-modal.stories.js
+++ b/services/web/frontend/stories/word-count-modal.stories.js
@@ -1,37 +1,39 @@
import React from 'react'
-import fetchMock from 'fetch-mock'
import PropTypes from 'prop-types'
import WordCountModal from '../js/features/word-count-modal/components/word-count-modal'
+import useFetchMock from './hooks/use-fetch-mock'
export const Interactive = ({
mockResponse = 200,
mockResponseDelay = 500,
...args
}) => {
- fetchMock.restore().get(
- 'express:/project/:projectId/wordcount',
- () => {
- switch (mockResponse) {
- case 400:
- return { status: 400, body: 'The project id is not valid' }
+ useFetchMock(fetchMock => {
+ fetchMock.get(
+ 'express:/project/:projectId/wordcount',
+ () => {
+ switch (mockResponse) {
+ case 400:
+ return { status: 400, body: 'The project id is not valid' }
- case 200:
- return {
- texcount: {
- headers: 4,
- mathDisplay: 40,
- mathInline: 400,
- textWords: 4000,
- },
- }
+ case 200:
+ return {
+ texcount: {
+ headers: 4,
+ mathDisplay: 40,
+ mathInline: 400,
+ textWords: 4000,
+ },
+ }
- default:
- return mockResponse
- }
- },
- { delay: mockResponseDelay }
- )
+ default:
+ return mockResponse
+ }
+ },
+ { delay: mockResponseDelay }
+ )
+ })
return
}