diff --git a/hyperglass/ui/context/HyperglassProvider.tsx b/hyperglass/ui/context/HyperglassProvider.tsx index 239e4de..e51aa52 100644 --- a/hyperglass/ui/context/HyperglassProvider.tsx +++ b/hyperglass/ui/context/HyperglassProvider.tsx @@ -12,7 +12,7 @@ import { makeTheme, defaultTheme } from '~/util'; import type { Config, Theme } from '~/types'; import type { THyperglassProvider } from './types'; -const HyperglassContext = createContext(Object()); +export const HyperglassContext = createContext({} as Config); const queryClient = new QueryClient(); diff --git a/hyperglass/ui/hooks/useBooleanValue.test.tsx b/hyperglass/ui/hooks/useBooleanValue.test.tsx new file mode 100644 index 0000000..5bb3f13 --- /dev/null +++ b/hyperglass/ui/hooks/useBooleanValue.test.tsx @@ -0,0 +1,35 @@ +import { useState } from 'react'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import userEvent from '@testing-library/user-event'; +import { useBooleanValue } from './useBooleanValue'; + +const VALUE_IF_TRUE = 'Is True'; +const VALUE_IF_FALSE = 'Is False'; + +const TestComponent = (): JSX.Element => { + const [state, setState] = useState(false); + const value = useBooleanValue(state, VALUE_IF_TRUE, VALUE_IF_FALSE); + return ( +
+ {value} + +
+ ); +}; + +describe('useBooleanValue Hook', () => { + it('text should reflect boolean state', () => { + const { queryByText, getByRole } = render(); + + expect(queryByText(VALUE_IF_FALSE)).toBeInTheDocument(); + + userEvent.click(getByRole('button')); + + expect(queryByText(VALUE_IF_FALSE)).not.toBeInTheDocument(); + + expect(queryByText(VALUE_IF_TRUE)).toBeInTheDocument(); + }); +}); diff --git a/hyperglass/ui/hooks/useDevice.test.tsx b/hyperglass/ui/hooks/useDevice.test.tsx new file mode 100644 index 0000000..a2e2bf6 --- /dev/null +++ b/hyperglass/ui/hooks/useDevice.test.tsx @@ -0,0 +1,37 @@ +import {} from 'react'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { useDevice } from './useDevice'; +import { HyperglassContext } from '~/context'; + +import type { DeviceGroup, Config } from '~/types'; + +interface TestComponentProps { + deviceId: string; +} + +const DEVICES = [ + { + group: 'Test Group', + locations: [{ id: 'test1', name: 'Test 1' }], + }, +] as DeviceGroup[]; + +const TestComponent = (props: TestComponentProps): JSX.Element => { + const { deviceId } = props; + const getDevice = useDevice(); + const device = getDevice(deviceId); + + return
{device?.name}
; +}; + +describe('useDevice Hook', () => { + it('should get the device by ID', () => { + const { queryByText } = render( + + + , + ); + expect(queryByText('Test 1')).toBeInTheDocument(); + }); +}); diff --git a/hyperglass/ui/hooks/useGreeting.test.tsx b/hyperglass/ui/hooks/useGreeting.test.tsx new file mode 100644 index 0000000..4c0c43b --- /dev/null +++ b/hyperglass/ui/hooks/useGreeting.test.tsx @@ -0,0 +1,117 @@ +import '@testing-library/jest-dom'; +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { useGreeting } from './useGreeting'; + +const TRUE = JSON.stringify(true); +const FALSE = JSON.stringify(false); + +const TestComponent = (): JSX.Element => { + const { ack, open, close, isAck, isOpen, greetingReady } = useGreeting(); + return ( +
+ + + + + + + + +
{JSON.stringify(isAck)}{JSON.stringify(isOpen)}{JSON.stringify(greetingReady)}
+ + + + + + +
+ ); +}; + +describe('useGreeting Hook', () => { + it('should open and close when toggled', () => { + const { container } = render(); + const open = container.querySelector('#open'); + const close = container.querySelector('#close'); + const isOpen = container.querySelector('#isOpen'); + + if (open !== null && close !== null && isOpen !== null) { + expect(isOpen).toHaveTextContent(FALSE); + userEvent.click(open); + expect(isOpen).toHaveTextContent(TRUE); + userEvent.click(close); + expect(isOpen).toHaveTextContent(FALSE); + } else { + throw new Error('Test render error'); + } + }); + + it('should properly update acknowledgement state', () => { + const { container } = render(); + const open = container.querySelector('#open'); + const close = container.querySelector('#close'); + const isOpen = container.querySelector('#isOpen'); + const isAck = container.querySelector('#isAck'); + const greetingReady = container.querySelector('#greetingReady'); + const ackFalseRequired = container.querySelector('#ack-false-required'); + const ackTrueRequired = container.querySelector('#ack-true-required'); + const ackFalseNotRequired = container.querySelector('#ack-false-not-required'); + const ackTrueNotRequired = container.querySelector('#ack-true-not-required'); + + if ( + open !== null && + close !== null && + isOpen !== null && + isAck !== null && + greetingReady !== null && + ackFalseRequired !== null && + ackTrueRequired !== null && + ackFalseNotRequired !== null && + ackTrueNotRequired !== null + ) { + userEvent.click(open); + expect(isOpen).toHaveTextContent(TRUE); + expect(isAck).toHaveTextContent(FALSE); + expect(greetingReady).toHaveTextContent(FALSE); + + userEvent.click(open); + userEvent.click(ackFalseRequired); + expect(isOpen).toHaveTextContent(FALSE); + expect(isAck).toHaveTextContent(FALSE); + expect(greetingReady).toHaveTextContent(FALSE); + + userEvent.click(open); + userEvent.click(ackTrueRequired); + expect(isOpen).toHaveTextContent(FALSE); + expect(isAck).toHaveTextContent(TRUE); + expect(greetingReady).toHaveTextContent(TRUE); + + userEvent.click(open); + userEvent.click(ackFalseNotRequired); + expect(isOpen).toHaveTextContent(FALSE); + expect(isAck).toHaveTextContent(FALSE); + expect(greetingReady).toHaveTextContent(TRUE); + + userEvent.click(open); + userEvent.click(ackTrueNotRequired); + expect(isOpen).toHaveTextContent(FALSE); + expect(isAck).toHaveTextContent(TRUE); + expect(greetingReady).toHaveTextContent(TRUE); + } else { + throw new Error('Test render error'); + } + }); +}); diff --git a/hyperglass/ui/hooks/useOpposingColor.test.tsx b/hyperglass/ui/hooks/useOpposingColor.test.tsx new file mode 100644 index 0000000..0c5b36e --- /dev/null +++ b/hyperglass/ui/hooks/useOpposingColor.test.tsx @@ -0,0 +1,48 @@ +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import userEvent from '@testing-library/user-event'; +import { ChakraProvider, useColorMode, useColorModeValue, extendTheme } from '@chakra-ui/react'; +import { useOpposingColor } from './useOpposingColor'; + +const TestComponent = (): JSX.Element => { + const { toggleColorMode } = useColorMode(); + const bg1 = useColorModeValue('#ffffff', '#000000'); + const bg2 = useColorModeValue('blue.50', 'blue.900'); + const fg1 = useOpposingColor(bg1); + const fg2 = useOpposingColor(bg2); + + return ( +
+ + + +
+ ); +}; + +describe('useOpposingColor Hook', () => { + it('should change foreground color', () => { + const { getByRole, container } = render( + + + , + ); + const test1 = container.querySelector('#test1'); + const test2 = container.querySelector('#test2'); + + expect(test1).toHaveStyle('color: black;'); + expect(test2).toHaveStyle('color: black;'); + + userEvent.click(getByRole('button')); + + expect(test1).toHaveStyle('color: white;'); + expect(test2).toHaveStyle('color: white;'); + + userEvent.click(getByRole('button')); + + expect(test1).toHaveStyle('color: black;'); + expect(test2).toHaveStyle('color: black;'); + }); +}); diff --git a/hyperglass/ui/hooks/useStrf.test.tsx b/hyperglass/ui/hooks/useStrf.test.tsx new file mode 100644 index 0000000..95a3592 --- /dev/null +++ b/hyperglass/ui/hooks/useStrf.test.tsx @@ -0,0 +1,20 @@ +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { useStrf } from './useStrf'; + +const TEMPLATE = 'Testing {name} hook'; +const OBJECT = { name: 'useStrf' }; +const FINAL_VALUE = 'Testing useStrf hook'; + +const TestComponent = (): JSX.Element => { + const strf = useStrf(); + const value = strf(TEMPLATE, OBJECT); + return
{value}
; +}; + +describe('useStrf Hook', () => { + it('text be formatted', () => { + const { queryByText } = render(); + expect(queryByText(FINAL_VALUE)).toBeInTheDocument(); + }); +}); diff --git a/hyperglass/ui/package.json b/hyperglass/ui/package.json index 0dd075a..b9f84c9 100644 --- a/hyperglass/ui/package.json +++ b/hyperglass/ui/package.json @@ -50,6 +50,7 @@ "devDependencies": { "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^12.1.0", + "@testing-library/user-event": "^13.5.0", "@types/dagre": "^0.7.44", "@types/express": "^4.17.13", "@types/lodash": "^4.14.177", diff --git a/hyperglass/ui/yarn.lock b/hyperglass/ui/yarn.lock index e7a284b..98657ac 100644 --- a/hyperglass/ui/yarn.lock +++ b/hyperglass/ui/yarn.lock @@ -1710,6 +1710,13 @@ "@babel/runtime" "^7.12.5" "@testing-library/dom" "^8.0.0" +"@testing-library/user-event@^13.5.0": + version "13.5.0" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-13.5.0.tgz#69d77007f1e124d55314a2b73fd204b333b13295" + integrity sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg== + dependencies: + "@babel/runtime" "^7.12.5" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"