mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
test fixes
This commit is contained in:
parent
ed8c5b70cf
commit
ae4c8f5f1c
4 changed files with 47 additions and 13 deletions
|
|
@ -22,7 +22,7 @@ enum Theme {
|
||||||
static let terminalForeground = Color(light: Color(hex: "24292E"), dark: Color(hex: "B3B1AD"))
|
static let terminalForeground = Color(light: Color(hex: "24292E"), dark: Color(hex: "B3B1AD"))
|
||||||
|
|
||||||
// Accent colors (same for both modes)
|
// Accent colors (same for both modes)
|
||||||
static let primaryAccent = Color(hex: "00FF88") // Green accent matching web
|
static let primaryAccent = Color(light: Color(hex: "22C55E"), dark: Color(hex: "00FF88")) // Darker green for light mode
|
||||||
static let secondaryAccent = Color(hex: "59C2FF")
|
static let secondaryAccent = Color(hex: "59C2FF")
|
||||||
static let successAccent = Color(hex: "AAD94C")
|
static let successAccent = Color(hex: "AAD94C")
|
||||||
static let warningAccent = Color(hex: "FFB454")
|
static let warningAccent = Color(hex: "FFB454")
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ struct SessionCardView: View {
|
||||||
VStack(alignment: .leading, spacing: Theme.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Theme.Spacing.medium) {
|
||||||
// Header with session ID/name and kill button
|
// Header with session ID/name and kill button
|
||||||
HStack {
|
HStack {
|
||||||
Text(session.name)
|
Text(session.displayName)
|
||||||
.font(Theme.Typography.terminalSystem(size: 14))
|
.font(Theme.Typography.terminalSystem(size: 14))
|
||||||
.fontWeight(.medium)
|
.fontWeight(.medium)
|
||||||
.foregroundColor(Theme.Colors.primaryAccent)
|
.foregroundColor(Theme.Colors.primaryAccent)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ struct SessionListView: View {
|
||||||
|
|
||||||
return sessions.filter { session in
|
return sessions.filter { session in
|
||||||
// Search in session name
|
// Search in session name
|
||||||
if session.name.localizedCaseInsensitiveContains(searchText) {
|
if let name = session.name, name.localizedCaseInsensitiveContains(searchText) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// Search in command
|
// Search in command
|
||||||
|
|
@ -275,6 +275,11 @@ struct SessionListView: View {
|
||||||
Task {
|
Task {
|
||||||
await viewModel.killAllSessions()
|
await viewModel.killAllSessions()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onCleanupAll: {
|
||||||
|
Task {
|
||||||
|
await viewModel.cleanupAllExited()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
|
|
@ -290,13 +295,6 @@ struct SessionListView: View {
|
||||||
GridItem(.flexible(), spacing: Theme.Spacing.medium),
|
GridItem(.flexible(), spacing: Theme.Spacing.medium),
|
||||||
GridItem(.flexible(), spacing: Theme.Spacing.medium)
|
GridItem(.flexible(), spacing: Theme.Spacing.medium)
|
||||||
], spacing: Theme.Spacing.medium) {
|
], spacing: Theme.Spacing.medium) {
|
||||||
if showExitedSessions && filteredSessions.contains(where: { !$0.isRunning }) {
|
|
||||||
CleanupAllButton {
|
|
||||||
Task {
|
|
||||||
await viewModel.cleanupAllExited()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ForEach(filteredSessions) { session in
|
ForEach(filteredSessions) { session in
|
||||||
SessionCardView(session: session) {
|
SessionCardView(session: session) {
|
||||||
|
|
@ -383,11 +381,11 @@ struct ErrorBanner: View {
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: isOffline ? "wifi.slash" : "exclamationmark.triangle")
|
Image(systemName: isOffline ? "wifi.slash" : "exclamationmark.triangle")
|
||||||
.foregroundColor(.white)
|
.foregroundColor(Theme.Colors.terminalBackground)
|
||||||
|
|
||||||
Text(message)
|
Text(message)
|
||||||
.font(Theme.Typography.terminalSystem(size: 14))
|
.font(Theme.Typography.terminalSystem(size: 14))
|
||||||
.foregroundColor(.white)
|
.foregroundColor(Theme.Colors.terminalBackground)
|
||||||
.lineLimit(2)
|
.lineLimit(2)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
@ -493,6 +491,7 @@ struct SessionHeaderView: View {
|
||||||
let sessions: [Session]
|
let sessions: [Session]
|
||||||
@Binding var showExitedSessions: Bool
|
@Binding var showExitedSessions: Bool
|
||||||
let onKillAll: () -> Void
|
let onKillAll: () -> Void
|
||||||
|
let onCleanupAll: () -> Void
|
||||||
|
|
||||||
private var runningCount: Int { sessions.count(where: { $0.isRunning }) }
|
private var runningCount: Int { sessions.count(where: { $0.isRunning }) }
|
||||||
private var exitedCount: Int { sessions.count(where: { !$0.isRunning }) }
|
private var exitedCount: Int { sessions.count(where: { !$0.isRunning }) }
|
||||||
|
|
@ -524,6 +523,10 @@ struct SessionHeaderView: View {
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
if showExitedSessions && sessions.contains(where: { !$0.isRunning }) {
|
||||||
|
CleanupAllHeaderButton(onCleanup: onCleanupAll)
|
||||||
|
}
|
||||||
|
|
||||||
if sessions.contains(where: \.isRunning) {
|
if sessions.contains(where: \.isRunning) {
|
||||||
KillAllButton(onKillAll: onKillAll)
|
KillAllButton(onKillAll: onKillAll)
|
||||||
}
|
}
|
||||||
|
|
@ -600,7 +603,7 @@ struct KillAllButton: View {
|
||||||
.fontWeight(.medium)
|
.fontWeight(.medium)
|
||||||
}
|
}
|
||||||
.font(Theme.Typography.terminalSystem(size: 14))
|
.font(Theme.Typography.terminalSystem(size: 14))
|
||||||
.foregroundColor(.white)
|
.foregroundColor(Theme.Colors.terminalBackground)
|
||||||
.padding(.horizontal, Theme.Spacing.medium)
|
.padding(.horizontal, Theme.Spacing.medium)
|
||||||
.padding(.vertical, Theme.Spacing.small)
|
.padding(.vertical, Theme.Spacing.small)
|
||||||
.background(
|
.background(
|
||||||
|
|
@ -645,6 +648,36 @@ struct CleanupAllButton: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CleanupAllHeaderButton: View {
|
||||||
|
let onCleanup: () -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button(action: {
|
||||||
|
HapticFeedback.impact(.medium)
|
||||||
|
onCleanup()
|
||||||
|
}, label: {
|
||||||
|
HStack(spacing: 6) {
|
||||||
|
Image(systemName: "trash")
|
||||||
|
.font(.system(size: 14))
|
||||||
|
Text("Clean Up All Exited")
|
||||||
|
.font(Theme.Typography.terminalSystem(size: 14))
|
||||||
|
}
|
||||||
|
.foregroundColor(Theme.Colors.warningAccent)
|
||||||
|
.padding(.horizontal, Theme.Spacing.medium)
|
||||||
|
.padding(.vertical, Theme.Spacing.small)
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)
|
||||||
|
.fill(Theme.Colors.warningAccent.opacity(0.1))
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)
|
||||||
|
.stroke(Theme.Colors.warningAccent.opacity(0.2), lineWidth: 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.buttonStyle(PlainButtonStyle())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper for cast file URL to make it Identifiable
|
/// Wrapper for cast file URL to make it Identifiable
|
||||||
struct CastFileItem: Identifiable {
|
struct CastFileItem: Identifiable {
|
||||||
let id = UUID()
|
let id = UUID()
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,7 @@ struct APIClientTests {
|
||||||
// MARK: - Error Handling Tests
|
// MARK: - Error Handling Tests
|
||||||
|
|
||||||
@Test("Handles 404 error correctly")
|
@Test("Handles 404 error correctly")
|
||||||
|
@MainActor
|
||||||
func handle404Error() async throws {
|
func handle404Error() async throws {
|
||||||
// Arrange
|
// Arrange
|
||||||
MockURLProtocol.requestHandler = { request in
|
MockURLProtocol.requestHandler = { request in
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue