Set up E2E test framework for Android using WebdriverIO, Appium, and UiAutomator2. Add testID props to key components (AuthButton, BaseButton, ChatBubble, CustomTextInput, ProposedEventCard) and apply testIDs to login screen, chat screen, tab bar, and settings. Include initial tests for app launch detection and login flow validation. Update CLAUDE.md with E2E docs.
105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
import { useState } from "react";
|
|
import { View, Text, Pressable } from "react-native";
|
|
import { Link, router } from "expo-router";
|
|
import BaseBackground from "../components/BaseBackground";
|
|
import AuthButton from "../components/AuthButton";
|
|
import CustomTextInput from "../components/CustomTextInput";
|
|
import { AuthService } from "../services";
|
|
import { CaldavConfigService } from "../services/CaldavConfigService";
|
|
import { preloadAppData } from "../components/AuthGuard";
|
|
import { useThemeStore } from "../stores/ThemeStore";
|
|
|
|
const LoginScreen = () => {
|
|
const { theme } = useThemeStore();
|
|
const [identifier, setIdentifier] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const handleLogin = async () => {
|
|
setError(null);
|
|
|
|
if (!identifier || !password) {
|
|
setError("Bitte alle Felder ausfüllen");
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
try {
|
|
await AuthService.login({ identifier, password });
|
|
await preloadAppData();
|
|
try {
|
|
await CaldavConfigService.sync();
|
|
} catch {
|
|
// No CalDAV config or sync failed — not critical
|
|
}
|
|
router.replace("/(tabs)/chat");
|
|
} catch {
|
|
setError("Anmeldung fehlgeschlagen. Überprüfe deine Zugangsdaten.");
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<BaseBackground>
|
|
<View className="flex-1 justify-center items-center p-8">
|
|
<Text
|
|
testID="login-title"
|
|
className="text-3xl font-bold mb-8"
|
|
style={{ color: theme.textPrimary }}
|
|
>
|
|
Anmelden
|
|
</Text>
|
|
|
|
{error && (
|
|
<Text
|
|
testID="login-error-text"
|
|
className="mb-4 text-center"
|
|
style={{ color: theme.rejectButton }}
|
|
>
|
|
{error}
|
|
</Text>
|
|
)}
|
|
|
|
<CustomTextInput
|
|
testID="login-identifier-input"
|
|
placeholder="E-Mail oder Benutzername"
|
|
placeholderTextColor={theme.textMuted}
|
|
text={identifier}
|
|
onValueChange={setIdentifier}
|
|
autoCapitalize="none"
|
|
className="w-full rounded-lg p-4 mb-4"
|
|
/>
|
|
|
|
<CustomTextInput
|
|
testID="login-password-input"
|
|
placeholder="Passwort"
|
|
placeholderTextColor={theme.textMuted}
|
|
text={password}
|
|
onValueChange={setPassword}
|
|
secureTextEntry
|
|
className="w-full rounded-lg p-4 mb-6"
|
|
/>
|
|
|
|
<AuthButton
|
|
testID="login-button"
|
|
title="Anmelden"
|
|
onPress={handleLogin}
|
|
isLoading={isLoading}
|
|
/>
|
|
|
|
<Link href="/register" asChild>
|
|
<Pressable>
|
|
<Text style={{ color: theme.chatBot }}>
|
|
Noch kein Konto? Registrieren
|
|
</Text>
|
|
</Pressable>
|
|
</Link>
|
|
</View>
|
|
</BaseBackground>
|
|
);
|
|
};
|
|
|
|
export default LoginScreen;
|