[#647] Added 'DropzoneTrait' for multi-file drag-and-drop step.#652
Conversation
|
Warning Review limit reached
More reviews will be available in 36 minutes and 37 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
WalkthroughThis PR introduces ChangesDropzoneTrait: Multi-file drag-and-drop simulation
Sequence DiagramsequenceDiagram
participant Scenario as Test Scenario
participant Trait as DropzoneTrait
participant Resolver as dropzoneResolvePath
participant Mink as Mink Session
participant Browser as Browser
participant Fixture as Dropzone Fixture
Scenario->>Trait: dropzoneDropFiles(selector, paths)
Trait->>Trait: Validate target selector exists
loop For each fixture path
Trait->>Resolver: Resolve path against files_path
Resolver-->>Trait: Absolute path (or exception)
Trait->>Mink: Create hidden file input
Mink->>Mink: Attach fixture file
end
Trait->>Browser: Build DataTransfer with all files
Trait->>Browser: Dispatch DragEvent('drop')
Browser->>Fixture: drop event received
Fixture->>Fixture: Increment event counter
Fixture->>Fixture: Render dropped file names
Trait->>Mink: Remove temporary file inputs
Trait-->>Scenario: Complete
🎯 3 (Moderate) | ⏱️ ~22 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/DropzoneTrait.php`:
- Around line 156-165: The code uses realpath($files_path) cast to string and
proceeds even if realpath returned FALSE, letting $base be empty and bypassing
the containment check; update the logic in DropzoneTrait around the
$base/$full_path/$resolved checks to first validate that realpath($files_path)
!== FALSE and throw a clear RuntimeException if it fails, then compute $base =
rtrim(realpath($files_path), DIRECTORY_SEPARATOR), build $full_path and use
realpath($full_path) to compute $resolved, and finally keep the existing
containment guard using str_starts_with($resolved, $base . DIRECTORY_SEPARATOR)
to ensure fixture files cannot escape files_path.
🪄 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: Repository UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 80fa656a-1a83-406f-860a-a57531eb1a64
📒 Files selected for processing (6)
README.mdSTEPS.mdsrc/DropzoneTrait.phptests/behat/bootstrap/FeatureContext.phptests/behat/features/dropzone.featuretests/behat/fixtures/dropzone.html
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #652 +/- ##
==========================================
- Coverage 96.66% 96.59% -0.08%
==========================================
Files 45 46 +1
Lines 3481 3523 +42
==========================================
+ Hits 3365 3403 +38
- Misses 116 120 +4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Closes #647
Summary
Adds
DropzoneTraitto the generic namespace, providing twoWhensteps that simulate a real multi-file drag-and-drop gesture by dispatching a single nativedropevent whosedataTransfer.filescontains all requested files simultaneously. Unlike Mink'sattachFile, which writes files to a hidden<input type="file">one at a time (sequential uploads), this trait reproduces the concurrent-upload code path that real users trigger - exposing race conditions in dedup maps, status-indicator clobbering, queue deadlocks, and server-side handlers that only manifest under the multi-file path. Fixture paths are resolved against the Minkfiles_pathparameter and validated to prevent path-traversal escapes.Changes
New trait -
src/DropzoneTrait.phpWhen I drop the file :path on the :selector dropzone- single-file convenience step (delegates to the multi-file step with a one-row TableNode)When I drop the following files on the :selector dropzone:- drops N files in a single nativedropevent; injects temporary off-screen<input type="file">elements to satisfy browser security, collects theFileobjects into aDataTransfer, dispatchesDragEvent('drop', ...)on the resolved CSS target, then removes the holder inputsdropzoneResolvePath()- resolves each path againstfiles_path, rejects missing files and paths that escape the configured base directory viarealpathcomparisonNew tests -
tests/behat/features/dropzone.feature@javascript @phpserverscenarios: single-file drop, multi-file drop (verifies a singledropevent fires), drop on a non-default selector, two consecutive drops in one scenario@trait:DropzoneTraitscenarios: missing target element, missing single fixture file, missing file in a multi-file listNew fixture -
tests/behat/fixtures/dropzone.html.dropzoneprimary target and a#secondary-zonesecondary target; JavaScript listeners append dropped filenames to separate output lists and increment a shared event counter, letting scenarios assert both which files landed where and how manydropevents firedRegistration -
tests/behat/bootstrap/FeatureContext.phpDropzoneTraitalongside the existing generic traitsDocs -
STEPS.md,README.mdahoy update-docs;DropzoneTraitentry added to the trait table in both filesBefore / After
DropzoneTrait Implementation
Overview
Added a new Behat trait that simulates real multi-file drag-and-drop gestures by firing a single native
dropevent with all files in aDataTransfer, enabling tests of concurrent-upload code paths that Mink's sequentialattachFilecannot reproduce.Step Definitions
Two new
Whensteps (compliant with CONTRIBUTING.md):When I drop the file :path on the :selector dropzone— single-file convenience wrapperWhen I drop the following files on the :selector dropzone:— multi-file step accepting a table with one fixture path per rowPlaceholders, phrasing (
the following), action-verbWhen I drop, tuple format, and method naming (trait-prefixed) conform to the repository's step rules. No CONTRIBUTING.md violations found.Implementation Details
<input type="file">holders, uses Mink's attachFileToField to populate each holder, aggregates holder.files into a singleDataTransfer, dispatches one browser-nativeDragEvent('drop', { bubbles: true, cancelable: true, dataTransfer: dt })on the resolved CSS target, and removes holders.files_path, canonicalizesfiles_pathwithrealpath()and validates it is a directory, constructs the full path, checks file existence, canonicalizes the fixture path and rejects paths outside the canonicalfiles_pathdirectory (prevents path traversal). Throws clear RuntimeExceptions for empty paths, missing/invalidfiles_path, missing fixtures, and out-of-bounds fixtures.Tests & Fixtures
@traitscenarios (missing target, missing single fixture, missing file in multi-file list).event.dataTransfer.filesand append filenames.Documentation & Misc
Scope & Acceptance