Skip to content

Commit

Permalink
Temporarily copy render utility to repo to experiment with it.
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniGuardiola committed Jul 25, 2024
1 parent 3be0bc2 commit 68afa3c
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/components/src/tabs/test/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/
import { screen, waitFor } from '@testing-library/react';
import { press, click, sleep } from '@ariakit/test';
import { render } from '@ariakit/test/react';

/**
* WordPress dependencies
Expand All @@ -15,6 +14,7 @@ import { useEffect, useState } from '@wordpress/element';
*/
import Tabs from '..';
import type { TabsProps } from '../types';
import { render } from '../../utils/tmp-ariakit-test-render-replacement';

type Tab = {
tabId: string;
Expand Down
158 changes: 158 additions & 0 deletions packages/components/src/utils/tmp-ariakit-test-render-replacement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/**
* External dependencies
*/
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { createElement, StrictMode, type ReactNode } from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import * as ReactTestingLibrary from '@testing-library/react';

// eslint-disable-next-line import/no-extraneous-dependencies
import { isFocusable } from '@ariakit/core/utils/focus';
// eslint-disable-next-line import/no-extraneous-dependencies
import { noop } from '@ariakit/core/utils/misc';

export type DirtiableElement = Element & { dirty?: boolean };

export type TextField = HTMLInputElement | HTMLTextAreaElement;

export const isBrowser =
typeof navigator !== 'undefined' &&
// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
! navigator.userAgent.includes( 'jsdom' ) &&
typeof window !== 'undefined' &&
// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
! ( 'happyDOM' in window );

export async function flushMicrotasks() {
await Promise.resolve();
await Promise.resolve();
await Promise.resolve();
}

export function nextFrame() {
return new Promise( requestAnimationFrame );
}

export function setActEnvironment( value: boolean ) {
const scope = globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean };
const previousValue = scope.IS_REACT_ACT_ENVIRONMENT;
scope.IS_REACT_ACT_ENVIRONMENT = value;
const restoreActEnvironment = () => {
scope.IS_REACT_ACT_ENVIRONMENT = previousValue;
};
return restoreActEnvironment;
}

export function applyBrowserPolyfills() {
if ( isBrowser ) {
return noop;
}

const originalFocus = HTMLElement.prototype.focus;

HTMLElement.prototype.focus = function focus( options ) {
if ( ! isFocusable( this ) ) {
return;
}
return originalFocus.call( this, options );
};

const originalGetClientRects = Element.prototype.getClientRects;

// @ts-expect-error
Element.prototype.getClientRects = function getClientRects() {
const isHidden = ( element: Element ) => {
if ( ! element.isConnected ) {
return true;
}
if ( element.parentElement && isHidden( element.parentElement ) ) {
return true;
}
if ( ! ( element instanceof HTMLElement ) ) {
return false;
}
if ( element.hidden ) {
return true;
}
const style = getComputedStyle( element );
return style.display === 'none' || style.visibility === 'hidden';
};
if ( isHidden( this ) ) {
return [];
}
return [ { width: 1, height: 1 } ];
};

if ( ! Element.prototype.scrollIntoView ) {
Element.prototype.scrollIntoView = noop;
}

if ( ! Element.prototype.hasPointerCapture ) {
Element.prototype.hasPointerCapture = noop;
}

if ( ! Element.prototype.setPointerCapture ) {
Element.prototype.setPointerCapture = noop;
}

if ( ! Element.prototype.releasePointerCapture ) {
Element.prototype.releasePointerCapture = noop;
}

if ( typeof window.ClipboardEvent === 'undefined' ) {
// @ts-expect-error
window.ClipboardEvent = class ClipboardEvent extends Event {};
}

if ( typeof window.PointerEvent === 'undefined' ) {
// @ts-expect-error
window.PointerEvent = class PointerEvent extends MouseEvent {};
}

return () => {
HTMLElement.prototype.focus = originalFocus;
Element.prototype.getClientRects = originalGetClientRects;
};
}

export async function wrapAsync< T >( fn: () => Promise< T > ) {
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
const restoreActEnvironment = setActEnvironment( false );
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
const removeBrowserPolyfills = applyBrowserPolyfills();
try {
return await fn();
} finally {
restoreActEnvironment();
removeBrowserPolyfills();
}
}

export interface RenderOptions
extends Omit< ReactTestingLibrary.RenderOptions, 'queries' > {
strictMode?: boolean;
}

export async function render( ui: ReactNode, options?: RenderOptions ) {
const wrapper = ( props: { children: ReactNode } ) => {
const Wrapper = options?.wrapper;
const element = Wrapper
? createElement( Wrapper, props )
: props.children;
if ( ! options?.strictMode ) {
return element;
}
return createElement( StrictMode, undefined, element );
};

return wrapAsync( async () => {
const { unmount } = ReactTestingLibrary.render( ui, {
...options,
wrapper,
} );
await flushMicrotasks();
await nextFrame();
await flushMicrotasks();
return unmount;
} );
}

0 comments on commit 68afa3c

Please sign in to comment.