diff --git a/awx/ui_next/package-lock.json b/awx/ui_next/package-lock.json index 049b48ad8d..12df9b3259 100644 --- a/awx/ui_next/package-lock.json +++ b/awx/ui_next/package-lock.json @@ -8988,6 +8988,12 @@ } } }, + "jest-websocket-mock": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jest-websocket-mock/-/jest-websocket-mock-2.0.2.tgz", + "integrity": "sha512-SFTUI8O/LDGqROOMnfAzbrrX5gQ8GDhRqkzVrt8Y67evnFKccRPFI3ymS05tKcMONvVfxumat4pX/LRjM/CjVg==", + "dev": true + }, "jest-worker": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", @@ -9893,6 +9899,15 @@ "minimist": "^1.2.5" } }, + "mock-socket": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.0.3.tgz", + "integrity": "sha512-SxIiD2yE/By79p3cNAAXyLQWTvEFNEzcAO7PH+DzRqKSFaplAPFjiQLmw8ofmpCsZf+Rhfn2/xCJagpdGmYdTw==", + "dev": true, + "requires": { + "url-parse": "^1.4.4" + } + }, "moo": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", diff --git a/awx/ui_next/package.json b/awx/ui_next/package.json index e5ca6eb7f2..74f857ce63 100644 --- a/awx/ui_next/package.json +++ b/awx/ui_next/package.json @@ -72,6 +72,8 @@ "eslint-plugin-react": "^7.11.1", "eslint-plugin-react-hooks": "^2.2.0", "http-proxy-middleware": "^1.0.3", + "jest-websocket-mock": "^2.0.2", + "mock-socket": "^9.0.3", "prettier": "^1.18.2" }, "jest": { diff --git a/awx/ui_next/src/components/JobList/useThrottle.js b/awx/ui_next/src/components/JobList/useThrottle.js new file mode 100644 index 0000000000..cfdedfecfc --- /dev/null +++ b/awx/ui_next/src/components/JobList/useThrottle.js @@ -0,0 +1,21 @@ +import { useState, useEffect, useRef } from 'react'; + +export default function useThrottle(value, limit) { + const [throttledValue, setThrottledValue] = useState(value); + const lastRan = useRef(Date.now()); + + useEffect(() => { + const handler = setTimeout(() => { + if (Date.now() - lastRan.current >= limit) { + setThrottledValue(value); + lastRan.current = Date.now(); + } + }, limit - (Date.now() - lastRan.current)); + + return () => { + clearTimeout(handler); + }; + }, [value, limit]); + + return throttledValue; +} diff --git a/awx/ui_next/src/components/JobList/useThrottle.test.jsx b/awx/ui_next/src/components/JobList/useThrottle.test.jsx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/awx/ui_next/src/components/JobList/useWsJobs.js b/awx/ui_next/src/components/JobList/useWsJobs.js index 8602bc98c3..ab543d6d8e 100644 --- a/awx/ui_next/src/components/JobList/useWsJobs.js +++ b/awx/ui_next/src/components/JobList/useWsJobs.js @@ -1,10 +1,10 @@ import { useState, useEffect, useRef } from 'react'; +import useThrottle from './useThrottle'; export default function useWsJobs(initialJobs, fetchJobsById, filtersApplied) { const [jobs, setJobs] = useState(initialJobs); const [lastMessage, setLastMessage] = useState(null); const [jobsToFetch, setJobsToFetch] = useState([]); - // const debouncedJobsToFetch = useDebounce(jobsToFetch, 5000); const throttleJobsToFetch = useThrottle(jobsToFetch, 5000); useEffect(() => { @@ -101,23 +101,3 @@ function updateJob(jobs, index, message) { }; return [...jobs.slice(0, index), job, ...jobs.slice(index + 1)]; } - -function useThrottle(value, limit) { - const [throttledValue, setThrottledValue] = useState(value); - const lastRan = useRef(Date.now()); - - useEffect(() => { - const handler = setTimeout(() => { - if (Date.now() - lastRan.current >= limit) { - setThrottledValue(value); - lastRan.current = Date.now(); - } - }, limit - (Date.now() - lastRan.current)); - - return () => { - clearTimeout(handler); - }; - }, [value, limit]); - - return throttledValue; -} diff --git a/awx/ui_next/src/components/JobList/useWsJobs.test.jsx b/awx/ui_next/src/components/JobList/useWsJobs.test.jsx new file mode 100644 index 0000000000..1dead6d5da --- /dev/null +++ b/awx/ui_next/src/components/JobList/useWsJobs.test.jsx @@ -0,0 +1,126 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { mount } from 'enzyme'; +import WS from 'jest-websocket-mock'; +import useWsJobs from './useWsJobs'; + +/* + Jest mock timers don’t play well with jest-websocket-mock, + so we'll stub out throttling to resolve immediately +*/ +jest.mock('./useThrottle', () => ({ + __esModule: true, + default: jest.fn(val => val), +})); + +function TestInner() { + return
; +} +function Test({ jobs, fetch }) { + const syncedJobs = useWsJobs(jobs, fetch); + return