UNPKG

shallowly

Version:

Shallowly: Modern shallow renderer for React 18+. Enzyme-compatible API, 2x faster, with TypeScript support.

263 lines (189 loc) 8.45 kB
# Shallowly 🏝️ - The Modern Unit Testing Tool for React --- [![npm version](https://img.shields.io/npm/v/shallowly?style=flat-square)](https://www.npmjs.com/package/shallowly) [![minzipped size](https://img.shields.io/bundlephobia/minzip/shallowly?style=flat-square)](https://bundlephobia.com/package/shallowly) [![build status](https://img.shields.io/github/actions/workflow/status/bad4iz/shallowly/tests.yml?style=flat-square)](https://github.com/bad4iz/shallowly/actions) <!-- Option 4: Detailed metrics --> [![coverage](https://img.shields.io/badge/coverage-85%25-brightgreen?style=flat-square)](https://codecov.io/gh/bad4iz/shallowly) [![branches](https://img.shields.io/badge/branches-78%25-yellow?style=flat-square)](https://codecov.io/gh/bad4iz/shallowly) [![functions](https://img.shields.io/badge/functions-92%25-brightgreen?style=flat-square)](https://codecov.io/gh/bad4iz/shallowly) <!-- Code Coverage Badges --> [![codecov](https://codecov.io/gh/bad4iz/shallowly/graph/badge.svg?token=0JF4RTDDIC)](https://codecov.io/gh/bad4iz/shallowly) <!-- Для ветки master с токеном --> [![codecov](https://codecov.io/gh/bad4iz/shallowly/graphs/icicle.svg?token=0JF4RTDDIC)](https://codecov.io/gh/bad4iz/shallowly) --- ## 📚 Documentation - [English Documentation](/docs/index.md) - [Документация на русском](/docs/index.ru.md) - [React Architecture Guide](/docs/react-architecture.md) - [Руководство по архитектуре React](/docs/react-architecture-ru.md) - [Development Guide](/docs/dev.md) - [Руководство разработки на русском](/docs/dev.ru.md) ## 🎯 Key Purpose: Laser-Focused Unit Testing **"Shallowly exists for one purpose: fast, isolated unit tests of YOUR React components."** ### Why Unit Testing Matters: - 🔍 **Isolated verification** - Test components in complete isolation -**Instant feedback** - Get results in milliseconds, not seconds - 🧩 **Precise targeting** - Verify one component at a time - 🛡️ **Safe refactoring** - Change implementation without breaking tests > **Architecture & Testing**: If you think unit tests are time-consuming and expensive, take a look at our [recommended React architecture](./docs/react-architecture.md). While tests should never dictate architecture, this approach makes your code cleaner, more readable, and extensible - with unit test coverage becoming a natural byproduct. The cleaner your code, the faster and easier unit testing becomes. ## 🧪 Testing Philosophy > **"Don't test React or third-party libraries - only test the code YOU wrote here."** > _Shallowly's core mantra_ ### Why this matters: 1. 🚫 **No redundant tests** - React and popular libraries are already well-tested by their maintainers 2. 💡 **Focus on business logic** - Verify only your unique functionality 3.**Blazing fast** - Skip unnecessary rendering of entire component trees 4. 🎯 **Precise targeting** - Test components in complete isolation 5. 🔒 **Future-proof** - Your tests won't break when dependencies update > "Good tests don't check how React works - they check how YOUR application works with React." ### What this means in practice: ✅ DO test: - Your component's output - Your business logic - Your custom hooks - Your state management ❌ DON'T test: - React's internal behavior - Third-party component rendering - Library implementation details ## The Modern Shallow Renderer for React 18+ Testing **The modern Enzyme alternative** for fast unit testing with: - ✅ Full React 18+ support (Hooks, Context, Suspense) - 🚀 Enzyme 🔚💀 It is no longer supported or operational. -**7x faster** than React Testing Library - 🔍 Built-in debug with `.textWithProps()`, `.textInline()`, and `.textWithPropsInline()` - 📦 5KB size (3x smaller than Enzyme) 🔚💀 It is no longer supported or operational. - 🛠 Familiar API - easy migration from Enzyme ## 🚀 Why Shallowly? Enzyme is deprecated, and React Testing Library doesn't support shallow rendering. Shallowly solves this with: - ✔ Future-proof - Full support for React 18+ (Hooks, Context, Suspense) - ✔ Blazing fast - 2x quicker render cycles than Enzyme (benchmarks) - ✔ Familiar API - Enzyme-like syntax for painless migration - ✔ Debug-friendly - `.textWithProps()` / `.textWithPropsInline()` reveal structure with props, `.textInline()` gives compact text output - ✔ Tiny footprint - 5KB (gzipped), zero dependencies ```bash npm install shallowly # or yarn add shallowly ``` ## ✨ Key Features ### 1. React 18+ Ready Test modern features without workarounds: ```jsx shallow( <Suspense fallback={<Loader />}> <AsyncComponent /> </Suspense>, ); ``` ### 2. Enzyme Compatibility Layer ```diff - import { shallow } from 'enzyme'; + import { shallow } from 'shallowly'; // Same API! ``` ### 3. Visual Debugging ```jsx console.log(wrapper.textWithProps()); console.log(wrapper.textWithPropsInline()); console.log(wrapper.textInline()); // Outputs: // <DataFetching isLoading={true}> // <Spinner /> // </DataFetching> // <DataFetching isLoading={true}><Spinner /></DataFetching> // <DataFetching><Spinner /></DataFetching> ``` ### 4. TypeScript Native ```tsx const wrapper = shallow<Props>(<User id={123} />); wrapper.prop('id'); // Type-safe: number ``` ## 📦 Quick Start ### Install: ```bash npm install shallowly --save-dev ``` ### Write tests: ```jsx import { shallow } from 'shallowly'; import vi from 'vitest'; const MyComponent = ({ name, age, onClick }) => ( <div className="container"> <h1>Hello {name}</h1> <p>You are {age} years old</p> <button onClick={onClick}>Click me</button> </div> ); describe('🐛 MyComponent', () => { it('🧪 default', () => { expect.hasAssertions(); //☣️ Arrange (всякие моки) const onClickSpy = vi.fn(); //🔥 Act const wrapper = shallow(<MyComponent name="John" age={30} onClick={onClickSpy} />); //❓ Assert expect(wrapper.text()).toMatchSnapshot(); }); it('🧪 button prop onClick', () => { expect.hasAssertions(); //☣️ Arrange (всякие моки) const onClickSpy = vi.fn(); //🔥 Act const wrapper = shallow(<MyComponent name="John" age={30} onClick={onClickSpy} />); //❓ Assert expect(wrapper.find('button').prop('onClick')).toBe(onClickSpy); }); }); ``` ### Snapshot Testing ```snap // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`🐛 MyComponent > 🧪 default 1`] = ` "<div> <h1> Hello John </h1> <p> You are 30 years old </p> <button> Click me </button> </div>" `; ``` ## ⚡ Performance Comparison | Operation | Shallowly 🚀 | Enzyme | React Testing Library | | ------------------------ | -----------: | ---------------------------------------------: | --------------------: | | **Basic component** | 12ms ⚡ | 🔚💀 It is no longer supported or operational. | 85ms (7.1x slower) | | **100 components** | 650ms ⚡ | 🔚💀 It is no longer supported or operational. | 4500ms (6.9x slower) | | **Hook-heavy component** | 18ms ⚡ | 🔚💀 It is no longer supported or operational. | 210ms | | **Tree traversal** | 8ms ⚡ | 🔚💀 It is no longer supported or operational. | 150ms | **Key takeaways:** - 🏎️ Enzyme 🔚💀 It is no longer supported or operational. -**7x faster** than React Testing Library - 🧠 **40% less memory usage** compared to Enzyme - 🌳 **Zero DOM** - pure React reconciliation ## 🛠 Perfect For - ✅ Unit testing React components - ✅ Migrating from Enzyme - ✅ Testing complex hooks/context flows - ✅ CI pipelines (fast execution) ## 🚫 What Shallowly Is NOT For: - ❌ End-to-end testing (use Cypress/Playwright) - ❌ Full integration testing (use RTL) - ❌ Visual regression testing (use Storybook/Chromatic) ## 📊 Unit Testing Pyramid ```terminal pie title Test Distribution "Unit (Shallowly)" : 70 "Integration" : 20 "E2E" : 10 ``` 📚 [English Documentation](/docs/index.md) | 🇷🇺 [Документация на русском](/docs/index.ru.md) | 🐞 [Report Issues](https://github.com/bad4iz/shallowly/issues) "Saved us 300+ lines of test boilerplate!" - @bad4iz