mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-30 23:14:37 +00:00
test(e2e): onboarding simple vs advanced mode spec (#1989)
This commit is contained in:
Generated
+22
-94
@@ -1296,7 +1296,7 @@ dependencies = [
|
||||
"core-foundation-sys 0.8.7",
|
||||
"coreaudio-rs",
|
||||
"dasp_sample",
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"mach2 0.4.3",
|
||||
@@ -3496,36 +3496,6 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.22.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"combine",
|
||||
"jni-macros",
|
||||
"jni-sys 0.4.1",
|
||||
"log",
|
||||
"simd_cesu8",
|
||||
"thiserror 2.0.18",
|
||||
"walkdir",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-macros"
|
||||
version = "0.22.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"simd_cesu8",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-sys"
|
||||
version = "0.3.1"
|
||||
@@ -4896,7 +4866,7 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb"
|
||||
dependencies = [
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"ndk",
|
||||
"ndk-context",
|
||||
"num-derive",
|
||||
@@ -5111,9 +5081,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0"
|
||||
checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@@ -5124,22 +5094,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-http"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d"
|
||||
checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"http 1.4.0",
|
||||
"opentelemetry",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest 0.13.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-otlp"
|
||||
version = "0.31.1"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f"
|
||||
checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35"
|
||||
dependencies = [
|
||||
"http 1.4.0",
|
||||
"opentelemetry",
|
||||
@@ -5147,34 +5117,33 @@ dependencies = [
|
||||
"opentelemetry-proto",
|
||||
"opentelemetry_sdk",
|
||||
"prost 0.14.3",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest 0.13.1",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-proto"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f"
|
||||
checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638"
|
||||
dependencies = [
|
||||
"opentelemetry",
|
||||
"opentelemetry_sdk",
|
||||
"prost 0.14.3",
|
||||
"tonic",
|
||||
"tonic-prost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry_sdk"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd"
|
||||
checksum = "368afaed344110f40b179bb8fbe54bc52d98f9bd2b281799ef32487c2650c956"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-executor",
|
||||
"futures-util",
|
||||
"opentelemetry",
|
||||
"percent-encoding",
|
||||
"portable-atomic",
|
||||
"rand 0.9.4",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
@@ -6195,9 +6164,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.13.3"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0"
|
||||
checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@@ -6231,6 +6200,7 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots 1.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6596,13 +6566,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls-platform-verifier"
|
||||
version = "0.7.0"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
|
||||
checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
|
||||
dependencies = [
|
||||
"core-foundation 0.10.1",
|
||||
"core-foundation-sys 0.8.7",
|
||||
"jni 0.22.4",
|
||||
"jni",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
@@ -6816,7 +6786,7 @@ checksum = "eb25f439f97d26fea01d717fa626167ceffcd981addaa670001e70505b72acbb"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"httpdate",
|
||||
"reqwest 0.13.3",
|
||||
"reqwest 0.13.1",
|
||||
"rustls",
|
||||
"sentry-backtrace",
|
||||
"sentry-contexts",
|
||||
@@ -7157,16 +7127,6 @@ version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
|
||||
|
||||
[[package]]
|
||||
name = "simd_cesu8"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
"simdutf8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.5"
|
||||
@@ -7849,38 +7809,6 @@ version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
|
||||
|
||||
[[package]]
|
||||
name = "tonic"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"http 1.4.0",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"sync_wrapper",
|
||||
"tokio-stream",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic-prost"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost 0.14.3",
|
||||
"tonic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.3"
|
||||
|
||||
+3
-3
@@ -111,9 +111,9 @@ mail-parser = "0.11.2"
|
||||
async-imap = { version = "0.11", features = ["runtime-tokio"], default-features = false }
|
||||
axum = { version = "0.8", default-features = false, features = ["http1", "json", "tokio", "query", "ws", "macros"] }
|
||||
tower = { version = "0.5", default-features = false }
|
||||
opentelemetry = { version = "0.31", default-features = false, features = ["trace", "metrics"] }
|
||||
opentelemetry_sdk = { version = "0.31", default-features = false, features = ["trace", "metrics"] }
|
||||
opentelemetry-otlp = { version = "0.31", default-features = false, features = ["trace", "metrics", "http-proto", "reqwest-client", "reqwest-rustls-webpki-roots"] }
|
||||
opentelemetry = { version = "0.32", default-features = false, features = ["trace", "metrics"] }
|
||||
opentelemetry_sdk = { version = "0.32", default-features = false, features = ["trace", "metrics"] }
|
||||
opentelemetry-otlp = { version = "0.32", default-features = false, features = ["trace", "metrics", "http-proto", "reqwest-client", "reqwest-rustls-webpki-roots"] }
|
||||
sentry = { version = "0.47.0", default-features = false, features = ["backtrace", "contexts", "panic", "tracing", "debug-images", "reqwest", "rustls"] }
|
||||
tokio-stream = { version = "0.1.18", features = ["full"] }
|
||||
url = "2"
|
||||
|
||||
Generated
+31
-122
@@ -1459,7 +1459,7 @@ dependencies = [
|
||||
"core-foundation-sys 0.8.7",
|
||||
"coreaudio-rs",
|
||||
"dasp_sample",
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"mach2 0.4.3",
|
||||
@@ -3779,36 +3779,6 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.22.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"combine",
|
||||
"jni-macros",
|
||||
"jni-sys 0.4.1",
|
||||
"log",
|
||||
"simd_cesu8",
|
||||
"thiserror 2.0.18",
|
||||
"walkdir",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-macros"
|
||||
version = "0.22.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"simd_cesu8",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-sys"
|
||||
version = "0.3.1"
|
||||
@@ -4979,7 +4949,7 @@ version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb"
|
||||
dependencies = [
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"ndk 0.8.0",
|
||||
"ndk-context",
|
||||
"num-derive",
|
||||
@@ -5196,9 +5166,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0"
|
||||
checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@@ -5209,22 +5179,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-http"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d"
|
||||
checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"http",
|
||||
"opentelemetry",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest 0.13.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-otlp"
|
||||
version = "0.31.1"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f"
|
||||
checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35"
|
||||
dependencies = [
|
||||
"http",
|
||||
"opentelemetry",
|
||||
@@ -5232,34 +5202,33 @@ dependencies = [
|
||||
"opentelemetry-proto",
|
||||
"opentelemetry_sdk",
|
||||
"prost",
|
||||
"reqwest 0.12.28",
|
||||
"reqwest 0.13.1",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry-proto"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f"
|
||||
checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638"
|
||||
dependencies = [
|
||||
"opentelemetry",
|
||||
"opentelemetry_sdk",
|
||||
"prost",
|
||||
"tonic",
|
||||
"tonic-prost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opentelemetry_sdk"
|
||||
version = "0.31.0"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd"
|
||||
checksum = "368afaed344110f40b179bb8fbe54bc52d98f9bd2b281799ef32487c2650c956"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-executor",
|
||||
"futures-util",
|
||||
"opentelemetry",
|
||||
"percent-encoding",
|
||||
"portable-atomic",
|
||||
"rand 0.9.4",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
@@ -6428,16 +6397,16 @@ dependencies = [
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams 0.4.2",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
"webpki-roots 1.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.13.3"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0"
|
||||
checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@@ -6471,8 +6440,9 @@ dependencies = [
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams 0.5.0",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
"webpki-roots 1.0.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6663,13 +6633,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls-platform-verifier"
|
||||
version = "0.7.0"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
|
||||
checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
|
||||
dependencies = [
|
||||
"core-foundation 0.10.1",
|
||||
"core-foundation-sys 0.8.7",
|
||||
"jni 0.22.4",
|
||||
"jni",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
@@ -6936,7 +6906,7 @@ checksum = "eb25f439f97d26fea01d717fa626167ceffcd981addaa670001e70505b72acbb"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"httpdate",
|
||||
"reqwest 0.13.3",
|
||||
"reqwest 0.13.1",
|
||||
"rustls",
|
||||
"sentry-backtrace",
|
||||
"sentry-contexts",
|
||||
@@ -7346,22 +7316,6 @@ version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
|
||||
|
||||
[[package]]
|
||||
name = "simd_cesu8"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
"simdutf8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||
|
||||
[[package]]
|
||||
name = "simplecss"
|
||||
version = "0.2.2"
|
||||
@@ -7789,7 +7743,7 @@ dependencies = [
|
||||
"dpi",
|
||||
"gdkwayland-sys",
|
||||
"gtk",
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"libc",
|
||||
"log",
|
||||
"ndk 0.9.0",
|
||||
@@ -7859,7 +7813,7 @@ dependencies = [
|
||||
"gtk",
|
||||
"heck 0.5.0",
|
||||
"http",
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"libc",
|
||||
"log",
|
||||
"mime",
|
||||
@@ -7872,7 +7826,7 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
"plist",
|
||||
"raw-window-handle",
|
||||
"reqwest 0.13.3",
|
||||
"reqwest 0.13.1",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
@@ -8067,7 +8021,7 @@ dependencies = [
|
||||
"minisign-verify",
|
||||
"osakit",
|
||||
"percent-encoding",
|
||||
"reqwest 0.13.3",
|
||||
"reqwest 0.13.1",
|
||||
"rustls",
|
||||
"semver",
|
||||
"serde",
|
||||
@@ -8092,7 +8046,7 @@ dependencies = [
|
||||
"dpi",
|
||||
"gtk",
|
||||
"http",
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"objc2 0.6.4",
|
||||
"objc2-ui-kit",
|
||||
"raw-window-handle",
|
||||
@@ -8138,7 +8092,7 @@ version = "2.10.1"
|
||||
dependencies = [
|
||||
"gtk",
|
||||
"http",
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"log",
|
||||
"objc2 0.6.4",
|
||||
"objc2-app-kit 0.3.2",
|
||||
@@ -8651,38 +8605,6 @@ version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
|
||||
|
||||
[[package]]
|
||||
name = "tonic"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"sync_wrapper",
|
||||
"tokio-stream",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tonic-prost"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost",
|
||||
"tonic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.3"
|
||||
@@ -9424,19 +9346,6 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-streams"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.244.0"
|
||||
@@ -10427,7 +10336,7 @@ dependencies = [
|
||||
"gtk",
|
||||
"http",
|
||||
"javascriptcore-rs",
|
||||
"jni 0.21.1",
|
||||
"jni",
|
||||
"libc",
|
||||
"ndk 0.9.0",
|
||||
"objc2 0.6.4",
|
||||
|
||||
@@ -892,6 +892,7 @@ const VoicePanel = ({ embedded = false }: VoicePanelProps = {}) => {
|
||||
<label className="flex items-center gap-2 text-sm text-stone-700">
|
||||
<input
|
||||
type="checkbox"
|
||||
data-testid="voice-auto-start-toggle"
|
||||
checked={settings.auto_start}
|
||||
onChange={e => updateSetting('auto_start', e.target.checked)}
|
||||
className="h-4 w-4 rounded border-stone-300 text-primary-600 focus:ring-primary-500"
|
||||
@@ -987,6 +988,7 @@ const VoicePanel = ({ embedded = false }: VoicePanelProps = {}) => {
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<button
|
||||
type="button"
|
||||
data-testid="voice-save-settings"
|
||||
onClick={() => void saveSettings(true)}
|
||||
disabled={disabled || isSaving || !hasUnsavedChanges}
|
||||
className="px-3 py-1.5 text-xs rounded-md bg-primary-600 hover:bg-primary-700 disabled:opacity-60 text-white">
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Read-only helpers for the core's on-disk `config.toml`.
|
||||
*
|
||||
* `app/scripts/e2e-run-session.sh` always exports `OPENHUMAN_WORKSPACE` and
|
||||
* the core writes its config under that root (see `Config::load_or_init`).
|
||||
* We assert against the resulting file in onboarding/settings specs that
|
||||
* need to confirm UI mutations land in the persisted config.
|
||||
*
|
||||
* Intentionally minimal: a regex-based reader, not a full TOML parser. The
|
||||
* keys we care about (`onboarding_completed`, `voice_server.auto_start`,
|
||||
* etc.) are simple `key = value` lines at the top-level or inside a flat
|
||||
* `[section]` table.
|
||||
*/
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
function workspaceRoot(): string {
|
||||
const ws = process.env.OPENHUMAN_WORKSPACE?.trim();
|
||||
if (ws && ws.length > 0) return ws;
|
||||
const home = process.env.HOME || '';
|
||||
return path.join(home, '.openhuman');
|
||||
}
|
||||
|
||||
export function configTomlPath(): string {
|
||||
return path.join(workspaceRoot(), 'config.toml');
|
||||
}
|
||||
|
||||
export function readConfigToml(): string {
|
||||
const file = configTomlPath();
|
||||
if (!fs.existsSync(file)) {
|
||||
throw new Error(`[config-toml] expected config.toml at ${file}`);
|
||||
}
|
||||
return fs.readFileSync(file, 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a top-level `key = value` line. Returns the raw RHS (quotes
|
||||
* included for strings) or null if the key isn't present.
|
||||
*/
|
||||
export function topLevelValue(contents: string, key: string): string | null {
|
||||
const lines = contents.split(/\r?\n/);
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed.startsWith('[')) {
|
||||
// Stop at the first section header — we only scan the top-level block.
|
||||
break;
|
||||
}
|
||||
const m = trimmed.match(/^([A-Za-z0-9_]+)\s*=\s*(.+)$/);
|
||||
if (m && m[1] === key) {
|
||||
return m[2].trim();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a `key = value` line inside `[section]`. Works for any flat
|
||||
* `[a.b]`-style section name.
|
||||
*/
|
||||
export function sectionValue(contents: string, section: string, key: string): string | null {
|
||||
const lines = contents.split(/\r?\n/);
|
||||
let inSection = false;
|
||||
const target = `[${section}]`;
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed.startsWith('[')) {
|
||||
inSection = trimmed === target;
|
||||
continue;
|
||||
}
|
||||
if (!inSection) continue;
|
||||
const m = trimmed.match(/^([A-Za-z0-9_]+)\s*=\s*(.+)$/);
|
||||
if (m && m[1] === key) {
|
||||
return m[2].trim();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function readBool(raw: string | null): boolean | null {
|
||||
if (raw === null) return null;
|
||||
if (raw === 'true') return true;
|
||||
if (raw === 'false') return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Convenience: read a string-valued key from a section, stripping `"`. */
|
||||
export function readSectionString(contents: string, section: string, key: string): string | null {
|
||||
const raw = sectionValue(contents, section, key);
|
||||
if (raw === null) return null;
|
||||
const m = raw.match(/^"((?:[^"\\]|\\.)*)"$/);
|
||||
return m ? m[1] : raw;
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* E2E: Onboarding — Simple (Cloud) vs Advanced (Custom) modes.
|
||||
*
|
||||
* Verifies:
|
||||
* - Phase A — Simple/Cloud path: fresh login → Welcome → Runtime choice
|
||||
* (Cloud) → /home. `onboarding_completed = true` lands in
|
||||
* `${OPENHUMAN_WORKSPACE}/config.toml` immediately.
|
||||
*
|
||||
* - Phase B — Advanced/Custom path (Default on every wizard step):
|
||||
* reset onboarding flag → Welcome → Runtime choice (Custom) →
|
||||
* Inference (Default) → Voice (Default) → OAuth (Default) → Finish.
|
||||
* Asserts all three custom wizard step containers render with the
|
||||
* expected `data-testid`s (i.e. *all settings are reachable*).
|
||||
*
|
||||
* - Phase C — Advanced/Custom path with Configure on the Voice step:
|
||||
* pick Configure, the embedded VoicePanel renders. Flip the STT
|
||||
* provider selector and assert `config.toml` updates
|
||||
* `local_ai.stt_provider` within a few seconds (i.e. advanced voice
|
||||
* provider settings apply immediately to persisted config).
|
||||
*
|
||||
* Auth is the bypass deep-link path. The mock API server runs on the same
|
||||
* port the dist bundle was built against (see `app/scripts/e2e-run-session.sh`).
|
||||
* No real network is touched.
|
||||
*/
|
||||
import { waitForAppReady, waitForAuthBootstrap } from '../helpers/app-helpers';
|
||||
import { readBool, readConfigToml, readSectionString, topLevelValue } from '../helpers/config-toml';
|
||||
import { callOpenhumanRpc } from '../helpers/core-rpc';
|
||||
import { triggerAuthDeepLinkBypass } from '../helpers/deep-link-helpers';
|
||||
import { waitForWebView, waitForWindowVisible } from '../helpers/element-helpers';
|
||||
import { resetApp } from '../helpers/reset-app';
|
||||
import { dismissBootCheckGateIfVisible } from '../helpers/shared-flows';
|
||||
import {
|
||||
resetMockBehavior,
|
||||
setMockBehavior,
|
||||
startMockServer,
|
||||
stopMockServer,
|
||||
} from '../mock-server';
|
||||
|
||||
const STEP_LOG_PREFIX = '[onboarding-modes]';
|
||||
|
||||
function stepLog(message: string): void {
|
||||
console.log(`${STEP_LOG_PREFIX} ${message}`);
|
||||
}
|
||||
|
||||
async function pause(ms: number): Promise<void> {
|
||||
await browser.pause(ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click a button by `data-testid`. Returns true if the click landed.
|
||||
*/
|
||||
async function clickTestId(testId: string, timeout = 10_000): Promise<boolean> {
|
||||
const deadline = Date.now() + timeout;
|
||||
while (Date.now() < deadline) {
|
||||
const status = await browser.execute(id => {
|
||||
const el = document.querySelector<HTMLElement>(`[data-testid="${id}"]`);
|
||||
if (!el) return 'missing';
|
||||
if ((el as HTMLButtonElement).disabled) return 'disabled';
|
||||
['mousedown', 'mouseup', 'click'].forEach(type => {
|
||||
el.dispatchEvent(
|
||||
new MouseEvent(type, { bubbles: true, cancelable: true, view: window, button: 0 })
|
||||
);
|
||||
});
|
||||
return 'clicked';
|
||||
}, testId);
|
||||
if (status === 'clicked') return true;
|
||||
await pause(400);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function testIdExists(testId: string, timeout = 10_000): Promise<boolean> {
|
||||
const deadline = Date.now() + timeout;
|
||||
while (Date.now() < deadline) {
|
||||
const found = await browser.execute(
|
||||
id => document.querySelector(`[data-testid="${id}"]`) !== null,
|
||||
testId
|
||||
);
|
||||
if (found) return true;
|
||||
await pause(400);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function currentHash(): Promise<string> {
|
||||
return browser.execute(() => window.location.hash || '');
|
||||
}
|
||||
|
||||
async function waitForHash(prefix: string, timeout = 15_000): Promise<boolean> {
|
||||
const deadline = Date.now() + timeout;
|
||||
while (Date.now() < deadline) {
|
||||
const hash = await currentHash();
|
||||
if (hash.startsWith(prefix)) return true;
|
||||
await pause(400);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function resetOnboardingFlagAndReload(): Promise<void> {
|
||||
stepLog('Resetting onboarding_completed=false via RPC');
|
||||
const res = await callOpenhumanRpc<{ completed: boolean }>(
|
||||
'openhuman.config_set_onboarding_completed',
|
||||
{ value: false }
|
||||
);
|
||||
if (!res.ok) {
|
||||
throw new Error(`config.set_onboarding_completed failed: ${JSON.stringify(res)}`);
|
||||
}
|
||||
await browser.execute(() => {
|
||||
try {
|
||||
window.localStorage.clear();
|
||||
window.sessionStorage.clear();
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
window.location.replace('#/');
|
||||
window.location.reload();
|
||||
});
|
||||
await waitForWindowVisible(25_000);
|
||||
await waitForWebView(15_000);
|
||||
await waitForAppReady(15_000);
|
||||
await dismissBootCheckGateIfVisible(8_000);
|
||||
await triggerAuthDeepLinkBypass('e2e-onboarding-modes');
|
||||
await waitForAuthBootstrap(15_000);
|
||||
await dismissBootCheckGateIfVisible(8_000);
|
||||
// Wait for the welcome step to mount before returning.
|
||||
const onWelcome = await waitForHash('#/onboarding', 15_000);
|
||||
if (!onWelcome) {
|
||||
stepLog(`hash after reset = ${await currentHash()}`);
|
||||
throw new Error('onboarding overlay did not re-mount after flag reset');
|
||||
}
|
||||
}
|
||||
|
||||
async function clickOnboardingNext(): Promise<void> {
|
||||
// The Welcome step button is the same shared `onboarding-next-button`.
|
||||
const ok = await clickTestId('onboarding-next-button', 10_000);
|
||||
if (!ok) {
|
||||
throw new Error('onboarding-next-button missing or stayed disabled');
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForHome(timeout = 20_000): Promise<boolean> {
|
||||
const deadline = Date.now() + timeout;
|
||||
while (Date.now() < deadline) {
|
||||
const hash = await currentHash();
|
||||
if (hash.startsWith('#/home')) return true;
|
||||
await pause(400);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
describe('Onboarding modes — Simple (Cloud) vs Advanced (Custom)', () => {
|
||||
before(async () => {
|
||||
await startMockServer();
|
||||
resetMockBehavior();
|
||||
setMockBehavior('composioConnections', '[]');
|
||||
// Reset state but skip the built-in onboarding walker — we walk it
|
||||
// ourselves to assert the per-step UI.
|
||||
await resetApp('e2e-onboarding-modes', { skipAuth: true });
|
||||
await triggerAuthDeepLinkBypass('e2e-onboarding-modes');
|
||||
await waitForAuthBootstrap(15_000);
|
||||
await dismissBootCheckGateIfVisible(8_000);
|
||||
await waitForHash('#/onboarding', 15_000);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
resetMockBehavior();
|
||||
await stopMockServer();
|
||||
});
|
||||
|
||||
// ───────────────────────────────────────────────────────────────────────
|
||||
// Phase A — Simple (Cloud)
|
||||
// ───────────────────────────────────────────────────────────────────────
|
||||
|
||||
it('simple/cloud path: welcome → runtime-choice → cloud → home', async () => {
|
||||
// Step 0 — Welcome screen.
|
||||
const welcomeVisible = await testIdExists('onboarding-next-button', 15_000);
|
||||
expect(welcomeVisible).toBe(true);
|
||||
await clickOnboardingNext();
|
||||
|
||||
// Step 1 — Runtime choice. The card is preselected to Cloud, so simply
|
||||
// clicking the next button continues the cloud path.
|
||||
const choiceVisible = await testIdExists('onboarding-runtime-choice-step', 10_000);
|
||||
expect(choiceVisible).toBe(true);
|
||||
const cloudCardVisible = await testIdExists('onboarding-runtime-choice-cloud', 5_000);
|
||||
expect(cloudCardVisible).toBe(true);
|
||||
// Explicitly click the Cloud card so the test is robust against the
|
||||
// default selection changing in the future.
|
||||
await clickTestId('onboarding-runtime-choice-cloud');
|
||||
await pause(500);
|
||||
await clickOnboardingNext();
|
||||
|
||||
const landed = await waitForHome(20_000);
|
||||
if (!landed) stepLog(`current hash after cloud finish: ${await currentHash()}`);
|
||||
expect(landed).toBe(true);
|
||||
});
|
||||
|
||||
it('simple/cloud path: config.toml reflects onboarding_completed=true', async () => {
|
||||
// The setOnboardingCompletedFlag RPC writes config.save() before the
|
||||
// navigate() in OnboardingLayout, but I/O can lag a tick. Poll briefly.
|
||||
let value: boolean | null = null;
|
||||
const deadline = Date.now() + 8_000;
|
||||
while (Date.now() < deadline) {
|
||||
value = readBool(topLevelValue(readConfigToml(), 'onboarding_completed'));
|
||||
if (value === true) break;
|
||||
await pause(400);
|
||||
}
|
||||
if (value !== true) {
|
||||
stepLog(`config.toml head:\n${readConfigToml().split('\n').slice(0, 30).join('\n')}`);
|
||||
}
|
||||
expect(value).toBe(true);
|
||||
});
|
||||
|
||||
// ───────────────────────────────────────────────────────────────────────
|
||||
// Phase B — Advanced (Custom), Default on every step
|
||||
// ───────────────────────────────────────────────────────────────────────
|
||||
|
||||
it('advanced/custom path: walks all wizard steps with Default choice', async () => {
|
||||
await resetOnboardingFlagAndReload();
|
||||
|
||||
// Step 0 — Welcome.
|
||||
await clickOnboardingNext();
|
||||
|
||||
// Step 1 — Runtime choice → Custom.
|
||||
expect(await testIdExists('onboarding-runtime-choice-step', 10_000)).toBe(true);
|
||||
expect(await clickTestId('onboarding-runtime-choice-custom')).toBe(true);
|
||||
await pause(500);
|
||||
await clickOnboardingNext();
|
||||
|
||||
// Step 2 — Custom Inference (Default).
|
||||
expect(await testIdExists('onboarding-custom-inference-step', 10_000)).toBe(true);
|
||||
expect(await clickTestId('onboarding-custom-inference-step-default')).toBe(true);
|
||||
await pause(400);
|
||||
await clickOnboardingNext();
|
||||
|
||||
// Step 3 — Custom Voice (Default).
|
||||
expect(await testIdExists('onboarding-custom-voice-step', 10_000)).toBe(true);
|
||||
expect(await clickTestId('onboarding-custom-voice-step-default')).toBe(true);
|
||||
await pause(400);
|
||||
await clickOnboardingNext();
|
||||
|
||||
// Step 4 — Custom OAuth (Default). This is the final step → Finish.
|
||||
expect(await testIdExists('onboarding-custom-oauth-step', 10_000)).toBe(true);
|
||||
expect(await clickTestId('onboarding-custom-oauth-step-default')).toBe(true);
|
||||
await pause(400);
|
||||
await clickOnboardingNext();
|
||||
|
||||
const landed = await waitForHome(20_000);
|
||||
if (!landed) stepLog(`current hash after custom finish: ${await currentHash()}`);
|
||||
expect(landed).toBe(true);
|
||||
|
||||
// Re-confirm the persisted flag is true after the second completion.
|
||||
let value: boolean | null = null;
|
||||
const deadline = Date.now() + 8_000;
|
||||
while (Date.now() < deadline) {
|
||||
value = readBool(topLevelValue(readConfigToml(), 'onboarding_completed'));
|
||||
if (value === true) break;
|
||||
await pause(400);
|
||||
}
|
||||
expect(value).toBe(true);
|
||||
});
|
||||
|
||||
// ───────────────────────────────────────────────────────────────────────
|
||||
// Phase C — Advanced (Custom), Configure on Voice mutates config.toml
|
||||
// ───────────────────────────────────────────────────────────────────────
|
||||
|
||||
it('advanced/custom path: Configure on Voice updates local_ai.stt_provider in config.toml', async () => {
|
||||
await resetOnboardingFlagAndReload();
|
||||
|
||||
// Welcome → Runtime choice (Custom) → Inference (Default).
|
||||
await clickOnboardingNext();
|
||||
expect(await testIdExists('onboarding-runtime-choice-step', 10_000)).toBe(true);
|
||||
expect(await clickTestId('onboarding-runtime-choice-custom')).toBe(true);
|
||||
await pause(500);
|
||||
await clickOnboardingNext();
|
||||
|
||||
expect(await testIdExists('onboarding-custom-inference-step', 10_000)).toBe(true);
|
||||
expect(await clickTestId('onboarding-custom-inference-step-default')).toBe(true);
|
||||
await pause(400);
|
||||
await clickOnboardingNext();
|
||||
|
||||
// Voice step → Configure → embedded VoicePanel renders. The auto-start
|
||||
// checkbox + Save button only render when local STT assets (Whisper) are
|
||||
// installed (`disabled = !sttReady` gates that block). In the CI
|
||||
// container we don't ship those assets, so we drive the always-visible
|
||||
// provider selectors instead — flipping the STT provider fires
|
||||
// `voice_set_providers`, which writes `config.local_ai.stt_provider`
|
||||
// to `config.toml` via `config.save()`.
|
||||
expect(await testIdExists('onboarding-custom-voice-step', 10_000)).toBe(true);
|
||||
expect(await clickTestId('onboarding-custom-voice-step-configure')).toBe(true);
|
||||
expect(await testIdExists('voice-providers-section', 10_000)).toBe(true);
|
||||
expect(await testIdExists('stt-provider-select', 10_000)).toBe(true);
|
||||
|
||||
const before = readSectionString(readConfigToml(), 'local_ai', 'stt_provider');
|
||||
const want = before === 'whisper' ? 'cloud' : 'whisper';
|
||||
stepLog(`stt_provider before=${before ?? '<unset>'} → want=${want}`);
|
||||
|
||||
// Drive the same onChange path the user would. The `<option disabled>`
|
||||
// attribute blocks click/keyboard selection in the UI, but doesn't stop a
|
||||
// synthetic change event from React's perspective once we set `.value`.
|
||||
const dispatched = await browser.execute(next => {
|
||||
const el = document.querySelector<HTMLSelectElement>('[data-testid="stt-provider-select"]');
|
||||
if (!el) return false;
|
||||
const setter = Object.getOwnPropertyDescriptor(
|
||||
window.HTMLSelectElement.prototype,
|
||||
'value'
|
||||
)?.set;
|
||||
if (setter) {
|
||||
setter.call(el, next);
|
||||
} else {
|
||||
el.value = next;
|
||||
}
|
||||
el.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
return true;
|
||||
}, want);
|
||||
expect(dispatched).toBe(true);
|
||||
|
||||
// Poll config.toml for the new value.
|
||||
let onDisk: string | null = null;
|
||||
const deadline = Date.now() + 10_000;
|
||||
while (Date.now() < deadline) {
|
||||
onDisk = readSectionString(readConfigToml(), 'local_ai', 'stt_provider');
|
||||
if (onDisk === want) break;
|
||||
await pause(500);
|
||||
}
|
||||
if (onDisk !== want) {
|
||||
stepLog(
|
||||
`local_ai.stt_provider expected=${want} got=${onDisk ?? '<unset>'}; config.toml:\n` +
|
||||
readConfigToml()
|
||||
);
|
||||
}
|
||||
expect(onDisk).toBe(want);
|
||||
|
||||
// Continue out of the wizard so the spec leaves the app on /home.
|
||||
await clickOnboardingNext();
|
||||
expect(await testIdExists('onboarding-custom-oauth-step', 10_000)).toBe(true);
|
||||
expect(await clickTestId('onboarding-custom-oauth-step-default')).toBe(true);
|
||||
await pause(400);
|
||||
await clickOnboardingNext();
|
||||
|
||||
expect(await waitForHome(20_000)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -65,6 +65,11 @@ services:
|
||||
# each platform's tree separate.
|
||||
- e2e-node-modules:/workspace/node_modules
|
||||
- e2e-app-node-modules:/workspace/app/node_modules
|
||||
# CEF binary download cache — cef-dll-sys writes to ~/Library/Caches/tauri-cef
|
||||
# inside the container. Without a named volume this is lost between runs and
|
||||
# every new container re-downloads the ~400 MB CEF archive (which also fails
|
||||
# when the container has no outbound DNS / TLS access to the CDN).
|
||||
- e2e-cef-cache:/root/Library/Caches/tauri-cef
|
||||
environment:
|
||||
- DISPLAY=:99
|
||||
- CI=true
|
||||
@@ -86,3 +91,4 @@ volumes:
|
||||
e2e-node-modules:
|
||||
e2e-app-node-modules:
|
||||
e2e-pnpm-project-store:
|
||||
e2e-cef-cache:
|
||||
|
||||
Reference in New Issue
Block a user