[#647] Added 'DropzoneTrait' for multi-file drag-and-drop step.#652
[#647] Added 'DropzoneTrait' for multi-file drag-and-drop step.#652AlexSkrypnyk wants to merge 3 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
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 docstrings
🧪 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 Sentry. 🚀 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