Skip to content

release/v0.1.7-phase7-target-format-step#103

Merged
menvil merged 26 commits into
mainfrom
release/v0.1.7-phase7-target-format-step
May 31, 2026
Merged

release/v0.1.7-phase7-target-format-step#103
menvil merged 26 commits into
mainfrom
release/v0.1.7-phase7-target-format-step

Conversation

@menvil

@menvil menvil commented May 31, 2026

Copy link
Copy Markdown
Owner

Release v0.1.7 — Phase 7: Target Format Step

Promotes Phase 7 (CONV-084 → CONV-095) from develop to main.

What's in this release

Phase 7 turns the Phase 6 format-step placeholder into a real target-format selection step:

  • CONV-084 Format step guard — cannot open the format step without an uploaded file.
  • CONV-085 Load available target formats from ConverterRegistry for the current FileRecord.
  • CONV-086 TargetFormatCardViewModel (fromConverter / fromTarget).
  • CONV-087 Render registry-driven, clickable target-format cards.
  • CONV-088 "Recommended" badge on the recommended target.
  • CONV-089 Graceful empty state for source formats with no targets.
  • CONV-090 / CONV-091 Test + implement target selection (supported → settings placeholder; unsupported → readable error). No ConversionJob is created.
  • CONV-092 Reset selected target on file remove/replace.
  • CONV-093 Back navigation (settings → format → upload summary) preserving the file.
  • CONV-094 Loading spinner + styled error state on selection.
  • CONV-095 End-to-end smoke tests.

Out of scope (per plan)

Dynamic settings form, options schema rendering/validation, conversion jobs/execution, downloads, billing — all deferred to Phase 8+.

Quality gates

  • composer test — 201 passed (529 assertions)
  • composer lint — passed
  • npm run build — passed
  • php artisan migrate:fresh --seed — clean

Tag (after merge)

v0.1.7-phase7-target-format-step

🤖 Generated with Claude Code


Summary by cubic

Adds a real target-format selection step to the dashboard converter so users can pick supported outputs, see a recommended option, and navigate without losing their file. Also wires an init guard to auto-return to upload if state is stale.

  • New Features
    • Load available targets from ConverterRegistry for the current FileRecord.
    • Show clickable cards via TargetFormatCardViewModel with labels, descriptions, and a "Recommended" badge.
    • Init step guard via wire:init; missing file routes to upload; upload summary with Replace/Remove and "Choose format".
    • Target selection: supported → settings placeholder; unsupported → clear error; no ConversionJob.
    • Back navigation between upload summary, format, and settings; reset selection on file replace/remove.
    • UX polish and tests: loading spinner, styled error/empty states; added feature/smoke/navigation tests and a TargetFormatCardViewModel unit test; scoped FileRecord assertions to the user.

Written for commit 52ac719. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

Release Notes

  • New Features

    • Added format selection step with visual card grid displaying available conversion targets
    • Introduced file summary view after upload with Replace and Remove options
    • Added recommended format badges to highlight suggested conversions
    • Implemented back navigation between upload, format, and settings steps
    • Added error messaging for unsupported format conversions
    • Added loading indicator during format selection
  • Tests

    • Comprehensive feature tests for navigation flows and format selection
    • Added smoke tests for upload-to-conversion workflows

menvil and others added 25 commits May 31, 2026 17:40
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rget-formats

CONV-085: Load available target formats
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…mat-card-view-model

CONV-086: Create target format card view model
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…mat-cards

CONV-087: Render target format cards
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…arget-marker

CONV-088: Add recommended target marker
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ource-format-empty-state

CONV-089: Add unsupported source format empty state
Add Livewire tests for supported/unsupported target selection.
Verified red against the absent selectTargetFormat() handler, then
marked skip pending CONV-091 to keep the suite green for merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t-selection

CONV-090: Test target format selection
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…format-selection

CONV-091: Implement target format selection
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…target-format-in-component-state

CONV-092: Persist selected target format in component state
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ion-from-format-step

CONV-093: Add back navigation from format step
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t-step-loading-and-error-states

CONV-094: Add target format step loading and error states
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t-step-smoke-tests

CONV-095: Add target format step smoke tests
@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR introduces target-format selection to the DashboardConverter component. It adds state tracking for selected format and errors, registry-driven step navigation with format validation, view-model factories to render format cards, UI sections for selection with error/loading/empty states, and comprehensive feature and smoke tests covering selection logic, navigation, and edge cases.

Changes

Target Format Selection & Navigation

Layer / File(s) Summary
TargetFormatCardViewModel value object and factories
app/ViewModels/TargetFormatCardViewModel.php, tests/Unit/ViewModels/TargetFormatCardViewModelTest.php
Final readonly view model with constructor-promoted properties (targetFormat, label, description, recommended) and factory methods to map from Converter and ConverterTarget DTOs. Unit tests verify both factory paths.
DashboardConverter state properties and reset logic
app/Livewire/Dashboard/DashboardConverter.php
Introduces selectedTargetFormat and targetFormatError public properties, and extends resetCurrentUpload() to clear format state via new resetTargetSelection() helper.
DashboardConverter step navigation and target selection
app/Livewire/Dashboard/DashboardConverter.php
Implements goToFormatStep(), ensureValidStep(), selectTargetFormat() with converter registry lookup and error handling, and back methods that reset selection state. Adds computed properties getAvailableTargetsProperty() and getTargetFormatCardsProperty() that query the registry and map results to view models.
Dashboard converter Blade template format selection UI
resources/views/livewire/dashboard/dashboard-converter.blade.php
Upload step conditionally shows current-file summary with "Choose format" button or dropzone. Format step adds "← Back" button and target-format cards grid with error banner, loading spinner, empty-state message, and optional "Recommended" badges. Settings step adds "← Back" button and updates header to reference selected format.
Feature tests for target format selection and state transitions
tests/Feature/Livewire/DashboardConverterTargetFormatTest.php
Tests supported and unsupported format selection, file removal/replacement clearing state, error display and clearing, and loading UI markup for the selection action.
Feature tests for back navigation and step management
tests/Feature/Livewire/DashboardConverterNavigationTest.php
Tests back-button behavior across steps, file record persistence, selected-format clearing, and navigation with missing current files.
Feature tests for step validation and format availability
tests/Feature/Livewire/DashboardConverterTest.php
Tests step-access rules, available target lookup by file extension, card rendering and click wiring, view-model surface, recommended badge presence, and empty-state handling for source formats with no targets.
Smoke tests for upload-to-format workflows
tests/Feature/Livewire/DashboardConverterTargetFormatSmokeTest.php
End-to-end tests covering PNG upload to format selection with step transitions, non-persistence of extra records, and round-trip navigation preserving file data.
Update upload test expectations for format UI
tests/Feature/Livewire/DashboardConverterUploadTest.php
Aligns existing upload test assertions to expect "Convert PNG to" format-selection text instead of placeholder.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • menvil/FileConverter#59: The PR's DashboardConverter format-selection flow depends on the converter domain core and ConverterRegistry introduced in #59 to populate and validate target format options.
  • menvil/FileConverter#90: Both PRs modify the same Livewire DashboardConverter step flow and its upload reset/replace behavior plus the dashboard-converter Blade template, so this PR builds on the phase-06 implementation.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is a release branch name that describes the phase and feature being released, but it does not clearly summarize the main change in user-friendly terms. Consider using a more descriptive title like 'Implement target format selection step (Phase 7)' to clearly communicate the primary feature being added.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/v0.1.7-phase7-target-format-step

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the release Triggers AI code review (CodeRabbit, Cubic) label May 31, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
tests/Unit/ViewModels/TargetFormatCardViewModelTest.php (1)

8-10: ⚡ Quick win

Add an explicit non-null assertion before fromConverter()

Guard $converter with an assertion so failures clearly indicate missing registry fixture instead of a downstream type error.

Suggested patch
 it('creates target format card data from converter metadata', function () {
     $converter = app(ConverterRegistry::class)->find('png', 'jpg');
+    expect($converter)->not->toBeNull();
 
     $card = TargetFormatCardViewModel::fromConverter($converter);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Unit/ViewModels/TargetFormatCardViewModelTest.php` around lines 8 - 10,
The test calls ConverterRegistry::find('png', 'jpg') and passes the result into
TargetFormatCardViewModel::fromConverter without asserting it is non-null; add
an explicit non-null assertion (e.g. PHPUnit's assertNotNull or an explicit
check) on $converter immediately after the find call so a missing registry
fixture fails with a clear assertion message rather than causing a downstream
type error inside TargetFormatCardViewModel::fromConverter.
app/Livewire/Dashboard/DashboardConverter.php (1)

80-86: ensureValidStep() isn’t wired into the Livewire runtime

app/Livewire/Dashboard/DashboardConverter.php (lines 80-86) defines ensureValidStep(), but it’s never called by the component (no lifecycle hook calls it) or by resources/views/livewire/dashboard/dashboard-converter.blade.php (no wire:init/wire:* call). The only invocation is in tests/Feature/Livewire/DashboardConverterTest.php via ->call('ensureValidStep'), so the format-step guard is effectively dead unless you explicitly hook it in (or remove it if redundant with the existing $step + $this->currentFile checks/step transition methods).

public function ensureValidStep(): void
{
    if ($this->step === 'format' && $this->currentFile === null) {
        $this->currentFileId = null;
        $this->step = 'upload';
    }
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/Livewire/Dashboard/DashboardConverter.php` around lines 80 - 86,
ensureValidStep() is never invoked at runtime so its guard never runs; either
remove it if redundant or call it from the component lifecycle (e.g., invoke
$this->ensureValidStep() inside the Livewire component's mount() and
updated($name, $value) methods) and/or add a wire:init="ensureValidStep" to
resources/views/livewire/dashboard/dashboard-converter.blade.php so the check
runs on initialization; update DashboardConverter::mount and/or
DashboardConverter::updated to call ensureValidStep (or add the wire:init hook
in the blade) to ensure the format-step guard actually executes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/Feature/Livewire/DashboardConverterTargetFormatSmokeTest.php`:
- Line 45: The assertion in DashboardConverterTargetFormatSmokeTest uses
FileRecord::query()->count() which counts globally; change it to scope to the
test user by filtering the FileRecord query with the test user's identifier
(e.g., use the test user variable in the test such as $user or $this->user and
add a where('user_id', $user->id) or equivalent relation before calling count())
so the expect compares only records belonging to the test user.
- Line 67: The test's FileRecord existence assertion lacks user scoping; update
the expectation to include the test user's id so it mirrors the component's
scoping (see getCurrentFileProperty). Locate the assertion using
FileRecord::query()->where('original_name', 'roundtrip.png')->exists() and add a
where('user_id', $user->id) (or the test's user reference, e.g. $this->user or
$userFromSetup) before ->exists() so the check only looks for files owned by the
test user.

---

Nitpick comments:
In `@app/Livewire/Dashboard/DashboardConverter.php`:
- Around line 80-86: ensureValidStep() is never invoked at runtime so its guard
never runs; either remove it if redundant or call it from the component
lifecycle (e.g., invoke $this->ensureValidStep() inside the Livewire component's
mount() and updated($name, $value) methods) and/or add a
wire:init="ensureValidStep" to
resources/views/livewire/dashboard/dashboard-converter.blade.php so the check
runs on initialization; update DashboardConverter::mount and/or
DashboardConverter::updated to call ensureValidStep (or add the wire:init hook
in the blade) to ensure the format-step guard actually executes.

In `@tests/Unit/ViewModels/TargetFormatCardViewModelTest.php`:
- Around line 8-10: The test calls ConverterRegistry::find('png', 'jpg') and
passes the result into TargetFormatCardViewModel::fromConverter without
asserting it is non-null; add an explicit non-null assertion (e.g. PHPUnit's
assertNotNull or an explicit check) on $converter immediately after the find
call so a missing registry fixture fails with a clear assertion message rather
than causing a downstream type error inside
TargetFormatCardViewModel::fromConverter.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 750bd439-4583-478b-a123-7508f2def0bd

📥 Commits

Reviewing files that changed from the base of the PR and between 2e99a70 and 27c70c6.

📒 Files selected for processing (9)
  • app/Livewire/Dashboard/DashboardConverter.php
  • app/ViewModels/TargetFormatCardViewModel.php
  • resources/views/livewire/dashboard/dashboard-converter.blade.php
  • tests/Feature/Livewire/DashboardConverterNavigationTest.php
  • tests/Feature/Livewire/DashboardConverterTargetFormatSmokeTest.php
  • tests/Feature/Livewire/DashboardConverterTargetFormatTest.php
  • tests/Feature/Livewire/DashboardConverterTest.php
  • tests/Feature/Livewire/DashboardConverterUploadTest.php
  • tests/Unit/ViewModels/TargetFormatCardViewModelTest.php

Comment thread tests/Feature/Livewire/DashboardConverterTargetFormatSmokeTest.php Outdated
Comment thread tests/Feature/Livewire/DashboardConverterTargetFormatSmokeTest.php Outdated
… fixture, wire ensureValidStep

- Smoke test: scope FileRecord count/exists assertions to the test user
- TargetFormatCardViewModel test: assert converter is non-null before fromConverter
- Run ensureValidStep guard on component init via wire:init

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@menvil menvil merged commit 1df82de into main May 31, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release Triggers AI code review (CodeRabbit, Cubic)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant