Playwright Component Testing in Large Frontend Codebases
Not every component needs a real browser. Here's a clear decision framework for when Playwright component testing adds value and when Jest already covers it.

Playwright Component Testing (CT) runs components in a real browser without spinning up your full application. That puts it between Jest (fast, no browser) and E2E tests (real browser, full stack). In small projects the distinction barely matters. In design systems, multi-package monorepos, and shared component libraries, it does.
Unit tests don't render in a browser. E2E tests do, but they bring the entire application with them. That leaves a gap: bugs that only appear when a component runs in a live browser environment without the full stack around it. Layout calculations, CSS cascade behavior, IntersectionObserver, viewport-relative positioning. JSDOM can't catch these. CT can.
CT is still experimental. The API can change between minor versions without deprecation warnings. A community member proposed an alternative architecture in 2023. The Playwright team said they'd considered a similar approach but had "no plans to do so in the near future" since their focus was on end-to-end testing. When the community asked when CT would leave experimental status, a maintainer acknowledged interest and tagged a team member to look at it, but no public timeline or stable release has materialized since. If you've been waiting for stability guarantees before adopting CT, you'll be waiting a while. The question is whether pinning versions and absorbing upgrade work is worth the tradeoff for your codebase.
This guide covers the architecture decisions that determine whether CT is the right choice, and how to scale it without getting burned by breaking changes.
What Playwright Component Testing Actually Is (And Isn't)
The Rendering Model and the Node-Browser Boundary
Playwright CT runs on a dual-environment model. Node.js orchestrates the test while components render in a real browser served through a Vite dev server. This split introduces a serialization boundary that shapes how you write tests.
Only JSON-serializable data crosses that boundary. Plain objects, strings, numbers, and primitives pass through cleanly. Complex runtime values like class instances, database connections, and Node's process object do not. Functions passed as props become async dispatchers internally, so any prop function expected to return a value synchronously will return undefined inside the component. This is a known limitation that breaks render-prop patterns in libraries like Formik and React Hook Form.
This means you can't define test components inline in your test file. Playwright's docs recommend a "story wrapper" approach: a dedicated wrapper component that constructs complex objects in the browser and exposes only serializable signals back to the test. In larger codebases, this becomes the standard pattern for any component with non-trivial props.
The payoff for this constraint is real browser rendering. Layout, styling, fonts, viewport behavior, IntersectionObserver, ResizeObserver, and every other browser API behave exactly as they would in production. JSDOM doesn't replicate any of this.
What It Is Not
CT is not a replacement for Jest and Testing Library on logic-heavy components. If a component's correctness depends on state transformations, data formatting, or callback logic rather than browser rendering, Jest is faster and sufficient.
CT also mounts components in isolation. Tests that require routing, authentication, backend state, or cross-component flows belong in E2E.
Visual regression in CT works through the same toHaveScreenshot() mechanism Playwright uses for E2E. Baselines are generated on first run and committed to the repository. But CT doesn't give you a component-aware visual workflow on top of that. No story-style organization, no per-component approval flow, no dashboard for reviewing snapshots across runs. If you need that layer, pair CT with Storybook and Chromatic.
The Experimental Label: What It Actually Means for Adoption
Experimental is not a formality. Config options and hook signatures have changed across releases without deprecation warnings. The core mount API has remained stable, but everything around it is fair game. The community has asked repeatedly when CT will leave experimental status. A maintainer assigned someone to look at it, but no public timeline has followed.
Playwright 1.59, released April 2026, removed @playwright/experimental-ct-svelte entirely. No deprecation warning beforehand. If you're using Svelte, you now have two paths: migrate component tests to a custom setup on the main @playwright/test runner, or pin to Playwright 1.58 indefinitely. The migration isn't a config switch. Standard @playwright/test has no built-in mount fixture for Svelte components, so you need your own Vite config, HTML entry point, and mount helper. This is what breaking changes in experimental packages look like.
The practical response: pin @playwright/experimental-ct-* to exact versions. Test upgrades in a separate branch before merging. Budget for migration work if the architecture changes. Whether that tradeoff is worth it depends on where CT fits in your testing stack.
Where Playwright CT Fits in the Testing Pyramid
Martin Fowler's test pyramid places fast unit tests at the base, integration tests in the middle, and slow E2E tests at the top. Playwright CT sits in that middle layer, but only when a component’s correctness depends on real browser rendering or native browser APIs.
The decision follows directly from what JSDOM can and cannot do:
-
<DataGrid>with virtual scrolling and sticky headers: CT. JSDOM does not compute layout, which means scroll behavior and sticky positioning can pass in test and fail in production. -
<LoginForm>calling onSubmit with email and password: Jest. Reaching for CT here is the most common misstep. There is no browser behavior to validate, only callback logic that Jest handles directly. -
<Tooltip>positioning based on viewport edges: CT. The logic depends ongetBoundingClientRect, and JSDOM's implementation is incomplete enough to produce false positives. -
<AuthProvider>managing tokens in context: Jest. Routing this through CT adds browser overhead to a test that relies entirely on state. -
<FileUploader>using drag-and-drop and the File API: CT. JSDOM's File API stubs break under real interaction patterns, and those issues often appear only in production.
The harder cases are components that mix both. A <DateRangePicker> has callback logic (date validation, formatting) and browser-dependent behavior (calendar dropdown positioning, focus management). Don't test everything with CT just because one part needs a browser. Split it: Jest for the date validation logic, CT for the dropdown positioning and keyboard navigation. If the component is well-factored, the logic lives in a hook or utility that you test separately.
The practical threshold: if fewer than ~10 components in your codebase need real-browser validation, skip the CT pipeline entirely. Mount those components in your E2E suite instead. The overhead of maintaining a separate CT config, CI job, and upgrade process isn't worth it for a handful of tests. CT starts paying off when you have a shared component library or design system where 30+ components need rendering validation independent of any application.
The Cost Model
CT starts a real browser and Vite dev server once per worker. The first test in each file pays that startup cost (typically 2-5 seconds for Vite's cold start, depending on your dependency tree). After that, the Vite server stays warm and CT reuses the context and page fixture across tests in the same file, resetting both between each test.
To put this in perspective: a Jest unit test runs in single-digit milliseconds. A CT test runs in 50-200ms after warm-up, plus the per-worker startup cost amortized across tests. For a file with 20 CT tests, you're looking at roughly 5-8 seconds total vs. under a second in Jest. That overhead is worth it when you're testing real browser behavior. It's waste when you're testing callback logic.
Each CT worker also holds a browser process and a Vite dev server in memory. On CI runners with 4GB RAM, you'll typically max out at 3-4 parallel CT workers before hitting memory pressure. E2E suites face the same browser constraint, but CT adds the Vite process on top. If you're running CT alongside E2E in the same pipeline, budget your worker count accordingly.
The context/page reset between tests is described in the docs as "functionally equivalent" to getting a fresh context per test. In practice, watch for global side effects that survive the reset: a component that appends a <style> tag to document.head, registers a document-level event listener, or mutates window globals can leak state into the next test. If test A adds a global stylesheet and test B assumes a clean DOM, you get order-dependent failures that only appear when tests run in sequence within the same file. Group related component tests in the same file, but keep unrelated components in separate files so they get separate browser contexts.
Common Pitfalls
CT adoption rarely fails at scale. It fails in the first week, during setup and initial integration.

Vite plugin conflicts. Playwright CT doesn't reuse your existing vite.config.ts. Server-side or environment-specific plugins fail silently in the CT context. Don't assume plugins carry over. Audit each one.
Serialization boundary surprises. If you're coming from Jest, you expect to pass any object as a prop. Complex objects, function return values, and inline component declarations all break across the Node-browser boundary. The errors are often cryptic (e.g., undefined where you expected a callback result). Document these failure modes early and make the story wrapper pattern the default.
Accidental E2E/CT config overlap. Overlapping testMatch patterns between playwright.config.ts and playwright-ct.config.ts route specs through the wrong runner. This is easy to miss because both runners execute successfully. Keep patterns mutually exclusive (e.g., *.ct.spec.ts vs *.e2e.spec.ts) and verify them after every Playwright upgrade.
Provider tree drift. The beforeMount hook wrapping components with providers can gradually fall out of sync with the production provider tree. The result: CT passes while production fails due to a missing provider. Treat playwright/index.tsx as production code. Review it in PRs, test it, and update it whenever your provider tree changes.
Over-testing with CT. If you're writing CT tests for a <LoginForm> that just calls onSubmit, you're paying browser overhead for something Jest handles in milliseconds. Each CT test should answer a question Jest can't: a browser API interaction, a layout dependency, or a CSS behavior that only appears in a real rendering engine.
Version pinning neglect. In monorepos where packages update independently, unpinned @playwright/experimental-ct-* versions create silent version skew. One package runs CT on 1.58, another on 1.59, and suddenly your Svelte CT tests stop compiling. Pin to exact versions across every package.
CSS Modules naming. Vite requires CSS Modules files to use the *.module.[ext] convention. Projects importing CSS files without the .module prefix fail in CT with no useful error message. This comes from Vite, not Playwright, but it surfaces during CT adoption when the main app uses a more flexible bundler like webpack.
Architectural Setup in Large Codebases
Large codebases expose CT configuration problems that don't appear in smaller setups. The decisions you make at setup (monorepo structure, Vite config, file organization, TypeScript aliases) determine whether CT scales cleanly.

Monorepo Placement and Configuration
Root-level configuration is where monorepo setups run into trouble. A root-level playwright-ct.config.ts forces every package's Vite plugins, path aliases, and environment assumptions into a single ctViteConfig. That works until two packages rely on incompatible plugin versions or conflicting aliases. At that point, the config becomes a negotiation between unrelated packages, and the CT setup becomes more difficult to work with.
Package-level CT configs are the more durable approach for monorepos with diverging Vite needs. The cost is real: a 30-package monorepo means 30 separate playwright-ct.config.ts files, each carrying its own plugin list, alias map, and version pins. Extracting a shared base config into an internal package reduces that overhead, but each package still requires its own config file.
For monorepos where packages share identical Vite setups, a root-level config is fine. For those with genuine Vite divergence, per-package isolation is worth the maintenance cost.
Vite Config: What Actually Happens
The official guidance is clear: "Playwright is bundler-agnostic, so it is not reusing your existing Vite config." Every path alias and plugin must be manually copied into the ctViteConfig property inside playwright-ct.config.ts:
// playwright-ct.config.ts
import { defineConfig } from '@playwright/experimental-ct-react';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
use: {
ctViteConfig: {
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
},
},
});
You can use Vite's loadConfigFromFile to pull in an existing config dynamically, but it's not automatic. There's a longstanding behavior (#19829, reported in 2023 and closed without a fix) where ctViteConfig overwrites resolve.alias and plugins arrays rather than merging them. Setting a custom alias or adding a plugin replaces Playwright's injected entries. This means you must include @vitejs/plugin-react or @vitejs/plugin-vue in the plugins array every time you customize ctViteConfig, or the component bundle will fail to build with no useful error message.
Test File Organization
Place CT tests with the components they cover. CT tests are tightly coupled to a single component's rendering behavior, not to application flows. When a component moves, its CT test moves with it. Separation makes sense for E2E tests that span multiple pages, not for CT tests focused on one component.
Use distinct file suffixes to prevent CT and E2E specs from overlapping. Patterns like .ct.spec.ts and .e2e.spec.ts keep testMatch configs separate. Verify those patterns during Playwright version upgrades.
TypeScript Path Aliases
Alias resolution must stay consistent across both ctViteConfig and tsconfig.json. Imports that work in component source files but fail in CT test files usually trace back to aliases defined in tsconfig.json but missing from ctViteConfig. Duplicate them in both places.
Mounting Strategies for Complex Components
Mounting a simple component in CT is straightforward. Mounting one that includes providers, complex props, network dependencies, or lifecycle behavior requires patterns that remain reliable across a large test suite.
The beforeMount/afterMount Hooks System
The beforeMount and afterMount hooks live in playwright/index.ts and run entirely in the browser. They wrap components with providers, routers, and state stores before or after mounting, and support a hooksConfig parameter for per-test customization.
// playwright/index.tsx (React)
import { beforeMount, afterMount } from '@playwright/experimental-ct-react/hooks';
import { BrowserRouter } from 'react-router-dom';
export type HooksConfig = { enableRouting?: boolean };
beforeMount<HooksConfig>(async ({ App, hooksConfig }) => {
if (hooksConfig?.enableRouting) {
return <BrowserRouter><App /></BrowserRouter>;
}
});
afterMount<HooksConfig>(async ({ hooksConfig }) => {
});
The configuration style varies by framework. In Vue, you call app.use() inside beforeMount. In React, you wrap with JSX.
A common mistake is building a custom mountWithProviders helper that replicates this behavior across test files. This scatters provider logic and makes drift harder to detect. The hooks file is the single source of provider configuration. Don't duplicate it.
The Story Wrapper Pattern
Components with function props, render props, or class instances cannot pass complex objects across the Node-browser boundary. The story wrapper pattern addresses this by introducing a wrapper component that runs in the browser and constructs the required objects internally.
It accepts only serializable props from the test, handles complex setups internally in the browser, and signals results back through simple primitives:
// CheckoutFormWrapper.tsx — lives in the browser, NOT in the test file
import { CheckoutForm } from './CheckoutForm';
export function CheckoutFormWrapper({
onSubmitCalled,
}: {
onSubmitCalled: () => void;
}) {
return (
<CheckoutForm
onSubmit={() => onSubmitCalled()}
validationSchema={buildSchema()}
/>
);
}
Then in your test file:
// CheckoutForm.ct.spec.tsx
import { test, expect } from '@playwright/experimental-ct-react';
import { CheckoutFormWrapper } from './CheckoutFormWrapper';
test('form submits', async ({ mount }) => {
let submitted = false;
const component = await mount(
<CheckoutFormWrapper onSubmitCalled={() => { submitted = true; }} />
);
await component.getByRole('button', { name: 'Submit' }).click();
expect(submitted).toBe(true);
});
Schema construction, class instantiation, and render prop logic all stay in the browser where they belong. The test only sees the boolean callback that crosses the boundary cleanly.
If you already use Storybook, there's a more direct adoption path. Storybook's portable stories API lets you run stories natively in Playwright CT. The pattern uses createTest from Storybook's Playwright integration:
import { createTest } from '@storybook/react/experimental-playwright';
import { test as base } from '@playwright/experimental-ct-react';
import stories from './Button.stories.portable';
const test = createTest(base);
test('renders primary button', async ({ mount }) => {
const component = await mount(<stories.Primary />);
await expect(component).toContainText('Click me');
});
The story carries the props, decorators, and parameters the component needs. The test focuses only on the assertion. Two constraints: portable stories require React 18 or later and are not currently supported in Next.js projects.
Network Mocking with the Router Fixture
The experimental router fixture intercepts network requests at the component level. router.route(url, handler) works like page.route() in standard Playwright tests. router.use(...handlers) accepts MSW request handlers, so you can reuse mocks from your development setup. For a broader overview of request interception patterns, see the Playwright network mocking playbook.
Install shared handlers in test.beforeEach and add per-test overrides with individual router.use() calls. This keeps network behavior explicit at the test level rather than buried in Vite configuration.
One risk worth naming: the router fixture carries its own experimental label on top of CT's. The core mount API has held steady across releases, but router is newer and has higher change risk. If you'd rather avoid that, page.route() works fine as the stable fallback with slightly more verbose setup.
Module Mocking
Playwright CT has no jest.mock() equivalent. Module-level mocks run in the test process, not in the browser, so they don't affect what the component imports at runtime. This is the single biggest friction point when migrating from Jest to CT.
For dependencies that aren't network requests, three approaches work:
Dependency injection via props or context. The cleanest option when you control the component's API. Instead of importing an analytics SDK directly, accept it as a prop or read it from context. The test passes a stub. This is good architecture anyway, but retrofitting it onto existing components takes effort.
Vite plugin-based import replacement inside ctViteConfig. Use Vite's resolve.alias to swap a module at build time. For example, if your component imports @/services/analytics, you can redirect it to a stub module during CT:
// playwright-ct.config.ts
ctViteConfig: {
plugins: [react()],
resolve: {
alias: {
'@/services/analytics': path.resolve(__dirname, './test/stubs/analytics.ts'),
'@/services/feature-flags': path.resolve(__dirname, './test/stubs/feature-flags.ts'),
},
},
},
This works globally across all CT tests, which is both its strength (no per-test setup) and its weakness (you can't vary the mock per test without more indirection). For per-test control, make the stub module export a function that reads configuration from window, and set that configuration in beforeMount via hooksConfig.
The story wrapper pattern. The wrapper swaps implementations before the component renders. Most flexible, but adds a file for every component that needs mocking.
If a component requires multiple mocked imports just to render in isolation, that's a signal. CT exposes tight coupling more clearly than Jest does, because there's no escape hatch to mock at the module level. If you find yourself writing five aliases just to mount a component, the component probably needs refactoring more than it needs CT.
Lifecycle Testing with unmount and update
Playwright CT provides two lifecycle APIs that standard E2E tests don't have:
-
component.unmount()removes the component from the DOM. Use it to validate event listener cleanup, subscription cancellation, and navigation guard behavior. If your component sets up aResizeObserveror WebSocket connection,unmount()lets you assert it was torn down properly. -
component.update()re-renders with new props, children, or callbacks without a full remount. One thing that trips people up:update()requires the full JSX element again, not just the changed props. You're passing<Component msg="new" onClick={() => {}} />, not a partial props object. Functions passed throughupdate()hit the same serialization boundary asmount(), so they won't return values synchronously.
Scaling CT in CI
CT doesn't need a backend, a running server, or a seeded database. This changes how it fits into CI. Getting the setup wrong early creates slow pipelines that push you away from CT before you see its value.
Separating CT and E2E Pipelines
Running CT and E2E in the same CI job is one of the most common mistakes. CT needs npm ci, browser binaries, and nothing else. E2E needs all of that plus your application stack, database seeds, and environment config. Mixing them means every CT run pays for infrastructure it doesn't use, and every mixed failure forces you to figure out whether the problem is a component or the backend.
Separate CI jobs. Use distinct commands: npx playwright test --config=playwright-ct.config.ts for CT and your standard E2E config for the rest. The failure signal becomes precise: CT failures point to component rendering, E2E failures point to application issues.
Parallelization
CT suites benefit from the same sharding setup as E2E tests. Since there's no application stack to start, CT jobs boot faster and use fewer resources per worker. You can run CT shards on smaller CI machines than E2E, which saves money at scale.
strategy:
matrix:
shard: [1/4, 2/4, 3/4, 4/4]
steps:
- run: npx playwright test --config=playwright-ct.config.ts --shard=${{ matrix.shard }}
In large monorepos with hundreds of CT specs, sharding across four workers cuts suite time proportionally. For more detail on the tradeoffs between sharding and workers, see sharding vs. workers.
Caching Strategy
CT adds one startup cost E2E pipelines don't have: Vite dev server initialization. On a cold CI runner, Vite processes the component bundle from scratch on every run. Two caches address this:
- Cache Playwright browser binaries at
~/.cache/ms-playwrightas usual - Cache Vite's dependency pre-bundle directory (
node_modules/.vite) between runs
A warm Vite cache cuts startup time on subsequent CI runs. The difference is most noticeable on the first test file per worker, where Vite processes your component's dependency tree from scratch on a cold cache.
Unified Reporting
Playwright CT uses the same reporter infrastructure as E2E tests. Assign distinct project names (one for CT, one for E2E) so failures don't merge into a single list. This makes it immediately clear whether a pipeline failure is component-level or application-level without parsing logs.
Any reporting tool that works with Playwright works with CT. Currents supports CT runs through the same reporter that handles E2E, surfacing screenshots, traces, and performance metrics alongside each run. The same applies to debugging CT failures in CI and general CI setup patterns.
Playwright CT vs. the Alternatives
The right choice depends on what the component needs to cover and how your existing test stack is structured.
| Dimension | Playwright CT | Cypress CT | Jest + RTL | Vitest Browser Mode | Storybook + Vitest |
|---|---|---|---|---|---|
| Real browser rendering | Yes | Yes | No (JSDOM) | Yes | Yes |
| Execution speed | Fast | Moderate | Fastest | Fast | Fast |
| Cross-browser support | Chromium, Firefox, WebKit | Chromium, Firefox, experimental WebKit | N/A | Depends on provider (Playwright or WebDriverIO) | Primarily Chromium |
| Module mocking | Vite plugin only | Vite plugin only | jest.mock() | vi.mock() | vi.mock() |
| Network mocking | router fixture + MSW | cy.intercept() + MSW | MSW / manual | MSW | MSW |
| Native browser API support | Full | Full | Limited, JSDOM stubs | Full | Full |
| CI integration | Standard | Standard | Standard | Standard | Standard |
| Interactive debugging | Trace viewer | Command timeline UI | None | Vitest UI | Storybook UI |
| Component library support | Portable stories | Portable stories | Testing Library | Storybook + Vitest | Native, stories are test |
Playwright CT vs. Jest + React Testing Library
Jest + RTL runs in JSDOM. No browser startup, no Vite dev server, immediate feedback. Its mocking ecosystem is the most mature of any component testing option, and RTL's user-event covers most interaction patterns without a real browser.
Use both together. Jest handles logic-heavy components. CT covers rendering-dependent ones. The decision tree from the testing pyramid section gives you the routing rule. Don't replace Jest with CT. Add CT where Jest can't reach: getBoundingClientRect, scroll layout, CSS cascade, viewport behavior, native File API.
If you're on Svelte, note that both @testing-library/svelte and Playwright CT for Svelte have thinner community coverage than their React and Vue equivalents. With @playwright/experimental-ct-svelte removed in Playwright 1.59, Svelte CT requires a custom setup.
Playwright CT vs. Storybook Test
If you already run Storybook, the Vitest addon turns stories into tests that run in browser mode using Playwright's Chromium under the hood. You get browser-level rendering with execution speeds closer to Vitest than Playwright CT, because it reuses browser sessions more aggressively.
The tradeoff is isolation. Playwright CT resets context and page between tests, catching state-leak bugs that Storybook Test's session reuse can miss. If your component touches localStorage, a global event bus, or singleton state, Playwright CT gives you cleaner isolation. If your tests are mostly presentational assertions (correct class names, visible text, layout checks), Storybook Test is faster and simpler.
Playwright CT vs. Cypress CT
Cypress CT remains actively maintained. Its interactive runner is better for step-through debugging. The command timeline and time-travel snapshots give you a different debugging experience than Playwright CT's trace viewer, one that's closer to stepping through code than replaying a recording.
Playwright CT is faster per test due to lower setup cost and uses native async/await instead of Cypress's chainable command queue. Cross-browser support across Chromium, Firefox, and WebKit is a differentiator if you need it, though in practice most CT runs target Chromium only.
Stack alignment drives this decision more than feature comparison. If you already run Playwright for E2E, use Playwright CT. You get a unified runner, config model, and reporting pipeline. If you're on Cypress E2E, Cypress CT is less friction. Switching CT frameworks independent of your E2E framework creates maintenance overhead that rarely pays off.
If you're on Angular, the decision is different: Playwright has no official Angular CT package. Your options are Cypress CT or Storybook + Vitest.
Playwright CT vs. Storybook + Chromatic
Storybook is a development and documentation tool. Playwright CT is a testing tool. Don't conflate them.
Storybook excels at visual development, design system documentation, and visual regression through Chromatic. CT excels at behavioral assertions in CI. They're complementary, not competing. Storybook's portable stories work natively in Playwright CT, so stories written for documentation become CT fixtures without duplication. If you already have Storybook, adopt CT incrementally by using stories as the foundation for behavioral tests. You get visual regression from Chromatic and behavioral coverage from CT without writing anything twice.
Should You Adopt Playwright CT?
Adopt it if:
- You're shipping bugs that Jest missed because JSDOM doesn't compute layout, doesn't run CSS cascade, or stubs native APIs incorrectly. CT exists to close that gap.
- You maintain a shared component library or design system with 30+ components that need rendering validation independent of any specific application.
- You already run Playwright for E2E and want a single runner, config model, and reporting pipeline across both layers.
Skip it if:
- Your components are logic-heavy (state management, data transformation, callbacks) and Jest already catches what breaks. Browser overhead for callback tests is waste.
- Fewer than 10 components need real-browser validation. At that scale, run them in your E2E suite. The overhead of a separate CT pipeline, config, and upgrade process isn't justified.
- You can't commit to version pinning and a consistent upgrade process for an experimental API. If you run
npm updatewithout checking changelogs, CT will burn you.
CT is its own infrastructure layer. Scope it to components where it provides clear value, run it as a separate CI pipeline, and keep CT and E2E results visible in one place.
Join hundreds of teams using Currents.
Trademarks and logos mentioned in this text belong to their respective owners.



