Skip to content

Commit d5ebcea

Browse files
authored
Add app installation phase tests (#2644)
* Add app installation phase tests
1 parent 2ac86cf commit d5ebcea

File tree

4 files changed

+540
-110
lines changed

4 files changed

+540
-110
lines changed
Lines changed: 99 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import React, { useState, useEffect, useCallback } from "react";
22
import { useWizard } from "../../../../contexts/WizardModeContext";
3-
import AppInstallationStatus from "./AppInstallationStatus";
3+
import { useSettings } from "../../../../contexts/SettingsContext";
4+
import { useAuth } from "../../../../contexts/AuthContext";
5+
import { useQuery } from "@tanstack/react-query";
6+
import { XCircle, CheckCircle, Loader2 } from "lucide-react";
47
import { NextButtonConfig } from "../types";
5-
import { State } from "../../../../types";
8+
import { State, AppInstallStatus } from "../../../../types";
9+
import ErrorMessage from "../shared/ErrorMessage";
610

711
interface AppInstallationPhaseProps {
812
onNext: () => void;
@@ -11,13 +15,38 @@ interface AppInstallationPhaseProps {
1115
}
1216

1317
const AppInstallationPhase: React.FC<AppInstallationPhaseProps> = ({ onNext, setNextButtonConfig, onStateChange }) => {
14-
const { text } = useWizard();
18+
const { text, target } = useWizard();
19+
const { settings } = useSettings();
20+
const { token } = useAuth();
21+
const [isPolling, setIsPolling] = useState(true);
1522
const [installationComplete, setInstallationComplete] = useState(false);
1623
const [installationSuccess, setInstallationSuccess] = useState(false);
24+
const themeColor = settings.themeColor;
25+
26+
// Query to poll app installation status
27+
const { data: appInstallStatus, error: appStatusError } = useQuery<AppInstallStatus, Error>({
28+
queryKey: ["appInstallationStatus"],
29+
queryFn: async () => {
30+
const response = await fetch(`/api/${target}/install/app/status`, {
31+
headers: {
32+
"Content-Type": "application/json",
33+
Authorization: `Bearer ${token}`,
34+
},
35+
});
36+
if (!response.ok) {
37+
const errorData = await response.json().catch(() => ({}));
38+
throw new Error(errorData.message || "Failed to get app installation status");
39+
}
40+
return response.json() as Promise<AppInstallStatus>;
41+
},
42+
enabled: isPolling,
43+
refetchInterval: 2000,
44+
});
1745

1846
const handleInstallationComplete = useCallback((success: boolean) => {
1947
setInstallationComplete(true);
2048
setInstallationSuccess(success);
49+
setIsPolling(false);
2150
onStateChange(success ? 'Succeeded' : 'Failed');
2251
}, []);
2352

@@ -26,6 +55,15 @@ const AppInstallationPhase: React.FC<AppInstallationPhaseProps> = ({ onNext, set
2655
onStateChange('Running');
2756
}, []);
2857

58+
// Handle status changes
59+
useEffect(() => {
60+
if (appInstallStatus?.status?.state === "Succeeded") {
61+
handleInstallationComplete(true);
62+
} else if (appInstallStatus?.status?.state === "Failed") {
63+
handleInstallationComplete(false);
64+
}
65+
}, [appInstallStatus, handleInstallationComplete]);
66+
2967
// Update next button configuration
3068
useEffect(() => {
3169
setNextButtonConfig({
@@ -34,16 +72,72 @@ const AppInstallationPhase: React.FC<AppInstallationPhaseProps> = ({ onNext, set
3472
});
3573
}, [installationComplete, installationSuccess]);
3674

75+
const renderInstallationStatus = () => {
76+
// Loading state
77+
if (isPolling) {
78+
return (
79+
<div className="flex flex-col items-center justify-center py-12" data-testid="app-installation-loading">
80+
<Loader2 className="w-8 h-8 animate-spin mb-4" style={{ color: themeColor }} />
81+
<p className="text-lg font-medium text-gray-900">Installing application...</p>
82+
<p className="text-sm text-gray-500 mt-2" data-testid="app-installation-loading-description">
83+
{appInstallStatus?.status?.description || "Please wait while we install your application."}
84+
</p>
85+
</div>
86+
);
87+
}
88+
89+
// Success state
90+
if (appInstallStatus?.status?.state === "Succeeded") {
91+
return (
92+
<div className="flex flex-col items-center justify-center py-12" data-testid="app-installation-success">
93+
<div
94+
className="w-12 h-12 rounded-full flex items-center justify-center mb-4"
95+
style={{ backgroundColor: `${themeColor}1A` }}
96+
>
97+
<CheckCircle className="w-6 h-6" style={{ color: themeColor }} />
98+
</div>
99+
<p className="text-lg font-medium text-gray-900">Application installed successfully!</p>
100+
<p className="text-sm text-gray-500 mt-2">Your application is now ready to use.</p>
101+
</div>
102+
);
103+
}
104+
105+
// Error state
106+
if (appInstallStatus?.status?.state === "Failed") {
107+
return (
108+
<div className="flex flex-col items-center justify-center py-12" data-testid="app-installation-error">
109+
<div className="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mb-4">
110+
<XCircle className="w-6 h-6 text-red-600" />
111+
</div>
112+
<p className="text-lg font-medium text-gray-900">Application installation failed</p>
113+
<p className="text-sm text-gray-500 mt-2" data-testid="app-installation-error-message">
114+
{appInstallStatus?.status?.description || "An error occurred during installation."}
115+
</p>
116+
</div>
117+
);
118+
}
119+
120+
// Default loading state
121+
return (
122+
<div className="flex flex-col items-center justify-center py-12">
123+
<Loader2 className="w-8 h-8 animate-spin mb-4" style={{ color: themeColor }} />
124+
<p className="text-lg font-medium text-gray-900">Preparing installation...</p>
125+
</div>
126+
);
127+
};
128+
37129
return (
38130
<div className="space-y-6">
39131
<div className="mb-6">
40132
<h2 className="text-2xl font-bold text-gray-900">{text.appInstallationTitle}</h2>
41133
<p className="text-gray-600 mt-1">{text.appInstallationDescription}</p>
42134
</div>
43135

44-
<AppInstallationStatus onComplete={handleInstallationComplete} />
136+
{renderInstallationStatus()}
137+
138+
{appStatusError && <ErrorMessage error={appStatusError?.message} />}
45139
</div>
46140
);
47141
};
48142

49-
export default AppInstallationPhase;
143+
export default AppInstallationPhase;

web/src/components/wizard/installation/phases/AppInstallationStatus.tsx

Lines changed: 0 additions & 104 deletions
This file was deleted.

0 commit comments

Comments
 (0)