feat(10-01): update App.test.tsx and add step descriptions to all 4 steps

- Update App.test.tsx: add 'shows intro section on initial render' test
- Update App.test.tsx: fix 'renders BackendSelectionStep' — click Get Started first
- Add fireEvent import for click simulation
- BackendSelectionStep: add description below h2 (text-sm text-on-surface-variant)
- RemoteConfigStep: add description below h2
- DeploymentStep: add description below h2
- ReviewStep: add h2 heading + description paragraph (step was missing h2)
- All descriptions use text-sm text-on-surface-variant mt-1 mb-4
This commit is contained in:
2026-04-01 12:54:16 +02:00
parent c1d1633816
commit 4b837b19a0
5 changed files with 40 additions and 1 deletions
+16 -1
View File
@@ -1,7 +1,7 @@
// @vitest-environment jsdom
// Covers WIZD-02: App renders the correct step component for currentStep 0, 1, 2
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import { render, screen, fireEvent } from '@testing-library/react';
import React from 'react';
import App from './App';
import { WizardProvider } from './store/context';
@@ -52,8 +52,23 @@ function renderAtStep(targetStep: number) {
}
describe('App — step routing', () => {
it('shows intro section on initial render', () => {
render(<App />);
// Intro copy is present
const introHeading = screen.getByText(/Go from zero to a deployable rclone setup in minutes/);
expect(introHeading).toBeDefined();
// StepIndicator is NOT in the DOM
const stepNav = screen.queryByRole('navigation', { name: /Wizard steps/i });
expect(stepNav).toBeNull();
});
it('renders BackendSelectionStep when currentStep is 0', () => {
render(<App />);
// Intro shows first — assert Get Started button is visible
const getStarted = screen.getByRole('button', { name: /Get Started/i });
expect(getStarted).toBeDefined();
// Click Get Started to reveal the wizard
fireEvent.click(getStarted);
// BackendSelectionStep renders "Step 1: Select Backend"
const heading = screen.getByText(/Select Backend/);
expect(heading).toBeDefined();
@@ -8,6 +8,7 @@ import { BACKEND_REGISTRY } from '../../schemas/registry';
import { BackendCard } from '../ui/BackendCard';
import { MD3_BTN_FILLED } from '../../styles/md3-buttons';
import { TextFieldMD3 } from '../ui/TextFieldMD3';
import { RemoteNamePreview } from '../ui/RemoteNamePreview';
const remoteNameSchema = z.object({
name: z
@@ -29,6 +30,7 @@ export function BackendSelectionStep() {
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm<RemoteNameFormValues>({
resolver: zodResolver(remoteNameSchema),
@@ -37,6 +39,8 @@ export function BackendSelectionStep() {
defaultValues: { name: state.remote.name },
});
const remoteName = watch('name');
function onValidSubmit(values: RemoteNameFormValues) {
const backend = pendingBackend.current;
if (!backend) return;
@@ -54,6 +58,10 @@ export function BackendSelectionStep() {
return (
<div>
<h2>Step 1: Select Backend</h2>
<p className="text-sm text-on-surface-variant mt-1 mb-4">
Name your remote and pick the cloud storage provider you want to connect to.
Your choice determines which credentials are required in the next step.
</p>
<form onSubmit={handleSubmit(onValidSubmit)}>
<TextFieldMD3
id="remote-name"
@@ -61,7 +69,9 @@ export function BackendSelectionStep() {
registration={register('name')}
error={errors.name}
required
helpText="This becomes the section header [name] in your rclone.conf. Example: azure-prod, backup-s3. Letters, numbers, dashes, underscores only."
/>
<RemoteNamePreview value={remoteName} />
<div data-testid="backend-cards">
{Object.entries(BACKEND_REGISTRY).map(([type, entry]) => (
<BackendCard
+4
View File
@@ -22,6 +22,10 @@ export function DeploymentStep() {
return (
<div>
<h2>Step 3: Deployment Options</h2>
<p className="text-sm text-on-surface-variant mt-1 mb-4">
Choose how the generated config gets deployed to the target machine and which deployment
script formats to produce.
</p>
{/* Include rclone installation toggle */}
<div>
@@ -56,6 +56,10 @@ export function RemoteConfigStep() {
return (
<div>
<h2>Step 2: Configure {backendLabel[backendType]}</h2>
<p className="text-sm text-on-surface-variant mt-1 mb-4">
Enter the credentials for your selected backend. These values are written directly into the
generated rclone.conf and are never sent to any server.
</p>
<form onSubmit={handleSubmit(onNext)}>
{backendType === 'azureblob' ? (
<>
+6
View File
@@ -72,6 +72,12 @@ export function ReviewStep() {
return (
<div>
<h2>Step 4: Review &amp; Download</h2>
<p className="text-sm text-on-surface-variant mt-1 mb-4">
Review your generated files and download them. Acknowledge the security notice before
copying or downloading credentials.
</p>
{/* SECU-02: client-side only notice */}
<p className="text-sm text-success bg-success/10 rounded p-3 mb-6">
No data is sent to any server. All file generation happens in your browser.