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:
+16
-1
@@ -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
|
||||
|
||||
@@ -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' ? (
|
||||
<>
|
||||
|
||||
@@ -72,6 +72,12 @@ export function ReviewStep() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Step 4: Review & 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.
|
||||
|
||||
Reference in New Issue
Block a user