mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-30 21:23:04 +00:00
* fix(app): dock the New workspace composer like a chat on phones Only the composer is bounded by the viewport; the setup fields sit above it in a bottom-anchored stack that moves up as the draft grows. The keyboard reservation is retained on every screen, so the composer keeps one height across keyboard transitions. Removes the per-screen reserve policy. * fix(app): share composer docking across mobile hosts Extract chat's retained capacity and platform keyboard motion so chat, workspace drafts, and New workspace share one sizing and dismissal boundary. Keep the native drivers and settled portal reconciliation unchanged. * fix(app): preserve overlays in centered composer docks Honor the optional overlay child in both layouts so changing dock placement does not silently discard part of its content. * test(app): resolve keyboard controller through its web entry The shared keyboard entry point makes stream tests load the provider. Keep its real ESM dependencies inside the Vitest resolver so CommonJS does not bypass the React Native web alias and parse native Flow sources. * fix(app): keep native chat scrolling responsive Place keyboard dismissal behind scrollable content so an idle Android Fabric JS responder cannot intercept native drags. Keep decorative form padding transparent to iOS hit testing and exercise idle native scrolling after submission from every composer host.
195 lines
6.8 KiB
TypeScript
195 lines
6.8 KiB
TypeScript
import { defineConfig, configDefaults } from "vitest/config";
|
|
import { playwright } from "@vitest/browser-playwright";
|
|
import path from "path";
|
|
import fs from "fs";
|
|
|
|
const appNodeModules = path.resolve(__dirname, "node_modules");
|
|
const rootNodeModules = path.resolve(__dirname, "../../node_modules");
|
|
const resolvePackageEntry = (packageName: string) => {
|
|
const appPackagePath = path.resolve(appNodeModules, packageName);
|
|
return fs.existsSync(appPackagePath)
|
|
? appPackagePath
|
|
: path.resolve(rootNodeModules, packageName);
|
|
};
|
|
|
|
export default defineConfig({
|
|
test: {
|
|
environment: "node",
|
|
exclude: [...configDefaults.exclude, "e2e/**"],
|
|
projects: [
|
|
{
|
|
extends: true,
|
|
test: {
|
|
name: "unit",
|
|
environment: "node",
|
|
include: ["src/**/*.{test,spec}.{ts,tsx}", "native-release-version.test.ts"],
|
|
setupFiles: [path.resolve(__dirname, "vitest.setup.ts")],
|
|
exclude: [...configDefaults.exclude, "e2e/**", "src/**/*.browser.{test,spec}.{ts,tsx}"],
|
|
},
|
|
},
|
|
{
|
|
extends: true,
|
|
test: {
|
|
name: "browser",
|
|
fileParallelism: false,
|
|
include: ["src/**/*.browser.{test,spec}.{ts,tsx}"],
|
|
browser: {
|
|
enabled: true,
|
|
provider: playwright(),
|
|
headless: true,
|
|
connectTimeout: 180_000,
|
|
instances: [{ browser: "chromium" }],
|
|
screenshotDirectory: ".vitest-screenshots",
|
|
},
|
|
globalSetup: path.resolve(__dirname, "src/runtime/websocket-test-global-setup.ts"),
|
|
},
|
|
},
|
|
],
|
|
/**
|
|
* Expo pulls in native tooling (xcode, etc.) that executes files relying on `process.send`.
|
|
* Vitest's default worker pool uses worker_threads, which intentionally stub that API and
|
|
* immediately throw `Unexpected call to process.send`. Running the suite in forked processes
|
|
* keeps `process.send` intact so the app tests can boot before hitting the intentional failures.
|
|
*/
|
|
pool: "forks",
|
|
maxWorkers: 2,
|
|
server: {
|
|
deps: {
|
|
fallbackCJS: true,
|
|
inline: [
|
|
"zustand",
|
|
"@tanstack/react-query",
|
|
"react-native-web",
|
|
"react-native-gesture-handler",
|
|
"react-native-keyboard-controller",
|
|
],
|
|
},
|
|
},
|
|
},
|
|
// Reanimated and gesture-handler pick platform files by extension
|
|
// (e.g. `GestureHandlerRootView.web.js`). Vite's optimizer does not apply `resolve.extensions`,
|
|
// so it scans the native files and dies on imports react-native-web has no answer for.
|
|
// Unbundled, the same imports go through the resolver below and land on the web files.
|
|
optimizeDeps: {
|
|
// Bundle the CJS dependencies of the excluded gesture-handler package for the browser.
|
|
include: [
|
|
"react/jsx-runtime",
|
|
"react-native-gesture-handler > hoist-non-react-statics",
|
|
"react-native-gesture-handler > invariant",
|
|
],
|
|
exclude: [
|
|
"react-native-reanimated",
|
|
"react-native-gesture-handler",
|
|
"react-native-keyboard-controller",
|
|
],
|
|
},
|
|
// The globals a React Native bundler defines, which esbuild is no longer there to supply for
|
|
// the package excluded above.
|
|
define: {
|
|
"process.env.JEST_WORKER_ID": "undefined",
|
|
__DEV__: "false",
|
|
global: "globalThis",
|
|
},
|
|
resolve: {
|
|
extensions: [
|
|
".web.mjs",
|
|
".web.js",
|
|
".web.mts",
|
|
".web.ts",
|
|
".web.jsx",
|
|
".web.tsx",
|
|
".mjs",
|
|
".js",
|
|
".mts",
|
|
".ts",
|
|
".jsx",
|
|
".tsx",
|
|
".json",
|
|
],
|
|
alias: [
|
|
{
|
|
find: /^@getpaseo\/relay\/e2ee$/,
|
|
replacement: path.resolve(__dirname, "../relay/src/e2ee.ts"),
|
|
},
|
|
{
|
|
find: /^@getpaseo\/relay$/,
|
|
replacement: path.resolve(__dirname, "../relay/src/index.ts"),
|
|
},
|
|
{ find: "@", replacement: path.resolve(__dirname, "src") },
|
|
// Keep keyboard-controller's imports in Vite so native aliases and platform extensions apply.
|
|
{
|
|
find: /^react-native-keyboard-controller$/,
|
|
replacement: path.resolve(
|
|
resolvePackageEntry("react-native-keyboard-controller"),
|
|
"lib/module/index.js",
|
|
),
|
|
},
|
|
// The CJS entry bypasses Vite's React Native alias and web-extension resolution.
|
|
{
|
|
find: /^react-native-gesture-handler$/,
|
|
replacement: path.resolve(
|
|
rootNodeModules,
|
|
"react-native-gesture-handler/lib/module/index.js",
|
|
),
|
|
},
|
|
// Must precede the `react-native` alias: a string `find` matches by prefix, so this subpath
|
|
// would otherwise resolve inside a react-native-web *file* and break the dependency scan.
|
|
// Reanimated only imports it on the native path, which no test takes.
|
|
{
|
|
find: /^react-native\/Libraries\/Renderer\/shims\/ReactFabric$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/react-native-fabric-shim.ts"),
|
|
},
|
|
// Point to the ESM build so Vite can transform its imports and apply the
|
|
// react alias below (the CJS build uses require('react') which bypasses
|
|
// Vite alias resolution).
|
|
{
|
|
find: "react-native",
|
|
replacement: path.resolve(rootNodeModules, "react-native-web/dist/index.js"),
|
|
},
|
|
{ find: "react", replacement: resolvePackageEntry("react") },
|
|
{
|
|
find: "react-dom",
|
|
replacement: resolvePackageEntry("react-dom"),
|
|
},
|
|
{
|
|
find: /^@xterm\/addon-ligatures\/lib\/addon-ligatures\.mjs$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/xterm-addon-ligatures.ts"),
|
|
},
|
|
{
|
|
find: /^@xterm\/addon-ligatures$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/xterm-addon-ligatures.ts"),
|
|
},
|
|
{
|
|
find: /^react-native-unistyles$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/react-native-unistyles.ts"),
|
|
},
|
|
{
|
|
find: /^react-native-svg$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/react-native-svg.ts"),
|
|
},
|
|
// Both ship untranspiled Flow and fail to parse on import, which takes out any test that
|
|
// mounts a menu surface.
|
|
{
|
|
find: /^react-native-safe-area-context$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/react-native-safe-area-context.ts"),
|
|
},
|
|
{
|
|
find: /^@gorhom\/bottom-sheet$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/gorhom-bottom-sheet.ts"),
|
|
},
|
|
{
|
|
find: /^react-native-reanimated\/scripts\/validate-worklets-version$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/reanimated-validate-worklets-version.ts"),
|
|
},
|
|
{
|
|
find: /^expo-linking$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/expo-linking.ts"),
|
|
},
|
|
{
|
|
find: /^lucide-react-native$/,
|
|
replacement: path.resolve(__dirname, "test-stubs/lucide-react-native.ts"),
|
|
},
|
|
],
|
|
},
|
|
});
|