From 6d52eecf19c93a462ac2f13077b5b3bd5e7ac29b Mon Sep 17 00:00:00 2001 From: James Smith Date: Thu, 17 Jun 2021 11:53:29 -0400 Subject: [PATCH] Begin testing warnings --- jest-setup.js | 21 +++++++ src/focus-context.tsx | 2 +- src/focus-node.tsx | 2 +- src/focus-store.ts | 2 +- src/hooks/internal/use-on-change.ts | 2 +- src/hooks/use-active-node.ts | 2 +- src/hooks/use-focus-events.ts | 2 +- src/hooks/use-focus-hierarchy.ts | 2 +- src/hooks/use-focus-node.ts | 2 +- src/hooks/use-focus-store-dangerously.ts | 2 +- src/hooks/use-set-focus.test.js | 61 ++++++++++++++++++++- src/hooks/use-set-focus.ts | 2 +- src/update-focus/compute-focus-hierarchy.ts | 4 +- src/utils/create-node.ts | 6 +- src/utils/delete-node.ts | 2 +- src/utils/warning.ts | 2 +- 16 files changed, 98 insertions(+), 18 deletions(-) diff --git a/jest-setup.js b/jest-setup.js index 7b0828b..8186f7e 100644 --- a/jest-setup.js +++ b/jest-setup.js @@ -1 +1,22 @@ import '@testing-library/jest-dom'; +import * as warning from './src/utils/warning'; + +beforeEach(() => { + if (console.error.mockRestore) { + console.error.mockRestore(); + } + + if (console.warn.mockRestore) { + console.warn.mockRestore(); + } + + if (warning.warning.mockRestore) { + warning.warning.mockRestore(); + } + + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(warning, 'warning').mockImplementation(() => {}); + + warning.resetCodeCache(); +}); diff --git a/src/focus-context.tsx b/src/focus-context.tsx index 22abd26..068747c 100644 --- a/src/focus-context.tsx +++ b/src/focus-context.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react'; import createFocusStore from './focus-store'; import lrudInput from './lrud-input/focus-lrud'; import { ProviderValue, RootFocusNode, Orientation } from './types'; -import warning from './utils/warning'; +import { warning } from './utils/warning'; const FocusContext = React.createContext(null); diff --git a/src/focus-node.tsx b/src/focus-node.tsx index a36be41..2acd3a5 100644 --- a/src/focus-node.tsx +++ b/src/focus-node.tsx @@ -10,7 +10,7 @@ import React, { } from 'react'; import FocusContext from './focus-context'; import nodeFromDefinition from './utils/node-from-definition'; -import warning from './utils/warning'; +import { warning } from './utils/warning'; import { FocusStore, Id, diff --git a/src/focus-store.ts b/src/focus-store.ts index a3235c1..589a821 100644 --- a/src/focus-store.ts +++ b/src/focus-store.ts @@ -4,7 +4,7 @@ import updateFocus from './update-focus/update-focus'; import handleArrowUtil from './handle-arrow/handle-arrow'; import enforceStateStructure from './utils/enforce-state-structure'; import recursivelyUpdateChildren from './utils/recursively-update-node'; -import warning from './utils/warning'; +import { warning } from './utils/warning'; import { FocusState, Orientation, diff --git a/src/hooks/internal/use-on-change.ts b/src/hooks/internal/use-on-change.ts index 3c6b080..199961f 100644 --- a/src/hooks/internal/use-on-change.ts +++ b/src/hooks/internal/use-on-change.ts @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import usePrevious from './use-previous'; -import warning from '../../utils/warning'; +import { warning } from '../../utils/warning'; type ComparatorFn = (a: Value, b: Value | undefined) => boolean; diff --git a/src/hooks/use-active-node.ts b/src/hooks/use-active-node.ts index 99f5613..7218634 100644 --- a/src/hooks/use-active-node.ts +++ b/src/hooks/use-active-node.ts @@ -1,6 +1,6 @@ import { useContext, useState, useEffect, useRef } from 'react'; import FocusContext from '../focus-context'; -import warning from '../utils/warning'; +import { warning } from '../utils/warning'; import { Node } from '../types'; export default function useActiveNode(): Node | null { diff --git a/src/hooks/use-focus-events.ts b/src/hooks/use-focus-events.ts index 52cb2ce..bd4651e 100644 --- a/src/hooks/use-focus-events.ts +++ b/src/hooks/use-focus-events.ts @@ -1,7 +1,7 @@ import { useRef, useState } from 'react'; import useOnChange from './internal/use-on-change'; import useFocusNode from './use-focus-node'; -import warning from '../utils/warning'; +import { warning } from '../utils/warning'; import { Id, Node } from '../types'; type EventCallback = (node: Node) => void; diff --git a/src/hooks/use-focus-hierarchy.ts b/src/hooks/use-focus-hierarchy.ts index 7d683dd..b67d2b1 100644 --- a/src/hooks/use-focus-hierarchy.ts +++ b/src/hooks/use-focus-hierarchy.ts @@ -1,6 +1,6 @@ import { useContext, useEffect, useState, useRef } from 'react'; import FocusContext from '../focus-context'; -import warning from '../utils/warning'; +import { warning } from '../utils/warning'; import { Node, NodeHierarchy } from '../types'; function hierarchiesAreEqual( diff --git a/src/hooks/use-focus-node.ts b/src/hooks/use-focus-node.ts index ff6b3a9..38a0320 100644 --- a/src/hooks/use-focus-node.ts +++ b/src/hooks/use-focus-node.ts @@ -1,6 +1,6 @@ import { useContext, useState, useEffect, useRef } from 'react'; import FocusContext from '../focus-context'; -import warning from '../utils/warning'; +import { warning } from '../utils/warning'; import { Id, Node } from '../types'; export default function useFocusNode(focusId: Id): Node | null { diff --git a/src/hooks/use-focus-store-dangerously.ts b/src/hooks/use-focus-store-dangerously.ts index 766280d..27818c2 100644 --- a/src/hooks/use-focus-store-dangerously.ts +++ b/src/hooks/use-focus-store-dangerously.ts @@ -1,6 +1,6 @@ import { useContext } from 'react'; import FocusContext from '../focus-context'; -import warning from '../utils/warning'; +import { warning } from '../utils/warning'; import { FocusStore } from '../types'; export default function useFocusStoreDangerously(): FocusStore { diff --git a/src/hooks/use-set-focus.test.js b/src/hooks/use-set-focus.test.js index 2209c12..8816113 100644 --- a/src/hooks/use-set-focus.test.js +++ b/src/hooks/use-set-focus.test.js @@ -7,6 +7,7 @@ import { useSetFocus, useFocusStoreDangerously, } from '../index'; +import { warning } from '../utils/warning'; describe('useSetFocus', () => { it('is a noop when the node is already focused', () => { @@ -228,7 +229,6 @@ describe('useSetFocus', () => { expect(Object.values(focusState.nodes)).toHaveLength(3); }); - // TODO: add check for warning it('it is a noop if the node does not exist', () => { let focusStore; let setFocus; @@ -280,5 +280,64 @@ describe('useSetFocus', () => { expect(focusState.focusHierarchy).toEqual(['root', 'nodeA']); expect(focusState.activeNodeId).toEqual(null); expect(Object.values(focusState.nodes)).toHaveLength(3); + + expect(warning).toHaveBeenCalledTimes(1); + expect(warning.mock.calls[0][1]).toEqual('NODE_DOES_NOT_EXIST'); + }); + + it('it is a noop with a nonsense argument', () => { + let focusStore; + let setFocus; + + function TestComponent() { + focusStore = useFocusStoreDangerously(); + setFocus = useSetFocus(); + + return ( + <> + + + + ); + } + + render( + + + + ); + + let nodeA = screen.getByTestId('nodeA'); + expect(nodeA).toHaveClass('isFocused'); + expect(nodeA).toHaveClass('isFocusedLeaf'); + + let nodeB = screen.getByTestId('nodeB'); + expect(nodeB).not.toHaveClass('isFocused'); + expect(nodeB).not.toHaveClass('isFocusedLeaf'); + + let focusState = focusStore.getState(); + expect(focusState.focusedNodeId).toEqual('nodeA'); + expect(focusState.focusHierarchy).toEqual(['root', 'nodeA']); + expect(focusState.activeNodeId).toEqual(null); + expect(Object.values(focusState.nodes)).toHaveLength(3); + + act(() => setFocus({})); + + nodeA = screen.getByTestId('nodeA'); + expect(nodeA).toHaveClass('isFocused'); + expect(nodeA).toHaveClass('isFocusedLeaf'); + + nodeB = screen.getByTestId('nodeB'); + expect(nodeB).not.toHaveClass('isFocused'); + expect(nodeB).not.toHaveClass('isFocusedLeaf'); + + focusState = focusStore.getState(); + expect(focusState.focusedNodeId).toEqual('nodeA'); + expect(focusState.focusHierarchy).toEqual(['root', 'nodeA']); + expect(focusState.activeNodeId).toEqual(null); + expect(Object.values(focusState.nodes)).toHaveLength(3); + + expect(warning).toHaveBeenCalledTimes(1); + expect(warning.mock.calls[0][1]).toEqual('NODE_ID_NOT_STRING_TO_SET_FOCUS'); }); }); diff --git a/src/hooks/use-set-focus.ts b/src/hooks/use-set-focus.ts index 36b3129..8eee6bc 100644 --- a/src/hooks/use-set-focus.ts +++ b/src/hooks/use-set-focus.ts @@ -1,6 +1,6 @@ import { useContext } from 'react'; import FocusContext from '../focus-context'; -import warning from '../utils/warning'; +import { warning } from '../utils/warning'; import { Id } from '../types'; export default function useSetFocus(): (focusId: Id) => void { diff --git a/src/update-focus/compute-focus-hierarchy.ts b/src/update-focus/compute-focus-hierarchy.ts index 1161bb9..0507822 100644 --- a/src/update-focus/compute-focus-hierarchy.ts +++ b/src/update-focus/compute-focus-hierarchy.ts @@ -1,5 +1,5 @@ import { getParents, getChildren } from '../utils/tree-navigation'; -import warning from '../utils/warning'; +import { warning } from '../utils/warning'; import { FocusState, Id, Orientation, NodeHierarchy, Node } from '../types'; interface ComputeFocusHierarchyOptions { @@ -22,7 +22,7 @@ function generateFocusHierarchyFromId({ orientation, preferEnd, }: GenerateFocusHierarchyFromIdOptions): Id[] { - const node = (focusState.nodes[propagateFromId] as unknown) as Node; + const node = focusState.nodes[propagateFromId] as unknown as Node; let preferredChildren: NodeHierarchy = []; if (node.trap) { preferredChildren = node._focusTrapPreviousHierarchy; diff --git a/src/utils/create-node.ts b/src/utils/create-node.ts index 3a2175e..1aec7cb 100644 --- a/src/utils/create-node.ts +++ b/src/utils/create-node.ts @@ -1,4 +1,4 @@ -import warning from '../utils/warning'; +import { warning } from '../utils/warning'; import { NodeDefinition, FocusState, NodeMap, Id, Node } from '../types'; import getIndex from './get-index'; @@ -120,8 +120,8 @@ export default function createNodeDefinitionHierarchy({ const parentDefinition = nodeDefinitionHierarchy[parentLoopIndex]; const parentId = parentDefinition.focusId; - const parentNode = ((focusState.nodes[parentId] || - nodeUpdates[parentId]) as unknown) as Node; + const parentNode = (focusState.nodes[parentId] || + nodeUpdates[parentId]) as unknown as Node; const parentChildren = parentNode.children; diff --git a/src/utils/delete-node.ts b/src/utils/delete-node.ts index e65a0d9..aaa461c 100644 --- a/src/utils/delete-node.ts +++ b/src/utils/delete-node.ts @@ -1,5 +1,5 @@ import nodeIdIsFocused from './node-id-is-focused'; -import warning from './warning'; +import { warning } from './warning'; import updateFocus from '../update-focus/update-focus'; import { FocusState, Id, NodeMap, Node } from '../types'; diff --git a/src/utils/warning.ts b/src/utils/warning.ts index 0a8626b..4f54199 100644 --- a/src/utils/warning.ts +++ b/src/utils/warning.ts @@ -4,7 +4,7 @@ interface CodeCache { let codeCache: CodeCache = {}; -export default function warning(message: string, code: string) { +export function warning(message: string, code: string) { // This ensures that each warning type is only logged out one time if (code) { if (codeCache[code]) {