Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/mobile-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ jobs:
working-directory: mobile
run: |
export PATH="$HOME/.maestro/bin:$PATH"
maestro test .maestro/flows/ --format junit --output maestro-report.xml
# Exclude chat tests (require backend) - run those locally
maestro test .maestro/flows/ --exclude-tags=chat --format junit --output maestro-report.xml
env:
MAESTRO_DRIVER_STARTUP_TIMEOUT: 120000

Expand Down
66 changes: 66 additions & 0 deletions mobile/.maestro/flows/03-chat-claude-code.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
appId: com.gricha.perry
name: Chat - Claude Code
tags:
- chat
- claude-code
---
- launchApp:
clearState: true

# Configure server connection
- tapOn:
id: "hostname-input"
- inputText: "localhost"
- tapOn:
id: "port-input"
- eraseText
- inputText: "7391"
- tapOn:
id: "connect-button"

# Wait for workspace list to load
- extendedWaitUntil:
visible: "test"
timeout: 30000

# Tap on test workspace
- tapOn: "test"

# Wait for workspace detail screen
- extendedWaitUntil:
visible:
id: "new-chat-button"
timeout: 10000

# Start new Claude Code chat
- tapOn:
id: "new-chat-button"

# Select Claude Code from picker
- tapOn:
id: "new-chat-claude-code"

# Wait for chat screen to load and connect
- extendedWaitUntil:
visible:
id: "chat-input"
timeout: 15000

# Type and send a simple message
- tapOn:
id: "chat-input"
- inputText: "Say hello"
- tapOn:
id: "send-button"

# Verify thinking dots appear (streaming started)
- extendedWaitUntil:
visible:
id: "thinking-dots"
timeout: 10000

# Wait for response to complete (thinking dots disappear, assistant message appears)
- extendedWaitUntil:
visible:
id: "assistant-message"
timeout: 120000
66 changes: 66 additions & 0 deletions mobile/.maestro/flows/04-chat-opencode.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
appId: com.gricha.perry
name: Chat - OpenCode
tags:
- chat
- opencode
---
- launchApp:
clearState: true

# Configure server connection
- tapOn:
id: "hostname-input"
- inputText: "localhost"
- tapOn:
id: "port-input"
- eraseText
- inputText: "7391"
- tapOn:
id: "connect-button"

# Wait for workspace list to load
- extendedWaitUntil:
visible: "test"
timeout: 30000

# Tap on test workspace
- tapOn: "test"

# Wait for workspace detail screen
- extendedWaitUntil:
visible:
id: "new-chat-button"
timeout: 10000

# Start new OpenCode chat
- tapOn:
id: "new-chat-button"

# Select OpenCode from picker
- tapOn:
id: "new-chat-opencode"

# Wait for chat screen to load and connect
- extendedWaitUntil:
visible:
id: "chat-input"
timeout: 15000

# Type and send a simple message
- tapOn:
id: "chat-input"
- inputText: "Say hello"
- tapOn:
id: "send-button"

# Verify thinking dots appear (streaming started)
- extendedWaitUntil:
visible:
id: "thinking-dots"
timeout: 10000

# Wait for response to complete (thinking dots disappear, assistant message appears)
- extendedWaitUntil:
visible:
id: "assistant-message"
timeout: 120000
10 changes: 6 additions & 4 deletions mobile/src/screens/SessionChatScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ function MessageBubble({ message }: { message: ChatMessage }) {

if (message.role === 'user') {
return (
<View style={styles.userBubble}>
<View style={styles.userBubble} testID="user-message">
<Text style={styles.messageText}>{trimmedContent}</Text>
</View>
)
Expand All @@ -192,7 +192,7 @@ function MessageBubble({ message }: { message: ChatMessage }) {
}

return (
<View style={styles.assistantBubble}>
<View style={styles.assistantBubble} testID="assistant-message">
<Text style={styles.messageText}>{trimmedContent}</Text>
</View>
)
Expand Down Expand Up @@ -230,7 +230,7 @@ function ThinkingDots() {
}, [dot1, dot2, dot3])

return (
<View style={styles.thinkingDots}>
<View style={styles.thinkingDots} testID="thinking-dots">
<Animated.View style={[styles.dot, { opacity: dot1 }]} />
<Animated.View style={[styles.dot, { opacity: dot2 }]} />
<Animated.View style={[styles.dot, { opacity: dot3 }]} />
Expand Down Expand Up @@ -684,16 +684,18 @@ export function SessionChatScreen({ route, navigation }: any) {
multiline
maxLength={4000}
editable={connected && !isStreaming}
testID="chat-input"
/>
{isStreaming ? (
<TouchableOpacity style={styles.stopBtn} onPress={interrupt}>
<TouchableOpacity style={styles.stopBtn} onPress={interrupt} testID="stop-button">
<Text style={styles.stopBtnText}>Stop</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
style={[styles.sendBtn, (!connected || !input.trim()) && styles.sendBtnDisabled]}
onPress={sendMessage}
disabled={!connected || !input.trim()}
testID="send-button"
>
<Text style={styles.sendBtnText}>Send</Text>
</TouchableOpacity>
Expand Down
1 change: 1 addition & 0 deletions mobile/src/screens/WorkspaceDetailScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export function WorkspaceDetailScreen({ route, navigation }: any) {
setShowNewChatPicker(false)
navigation.navigate('SessionChat', { workspaceName: name, isNew: true, agentType: type })
}}
testID={`new-chat-${type}`}
>
<View style={[styles.agentBadgeLarge, { backgroundColor: type === 'claude-code' ? '#8b5cf6' : type === 'opencode' ? '#22c55e' : '#f59e0b' }]}>
<Text style={styles.agentBadgeLargeText}>{type === 'claude-code' ? 'CC' : type === 'opencode' ? 'OC' : 'CX'}</Text>
Expand Down