as-app/e2e/helpers/ui.js
2026-01-12 18:27:57 +01:00

76 lines
1.6 KiB
JavaScript

const DEFAULT_TIMEOUT_MS = 20_000;
async function launchAppFresh() {
await device.launchApp({
newInstance: true,
permissions: {
notifications: "YES",
location: "never",
microphone: "never",
},
});
}
async function reloadApp() {
await device.reloadReactNative();
}
function byId(id) {
return element(by.id(id));
}
async function waitForVisibleById(id, timeoutMs = DEFAULT_TIMEOUT_MS) {
await waitFor(byId(id)).toBeVisible().withTimeout(timeoutMs);
}
async function expectVisibleById(id) {
await expect(byId(id)).toBeVisible();
}
async function scrollUntilVisibleById(id, opts = {}) {
const { timeoutMs = DEFAULT_TIMEOUT_MS, stepPx = 240 } = opts;
// Fast-path: already visible.
try {
await waitForVisibleById(id, 500);
return;
} catch (_e) {
// Continue to scroll
}
const target = byId(id);
// Detox needs an explicit scrollable element to drive scrolling.
// This app uses RN ScrollView, which maps to different native class names.
const scrollViews = [
element(by.type("android.widget.ScrollView")),
element(by.type("RCTScrollView")),
];
const errors = [];
for (const scrollView of scrollViews) {
try {
await waitFor(target)
.toBeVisible()
.whileElement(scrollView)
.scroll(stepPx, "down");
return;
} catch (e) {
errors.push(e);
}
}
// Fall back to a direct wait to get a good assertion error.
await waitForVisibleById(id, timeoutMs);
}
module.exports = {
DEFAULT_TIMEOUT_MS,
byId,
expectVisibleById,
launchAppFresh,
reloadApp,
scrollUntilVisibleById,
waitForVisibleById,
};