| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Run Vitest unit and UI tests inside real NativeScript runtimes on Android, iOS, and visionOS.
Vitest stays on your machine as the orchestrator — configuration, CLI, reporters, --ui, coverage, and editor integrations all work as usual — while your specs execute on device/emulator inside the actual V8/JSC runtimes, with full access to native APIs and the NativeScript UI layer.
Version 5 is a complete rewrite. Karma-based testing (v4 and below) is deprecated; see the migration guide.
ns test init --framework vitest
ns test ios # or: ns test android / ns test visionosOr run Vitest directly (what editor extensions and CI use):
NS_PLATFORM=ios npx vitest run// vitest.config.mts
import { defineConfig } from 'vitest/config';
import { nativeScript } from '@nativescript/unit-test-runner';
export default defineConfig({
plugins: [
nativeScript({
platform: process.env.NS_PLATFORM || 'ios', // 'android' | 'ios' | 'visionos'
device: process.env.NS_DEVICE || undefined,
// workers: 2, // extra Worker runtimes for non-UI specs
// mainThread: false, // disable the UI-capable slot (workers only)
// port: 17878,
// launch: false, // attach to an app you run yourself
}),
],
});Per-platform setups are possible with Vitest projects — give each project its own nativeScript({ platform }) plugin instance.
import { describe, expect, it } from 'vitest';
import { Button } from '@nativescript/core';
import { mount, tap } from '@nativescript/unit-test-runner/testing';
describe('counter button', () => {
it('increments on tap', async () => {
let count = 0;
const { view } = await mount(() => {
const button = new Button();
button.text = 'Count';
button.on('tap', () => (count += 1));
return button;
});
await tap(view);
expect(count).toBe(1);
expect(view.isLayoutValid).toBe(true);
});
});mount() attaches the view to the host page scaffolded in your test.ts, waits for loaded + a real layout pass, and auto-unmounts when the test finishes. Also available from ./testing: tap, doubleTap, longPress, enterText, returnPress, waitForLayout, waitUntil, nextRenderPass.
UI specs require the main-thread context (the default). Files routed to Worker contexts must not touch Views.
ns test ios --env.codeCoverage
# or: NS_PLATFORM=ios npx vitest run --coverageUse the istanbul provider — device runtimes do not expose V8 coverage:
test: {
coverage: { provider: 'istanbul', reporter: ['text', 'lcov'] },
},| Target | Transport |
|---|---|
| iOS / visionOS simulator | host loopback (127.0.0.1) |
| Android emulator | 10.0.2.2 → host loopback |
| Physical Android | USB via automatic adb reverse |
| Physical iOS / Apple Vision Pro | pass a LAN-reachable url to the coordinator in test.ts |
The host server binds 127.0.0.1 by default. Test builds on Android may need a scoped cleartext exception for 10.0.2.2/127.0.0.1; on iOS and visionOS, NSAllowsLocalNetworking.
| Feature | Status |
|---|---|
| describe / it / hooks / expect | ✅ |
| Reporters, vitest --ui, JUnit output | ✅ |
| Istanbul coverage | ✅ |
| UI testing (mount, gestures) | ✅ main-thread context |
| vi.fn / vi.spyOn / fake timers | 🚧 planned |
| Snapshots | 🚧 planned |
| Watch mode | 🚧 planned (one-shot vitest run today) |
| vi.mock module mocking | ❌ not supported (webpack static bundle) — prefer DI |
The host↔device bridge design originates from @cross-code/vitest-ns by @listepo (MIT). Thank you!
Apache-2.0
| Back | FazBrowse Home | New Git URL |