Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utility hooks additions #867

Merged
merged 8 commits into from
Feb 10, 2025
Merged

Utility hooks additions #867

merged 8 commits into from
Feb 10, 2025

Conversation

kotAPI
Copy link
Collaborator

@kotAPI kotAPI commented Feb 8, 2025

Adding some useful hooks to the library for using with

Summary by CodeRabbit

  • New Features
    • Introduced a custom hook that conditionally enables layout effects only in browser environments to prevent rendering issues during server-side rendering.
    • Enhanced the TogglePrimitive component with new event handler properties for better integration with external click and key down handlers.
    • Added a color prop to the Table component in the documentation for improved visual presentation.
    • Updated the FullHeightScroll component to allow additional styling through a new className prop.
  • Bug Fixes
    • Improved event handling logic in the TogglePrimitive component to ensure seamless integration with external handlers.
  • Tests
    • Added tests to ensure components mount correctly when using the new hook in server-like conditions.
    • Introduced a test suite for event handler composition, verifying the behavior of combined event handlers in various scenarios.
  • Style
    • Updated styles for table components to enhance visual presentation, including adjustments to colors, padding, and font weights.
    • Modified the rendering structure and styling of the FullPageScroll component for improved layout and appearance.
    • Adjusted styles in the Documentation module to enhance the visual presentation of the DocsTable component.

Copy link
Contributor

coderabbitai bot commented Feb 8, 2025

Walkthrough

The changes introduce a new custom hook, useLayoutEffect, in the core hooks directory. This hook conditionally wraps React's useLayoutEffect by checking for the presence of globalThis.document. If found, it calls the original useLayoutEffect; if not, it returns a no-operation function to ensure compatibility with server-side rendering (SSR). Additionally, tests have been added for both the new hook and the composeEventHandlers function, along with modifications to the TogglePrimitive component to support external event handlers.

Changes

File(s) Change Summary
src/core/hooks/.../useLayoutEffect/index.tsx Added a new custom hook, useLayoutEffect, that conditionally wraps the React useLayoutEffect to safely handle SSR scenarios.
src/core/hooks/.../useLayoutEffect/useLayoutEffect.test.tsx Introduced tests to verify the proper mounting behavior of components using the useLayoutEffect hook, especially in server-side rendering.
src/core/hooks/.../composeEventHandlers/index.tsx Added a new type EventHandler and defined composeEventHandlers to combine event handlers with an option to check for default prevention.
src/core/hooks/.../composeEventHandlers/composeEventHandlers.test.tsx Created a test suite for composeEventHandlers to validate the behavior of event handlers under different scenarios.
src/core/primitives/.../Toggle/index.tsx Modified TogglePrimitive to include new onClick and onKeyDown props, integrating them with internal event handling using composeEventHandlers.
styles/themes/components/.../table.scss Updated styles for various table elements, modifying colors, padding, font weights, and sizes for improved visual presentation.
docs/app/docs/layout.tsx Restructured Layout component to include a new Callout component for additional information, altering the visual structure.
docs/app/testing/full_page_scroll/page.tsx Updated rendering structure and styling of the FullPageScroll component, modifying class names and child elements for better presentation.
docs/components/layout/Documentation/Documentation.js Added a color prop to the Table component in DocsTable for enhanced visual presentation.
docs/components/layout/ScrollContainers/FullHeightScroll.tsx Updated FullHeightScroll component to accept additional styling through a className prop and spread operator.

Sequence Diagram(s)

sequenceDiagram
    participant Component as React Component
    participant Hook as useLayoutEffect Hook
    participant Check as Browser Environment Check

    Component->>Hook: Invoke useLayoutEffect
    Hook->>Check: Check for globalThis.document
    alt Document exists (Browser)
        Check-->>Hook: Document found
        Hook->>Component: Execute React's useLayoutEffect
    else Document not found (SSR)
        Check-->>Hook: No document detected
        Hook->>Component: Return no-operation
    end
Loading

Poem

I'm a rabbit hopping through the code,
A new hook shines on my winding road.
With checks in place and tests so neat,
SSR errors admit defeat.
Carrots and code, we celebrate this feat!
Hop along, for improvements are sweet!

Suggested labels

automerge


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/core/hooks/useLayoutEffect/index.tsx (1)

10-10: Consider adding TypeScript types for better type safety.

While the implementation is correct and follows Radix UI's approach, adding explicit types would improve type safety and documentation.

-const useLayoutEffect = globalThis.document ? ReactUseLayoutEffect : () => {};
+const useLayoutEffect: typeof ReactUseLayoutEffect = 
+  globalThis.document ? ReactUseLayoutEffect : () => {};
src/core/hooks/useLayoutEffect/useLayoutEffect.test.tsx (1)

7-9: Add meaningful effect logic or remove empty comment.

The empty comment "mounts" doesn't provide value. Either add meaningful effect logic for testing or remove the comment.

     useLayoutEffect(() => {
-        // mounts
+        // Effect runs after layout changes
+        // Left empty as we're just testing mounting behavior
     }, []);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ccbeaf and 5bb3def.

📒 Files selected for processing (2)
  • src/core/hooks/useLayoutEffect/index.tsx (1 hunks)
  • src/core/hooks/useLayoutEffect/useLayoutEffect.test.tsx (1 hunks)
🔇 Additional comments (1)
src/core/hooks/useLayoutEffect/index.tsx (1)

3-8: LGTM! Clear and helpful comments.

The comments effectively explain the purpose and behavior of this SSR-compatible implementation.

src/core/hooks/useLayoutEffect/useLayoutEffect.test.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
src/core/primitives/Toggle/index.tsx (1)

34-44: Fix double composition of event handlers.

The handleTogglePressed handler is composed twice:

  1. In its definition with props.onClick
  2. Again in the button's onClick prop

Apply this fix to avoid double composition:

-    const handleTogglePressed = composeEventHandlers(props.onClick, () => {
+    const handleTogglePressed = () => {
         if (disabled) {
             return;
         }
 
         const updatedPressed = !isPressed;
         if (!isControlled) {
             setUncontrolledPressed(updatedPressed);
         }
         onPressedChange(updatedPressed);
-    });
+    };

     return <Primitive.button
         onClick={composeEventHandlers(props.onClick, handleTogglePressed)}
         onKeyDown={composeEventHandlers(props.onKeyDown, handleKeyDown)}

Also applies to: 58-59

🧹 Nitpick comments (4)
src/core/hooks/composeEventHandlers/index.tsx (1)

8-20: Consider a more concise implementation.

The current implementation is correct but could be more concise and avoid the early return.

Consider this alternative implementation:

-    return function handleEvent(event: E) {
-        // If the original event handler is defined, call it
-        if (typeof originalEventHandler === 'function') {
-            originalEventHandler(event);
-        }
-
-        // If the default prevented flag is false or the event is not prevented, call our event handler
-        if (checkForDefaultPrevented === false || !event.defaultPrevented) {
-            return ourEventHandler?.(event);
-        }
-    };
+    return function handleEvent(event: E) {
+        originalEventHandler?.(event);
+        if (checkForDefaultPrevented === false || !event.defaultPrevented) {
+            ourEventHandler?.(event);
+        }
+    };
src/core/hooks/composeEventHandlers/composeEventHandlers.test.tsx (3)

5-28: Improve test component focus and remove console.log statements.

The test component could be more focused and avoid using console.log for assertions.

Consider this alternative implementation:

 const OnlyOriginalHandlerWithPreventDefault = ({
     checkForDefaultPrevented = true
 }: {
     checkForDefaultPrevented?: boolean;
+    onOriginalClick?: () => void;
+    onOurClick?: () => void;
 }) => {
     const originalClickHandler = (event: React.MouseEvent<HTMLButtonElement>) => {
         event.preventDefault();
-        // we prevent default, so we should not see our handler
-        console.log('RETURNING_ORIGINAL_HANDLER');
+        onOriginalClick?.();
     };
     const ourClickHandler = () => {
-        // This won't be triggered because we prevent default in the original handler
-        console.log('RETURNING_OUR_HANDLER');
-
-        console.log('RETURN_OUR_HANDLER_WITH_CHECK_FOR_DEFAULT_PREVENTED');
+        onOurClick?.();
     };

30-39: Simplify test setup by removing console spies.

With the proposed component changes, the test setup can be simplified by removing console spies.

Consider this alternative setup:

 describe('composeEventHandlers', () => {
-    let consoleLogSpy: jest.SpyInstance;
-
-    beforeEach(() => {
-        consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
-    });
-
-    afterEach(() => {
-        consoleLogSpy.mockRestore();
-    });

41-58: Add test coverage for edge cases.

The current tests cover the main functionality but could benefit from additional edge cases.

Consider adding these test cases:

test('should handle undefined handlers gracefully', () => {
    const onOriginalClick = jest.fn();
    render(
        <OnlyOriginalHandlerWithPreventDefault
            onOriginalClick={onOriginalClick}
        />
    );
    const button = screen.getByText('Click Me');
    fireEvent.click(button);
    expect(onOriginalClick).toHaveBeenCalled();
});

test('should handle null handlers gracefully', () => {
    const onOurClick = jest.fn();
    const Component = () => (
        <button
            onClick={composeEventHandlers(
                null as any,
                onOurClick
            )}
        >
            Click Me
        </button>
    );
    render(<Component />);
    const button = screen.getByText('Click Me');
    fireEvent.click(button);
    expect(onOurClick).toHaveBeenCalled();
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bb3def and 3e625db.

📒 Files selected for processing (4)
  • src/core/hooks/composeEventHandlers/composeEventHandlers.test.tsx (1 hunks)
  • src/core/hooks/composeEventHandlers/index.tsx (1 hunks)
  • src/core/hooks/useLayoutEffect/index.tsx (1 hunks)
  • src/core/primitives/Toggle/index.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/hooks/useLayoutEffect/index.tsx
🧰 Additional context used
📓 Learnings (1)
src/core/primitives/Toggle/index.tsx (1)
Learnt from: kotAPI
PR: rad-ui/ui#576
File: src/core/primitives/Toggle/index.tsx:15-22
Timestamp: 2024-11-24T06:43:42.194Z
Learning: In the `TogglePrimitive` component (`src/core/primitives/Toggle/index.tsx`), when the component becomes controlled, it's acceptable to not sync the internal `isPressed` state with the external `pressed` prop.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (3)
src/core/hooks/composeEventHandlers/index.tsx (2)

1-1: LGTM! Well-defined type with proper generic constraint.

The EventHandler type is correctly defined with a generic parameter defaulting to React.SyntheticEvent.


3-7: LGTM! Well-structured function signature with proper typing.

The function signature is well-designed with:

  • Proper generic constraint
  • Optional parameters
  • Type-safe options object with default value
src/core/primitives/Toggle/index.tsx (1)

11-12: LGTM! Well-typed event handler props.

The new event handler props follow React's naming convention and are correctly typed.

src/core/primitives/Toggle/index.tsx Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
docs/components/layout/ScrollContainers/FullHeightScroll.tsx (1)

3-5: Remove empty style object and clean up className template literal.

The empty style object and extra spaces in the className template literal should be cleaned up.

-    return <div className={` ${className}  ${scrollable?' overflow-y-auto overflow-x-hidden':''}`} {...props} style={{
-       
-    }}>
+    return <div className={`${className} ${scrollable ? ' overflow-y-auto overflow-x-hidden' : ''}`} {...props}>
docs/app/docs/layout.tsx (1)

5-7: Add ARIA label to InfoIcon SVG.

Consider adding aria-label to improve accessibility of the InfoIcon SVG.

const InfoIcon = () => {
-    return (<svg width="18" height="18" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.49991 0.876892C3.84222 0.876892 0.877075 3.84204 0.877075 7.49972C0.877075 11.1574 3.84222 14.1226 7.49991 14.1226C11.1576 14.1226 14.1227 11.1574 14.1227 7.49972C14.1227 3.84204 11.1576 0.876892 7.49991 0.876892ZM1.82707 7.49972C1.82707 4.36671 4.36689 1.82689 7.49991 1.82689C10.6329 1.82689 13.1727 4.36671 13.1727 7.49972C13.1727 10.6327 10.6329 13.1726 7.49991 13.1726C4.36689 13.1726 1.82707 10.6327 1.82707 7.49972ZM8.24992 4.49999C8.24992 4.9142 7.91413 5.24999 7.49992 5.24999C7.08571 5.24999 6.74992 4.9142 6.74992 4.49999C6.74992 4.08577 7.08571 3.74999 7.49992 3.74999C7.91413 3.74999 8.24992 4.08577 8.24992 4.49999ZM6.00003 5.99999H6.50003H7.50003C7.77618 5.99999 8.00003 6.22384 8.00003 6.49999V9.99999H8.50003H9.00003V11H8.50003H7.50003H6.50003H6.00003V9.99999H6.50003H7.00003V6.99999H6.50003H6.00003V5.99999Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path></svg>);
+    return (<svg aria-label="Information" role="img" width="18" height="18" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.49991 0.876892C3.84222 0.876892 0.877075 3.84204 0.877075 7.49972C0.877075 11.1574 3.84222 14.1226 7.49991 14.1226C11.1576 14.1226 14.1227 11.1574 14.1227 7.49972C14.1227 3.84204 11.1576 0.876892 7.49991 0.876892ZM1.82707 7.49972C1.82707 4.36671 4.36689 1.82689 7.49991 1.82689C10.6329 1.82689 13.1727 4.36671 13.1727 7.49972C13.1727 10.6327 10.6329 13.1726 7.49991 13.1726C4.36689 13.1726 1.82707 10.6327 1.82707 7.49972ZM8.24992 4.49999C8.24992 4.9142 7.91413 5.24999 7.49992 5.24999C7.08571 5.24999 6.74992 4.9142 6.74992 4.49999C6.74992 4.08577 7.08571 3.74999 7.49992 3.74999C7.91413 3.74999 8.24992 4.08577 8.24992 4.49999ZM6.00003 5.99999H6.50003H7.50003C7.77618 5.99999 8.00003 6.22384 8.00003 6.49999V9.99999H8.50003H9.00003V11H8.50003H7.50003H6.50003H6.00003V9.99999H6.50003H7.00003V6.99999H6.50003H6.00003V5.99999Z" fill="currentColor" fillRule="evenodd" clipRule="evenodd"></path></svg>);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4f08d and e69bd7e.

📒 Files selected for processing (5)
  • docs/app/docs/layout.tsx (1 hunks)
  • docs/app/testing/full_page_scroll/page.tsx (1 hunks)
  • docs/components/layout/Documentation/Documentation.js (1 hunks)
  • docs/components/layout/ScrollContainers/FullHeightScroll.tsx (1 hunks)
  • src/core/hooks/composeEventHandlers/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/hooks/composeEventHandlers/index.tsx
🔇 Additional comments (5)
docs/components/layout/Documentation/Documentation.js (2)

49-49: Document the color prop and ensure consistent Table usage.

The Table component is used with different props across the file. Consider:

  1. Adding documentation for the new color prop and its possible values
  2. Applying consistent styling by adding the color prop to the Table in KeyboardShortcuts component (line 89)
// In KeyboardShortcuts component
-        <Table columns={keyboardShortcuts.columns} data={keyboardShortcuts.data} >
+        <Table columns={keyboardShortcuts.columns} data={keyboardShortcuts.data} color="gray" >

49-49: Verify type definitions for the Table component.

Let's ensure the color prop is properly typed in the Table component.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Search for Table component type definitions and documentation
echo "Searching for Table component type definitions..."
fd -e ts -e tsx -e d.ts Table

echo "Searching for Table component documentation..."
fd -e md Table

Length of output: 688


Verified: Table component's type definitions include the "color" prop.

We confirmed that the Table component is defined in "src/components/ui/Table/Table.tsx" with explicit type definitions that include the "color" prop. No further documentation issues were found.

docs/components/layout/ScrollContainers/FullHeightScroll.tsx (1)

1-1: LGTM! Props signature update looks good.

The addition of className prop with a default value and props spreading follows React best practices.

docs/app/testing/full_page_scroll/page.tsx (1)

4-14: LGTM! Component changes look good.

The implementation properly demonstrates the usage of the new className prop and maintains good practices with key usage in the map function.

docs/app/docs/layout.tsx (1)

17-17: LGTM! Layout improvements look good.

The max-width constraint and auto margins improve content layout consistency.

@kotAPI kotAPI merged commit ee73049 into main Feb 10, 2025
6 checks passed
@kotAPI kotAPI deleted the kotapi/feb-2nd-week-improvements branch February 10, 2025 09:26
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/core/hooks/useLayoutEffect/useLayoutEffect.test.tsx (2)

5-11: Improve test component documentation and clarity.

The test component could be more explicit about what it's testing:

  1. Remove redundant comments
  2. Add meaningful documentation or make the test intention clear through code
 const TestComponent = () => {
-    // invoke useLayoutEffect and check if the component still mounts as expected
     useLayoutEffect(() => {
-        // mounts
+        // Intentionally empty for SSR compatibility test
     }, []);
     return <div>Hello</div>;
 };

14-16: Add assertions to verify component rendering.

While the test verifies that the component mounts without errors, it would be more robust to assert that the component actually rendered its content.

     it('should mount without errors in SSR environment', () => {
-        render(<TestComponent />);
+        const { getByText } = render(<TestComponent />);
+        expect(getByText('Hello')).toBeInTheDocument();
     });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e277226 and c9e9b57.

📒 Files selected for processing (1)
  • src/core/hooks/useLayoutEffect/useLayoutEffect.test.tsx (1 hunks)

Comment on lines +18 to +36
it('should execute effect in browser environment', () => {
const mockFn = jest.fn();
const TestComponent = () => {
useLayoutEffect(() => {
mockFn();
}, []);
return <div>Hello</div>;
};

// Mock document existence
const originalDocument = global.document;
global.document = {} as typeof document;

render(<TestComponent />);
expect(mockFn).toHaveBeenCalledTimes(1);

// Cleanup
global.document = originalDocument;
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve browser environment test robustness.

The browser environment test could be more robust with these improvements:

  1. Use proper test lifecycle hooks for setup/cleanup
  2. Use a more realistic document mock
  3. Add error handling for cleanup
+    let originalDocument: typeof document;
+
+    beforeEach(() => {
+        originalDocument = global.document;
+        // Mock a more realistic document object
+        global.document = {
+            createElement: jest.fn(),
+            body: {},
+        } as unknown as typeof document;
+    });
+
+    afterEach(() => {
+        try {
+            global.document = originalDocument;
+        } catch (error) {
+            console.error('Failed to restore document:', error);
+            throw error;
+        }
+    });
+
     it('should execute effect in browser environment', () => {
         const mockFn = jest.fn();
         const TestComponent = () => {
             useLayoutEffect(() => {
                 mockFn();
             }, []);
             return <div>Hello</div>;
         };
 
-        // Mock document existence
-        const originalDocument = global.document;
-        global.document = {} as typeof document;
-
         render(<TestComponent />);
         expect(mockFn).toHaveBeenCalledTimes(1);
-
-        // Cleanup
-        global.document = originalDocument;
     });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should execute effect in browser environment', () => {
const mockFn = jest.fn();
const TestComponent = () => {
useLayoutEffect(() => {
mockFn();
}, []);
return <div>Hello</div>;
};
// Mock document existence
const originalDocument = global.document;
global.document = {} as typeof document;
render(<TestComponent />);
expect(mockFn).toHaveBeenCalledTimes(1);
// Cleanup
global.document = originalDocument;
});
let originalDocument: typeof document;
beforeEach(() => {
originalDocument = global.document;
// Mock a more realistic document object
global.document = {
createElement: jest.fn(),
body: {},
} as unknown as typeof document;
});
afterEach(() => {
try {
global.document = originalDocument;
} catch (error) {
console.error('Failed to restore document:', error);
throw error;
}
});
it('should execute effect in browser environment', () => {
const mockFn = jest.fn();
const TestComponent = () => {
useLayoutEffect(() => {
mockFn();
}, []);
return <div>Hello</div>;
};
render(<TestComponent />);
expect(mockFn).toHaveBeenCalledTimes(1);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant