Skip to content
This repository was archived by the owner on Oct 20, 2025. It is now read-only.

Commit 74c4ad5

Browse files
authored
Bulk Action password confirmation + Bugfix for #266 (#272)
1 parent 53de495 commit 74c4ad5

20 files changed

+303
-112
lines changed

app/app/Http/Controllers/FilepondController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ public function showValidation()
3232

3333
public function showExisting()
3434
{
35-
$user = User::first();
35+
/** @var User */
36+
$user = User::firstOrFail();
3637

3738
return view('form.components.filepondExisting', [
3839
'avatar' => ExistingFile::fromMediaLibrary($user->getFirstMedia('avatar')),
@@ -43,7 +44,7 @@ public function showExisting()
4344

4445
public function storeExisting(Request $request)
4546
{
46-
$user = User::first();
47+
$user = User::firstOrFail();
4748

4849
if ($request->query('form') === 'avatar') {
4950
HandleSpladeFileUploads::syncMediaLibrary($request, $user, 'avatar', 'avatar');

app/app/Tables/Projects.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ public function configure(SpladeTable $table)
4545
confirmButton: 'Sure!',
4646
cancelButton: 'Nope!'
4747
)
48+
->bulkAction(
49+
label: 'Touch timestamp confirm password',
50+
each: fn (Project $project) => $project->touch(),
51+
after: fn () => Toast::info('Timestamps updated!'),
52+
confirm: true,
53+
requirePassword: true
54+
)
4855
->export()
4956
->export('CSV export', 'projects.csv', Excel::CSV)
5057
->defaultSort('name')

app/database/factories/OrganizationFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class OrganizationFactory extends Factory
1717
public function definition()
1818
{
1919
return [
20-
'name' => str_replace(['-', ','], [' ', ''], $this->faker->company),
20+
'name' => str_replace(['-', ',', ' and '], [' ', '', ' '], $this->faker->company),
2121
];
2222
}
2323
}

app/database/factories/ProjectFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ProjectFactory extends Factory
1717
public function definition()
1818
{
1919
return [
20-
'name' => $this->faker->company(),
20+
'name' => str_replace(['-', ',', ' and '], [' ', '', ' '], $this->faker->company),
2121

2222
'organization_id' => OrganizationFactory::new()->has(AddressFactory::new()),
2323
];

app/tests/Browser.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Tests;
44

55
use Facebook\WebDriver\Remote\LocalFileDetector;
6+
use Illuminate\Support\Str;
67
use Laravel\Dusk\Browser as BaseBrowser;
78
use PHPUnit\Framework\Assert as PHPUnit;
89

@@ -41,12 +42,26 @@ public function assertMetaByName($name, $content)
4142

4243
public function attachToFilepond($path)
4344
{
44-
$element = $this->resolver->firstOrFail([
45-
'input[type=file].filepond--browser',
46-
]);
45+
$element = $this->resolver->firstOrFail(['input[type=file].filepond--browser']);
4746

4847
$element->setFileDetector(new LocalFileDetector)->sendKeys($path);
4948

50-
return $this;
49+
$filename = pathinfo($path, PATHINFO_BASENAME);
50+
51+
if ($element->getAttribute('data-server') === 'false') {
52+
return $this->waitForText($filename)->pause(250);
53+
}
54+
55+
$assistants = $this->resolver->all('.filepond--assistant');
56+
57+
return $this->waitUsing(10, 50, function () use ($assistants, $filename) {
58+
foreach ($assistants as $assistant) {
59+
if (Str::contains($assistant->getText(), ["{$filename} Upload complete"])) {
60+
return true;
61+
}
62+
}
63+
64+
return false;
65+
})->pause(250);
5166
}
5267
}

app/tests/Browser/Form/FilepondExistingTest.php

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function it_can_keep_the_existing_single_media_upload()
2929
$browser->visit('form/components/filepondExisting')
3030
->within('@avatar', function (Browser $browser) {
3131
$browser->waitForText('1.jpeg')
32-
->pause(500)
32+
->pause(250)
3333
->press('Submit');
3434
})
3535
->waitForText('The photos have been saved');
@@ -51,11 +51,12 @@ public function it_can_replace_the_existing_single_media_upload()
5151
$browser->visit('form/components/filepondExisting')
5252
->within('@avatar', function (Browser $browser) {
5353
$browser->waitForText('1.jpeg')
54-
->pause(500)
54+
->pause(250)
5555
->press('.filepond--action-remove-item')
56+
->waitUntilMissingText('1.jpeg')
57+
->pause(250)
5658
->waitForText('Drag and drop your files')
5759
->attachToFilepond(__DIR__ . '/../small.jpeg')
58-
->waitForText('Upload complete', 10)
5960
->press('Submit');
6061
})
6162
->waitForText('The photos have been saved');
@@ -77,8 +78,10 @@ public function it_can_delete_the_existing_single_media_upload()
7778
$browser->visit('form/components/filepondExisting')
7879
->within('@avatar', function (Browser $browser) {
7980
$browser->waitForText('1.jpeg')
80-
->pause(500)
81+
->pause(250)
8182
->press('.filepond--action-remove-item')
83+
->waitUntilMissingText('1.jpeg')
84+
->pause(250)
8285
->waitForText('Drag and drop your files')
8386
->press('Submit');
8487
})
@@ -99,7 +102,7 @@ public function it_can_keep_the_existing_multiple_media_uploads()
99102
$browser->visit('form/components/filepondExisting')
100103
->within('@photos', function (Browser $browser) {
101104
$browser->waitForText('1.jpeg')
102-
->pause(500)
105+
->pause(250)
103106
->press('Submit');
104107
})
105108
->waitForText('The photos have been saved');
@@ -125,9 +128,8 @@ public function it_can_add_a_file_to_the_existing_multiple_media_uploads()
125128
->within('@photos', function (Browser $browser) {
126129
$browser->waitForText('1.jpeg')
127130
->waitForText('Drag and drop your files')
128-
->pause(500)
131+
->pause(250)
129132
->attachToFilepond(__DIR__ . '/../small.jpeg')
130-
->waitForText('Upload complete', 10)
131133
->press('Submit');
132134
})
133135
->waitForText('The photos have been saved');
@@ -153,9 +155,10 @@ public function it_can_delete_an_existing_multiple_media_upload()
153155
$browser->visit('form/components/filepondExisting')
154156
->within('@photos', function (Browser $browser) {
155157
$browser->waitForText('1.jpeg')
156-
->pause(500)
158+
->pause(250)
157159
->press('.filepond--action-remove-item')
158-
->pause(500)
160+
->waitUntilMissingText('1.jpeg')
161+
->pause(250)
159162
->press('Submit');
160163
})
161164
->waitForText('The photos have been saved');
@@ -179,7 +182,7 @@ public function it_can_reorder_multiple_uploads()
179182
$formattedFilepondSelector = $browser->resolver->format('@photos-file-input');
180183

181184
$browser->waitForText('1.jpeg')
182-
->pause(500)
185+
->pause(250)
183186
->script("return document.querySelector('{$formattedFilepondSelector}').dispatchEvent(new CustomEvent('moveFile', { detail: [0, 2] }));");
184187

185188
$browser->pause(500)->press('Submit');
@@ -207,14 +210,22 @@ public function it_can_add_and_delete_and_reorder_in_one_request()
207210

208211
$browser->waitForText('1.jpeg')
209212
->waitForText('Drag and drop your files')
210-
->pause(500)
213+
->pause(250)
214+
->screenshot('Filpond-1-AddAndReorderMedia-BeforeRemoving')
211215
->press('.filepond--action-remove-item')
212-
->attachToFilepond(__DIR__ . '/../small.jpeg')
213-
->waitForText('Upload complete', 10);
216+
->waitUntilMissingText('1.jpeg')
217+
->pause(250)
218+
->screenshot('Filpond-2-AddAndReorderMedia-BeforeAttaching')
219+
->attachToFilepond(__DIR__ . '/../small.jpeg');
214220

215-
$browser->script("return document.querySelector('{$formattedFilepondSelector}').dispatchEvent(new CustomEvent('moveFile', { detail: [0, 2] }));");
221+
$browser
222+
->screenshot('Filpond-3-AddAndReorderMedia-BeforeReordering')
223+
->script("return document.querySelector('{$formattedFilepondSelector}').dispatchEvent(new CustomEvent('moveFile', { detail: [0, 2] }));");
216224

217-
$browser->pause(250)->press('Submit');
225+
$browser
226+
->pause(500)
227+
->screenshot('Filpond-4-AddAndReorderMedia-BeforeSubmitting')
228+
->press('Submit');
218229
})
219230
->waitForText('The photos have been saved');
220231
});
@@ -223,8 +234,8 @@ public function it_can_add_and_delete_and_reorder_in_one_request()
223234

224235
$this->assertCount(2, $newMedia);
225236

226-
$this->assertEquals('2.jpeg', $newMedia[0]->file_name);
227-
$this->assertEquals('small.jpeg', $newMedia[1]->file_name);
237+
$this->assertEquals('small.jpeg', $newMedia[0]->file_name);
238+
$this->assertEquals('2.jpeg', $newMedia[1]->file_name);
228239
}
229240

230241
/** @test */
@@ -239,13 +250,14 @@ public function it_can_also_reorder_with_direct_uploads()
239250

240251
$browser->waitForText('dummy1.txt')
241252
->waitForText('Drag and drop your files')
242-
->pause(500)
253+
->pause(250)
243254
->screenshot('Filepond-1-BeforeRemovingFirstDummy')
244255
->press('.filepond--action-remove-item')
256+
->waitUntilMissingText('dummy1.txt')
257+
->pause(250)
245258
->screenshot('Filepond-2-BeforeAddingThirdDummy')
246259
->attachToFilepond(__DIR__ . '/../dummy3.txt')
247-
->waitForText('dummy3.txt')
248-
->pause(500)
260+
->pause(250)
249261
->screenshot('Filepond-3-BeforeOrderingDummies');
250262

251263
$browser->script("return document.querySelector('{$formattedFilepondSelector}').dispatchEvent(new CustomEvent('moveFile', { detail: [0, 2] }));");
@@ -261,8 +273,8 @@ public function it_can_also_reorder_with_direct_uploads()
261273

262274
$this->assertCount(2, $newMedia);
263275

264-
$this->assertEquals('dummy2.txt', $newMedia[0]->file_name);
265-
$this->assertEquals('dummy3.txt', $newMedia[1]->file_name);
276+
$this->assertEquals('dummy3.txt', $newMedia[0]->file_name);
277+
$this->assertEquals('dummy2.txt', $newMedia[1]->file_name);
266278
}
267279

268280
/** @test */

app/tests/Browser/Form/FilepondTest.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ public function it_can_upload_a_file_using_a_regular_single_request()
3434
$browser->waitForText('Drag and drop your files')->pause(500);
3535

3636
$browser->attachToFilepond(__DIR__ . '/../small.jpeg')
37-
->waitForText('small.jpeg')
3837
->press('Submit');
3938
})
4039
->waitForRoute('navigation.one');
@@ -54,8 +53,6 @@ public function it_can_upload_multiple_files_using_a_regular_single_request()
5453
$browser
5554
->attachToFilepond(__DIR__ . '/../small.jpeg')
5655
->attachToFilepond(__DIR__ . '/../small.png')
57-
->waitForText('small.jpeg')
58-
->waitForText('small.png')
5956
->press('Submit');
6057
})
6158
->waitForRoute('navigation.one');
@@ -74,7 +71,6 @@ public function it_can_upload_a_temporary_file_using_controller_middleware()
7471
$browser->waitForText('Drag and drop your files')->pause(500);
7572

7673
$browser->attachToFilepond(__DIR__ . '/../small.jpeg')
77-
->waitForText('Upload complete', 10)
7874
->press('Submit');
7975
})
8076
->waitForRoute('navigation.one');
@@ -94,8 +90,6 @@ public function it_can_upload_multiple_temporary_files()
9490
$browser
9591
->attachToFilepond(__DIR__ . '/../small.jpeg')
9692
->attachToFilepond(__DIR__ . '/../small.png')
97-
->waitForText('Uploading')
98-
->waitUntilMissingText('Uploading')
9993
->press('Submit');
10094
})
10195
->waitForRoute('navigation.one');
@@ -114,7 +108,6 @@ public function it_can_upload_a_temporary_file_using_route_middleware()
114108
$browser->waitForText('Drag and drop your files')->pause(500);
115109

116110
$browser->attachToFilepond(__DIR__ . '/../small.jpeg')
117-
->waitForText('Upload complete', 10)
118111
->press('Submit');
119112
})
120113
->waitForRoute('navigation.one');
@@ -132,7 +125,6 @@ public function it_can_upload_a_temporary_file_using_a_form_request()
132125
$browser->waitForText('Drag and drop your files')->pause(500);
133126

134127
$browser->attachToFilepond(__DIR__ . '/../small.jpeg')
135-
->waitForText('Upload complete', 10)
136128
->press('Submit');
137129
})
138130
->waitForRoute('navigation.one');
@@ -150,7 +142,6 @@ public function it_can_upload_a_temporary_file_using_a_form_request_that_has_a_v
150142
$browser->waitForText('Drag and drop your files')->pause(500);
151143

152144
$browser->attachToFilepond(__DIR__ . '/../small.jpeg')
153-
->waitForText('Upload complete', 10)
154145
->press('Submit');
155146
})
156147
->waitForRoute('navigation.one');
@@ -168,7 +159,6 @@ public function it_can_upload_a_temporary_file_using_a_form_request_and_it_clear
168159
$browser->waitForText('Drag and drop your files')->pause(500);
169160

170161
$browser->attachToFilepond(__DIR__ . '/../small.jpeg')
171-
->waitForText('Upload complete', 10)
172162
->type('title', Str::random())
173163
->press('Submit');
174164
})

app/tests/Browser/ModalTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public function it_can_show_a_slideover()
6565
$browser->visit('/modal/base')
6666
->resize(1024, 768)
6767
->waitForText('ModalComponent')
68+
->pause(250)
6869
->click('@slideover')
6970
->waitForText('ModalComponentSlideover')
7071
->pause(500)
@@ -88,6 +89,7 @@ public function it_can_show_a_slideover_on_the_left_side()
8889
$browser->visit('/modal/base')
8990
->resize(1024, 768)
9091
->waitForText('ModalComponent')
92+
->pause(250)
9193
->click('@slideover-left')
9294
->waitForText('ModalComponentSlideover')
9395
->pause(500)

app/tests/Browser/RehydrateTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ public function it_can_rehydrate_by_polling()
1818
$dynamicContent = $browser->getTextIn('@dynamic');
1919

2020
$browser->pause(1500)
21-
->assertSeeIn('@static', $staticContent);
21+
->assertSeeIn('@static', $staticContent)
22+
->pause(250);
2223

2324
$newDynamicContent = $browser->getTextIn('@dynamic');
2425
$this->assertNotEquals($dynamicContent, $newDynamicContent);
2526

2627
$browser->pause(1500)
27-
->assertSeeIn('@static', $staticContent);
28+
->assertSeeIn('@static', $staticContent)
29+
->pause(250);
2830

2931
$newerDynamicContent = $browser->getTextIn('@dynamic');
3032
$this->assertNotEquals($dynamicContent, $newerDynamicContent);

0 commit comments

Comments
 (0)