diff --git a/tests/Feature/CopyButtonComponentTest.php b/tests/Feature/CopyButtonComponentTest.php
index a9996a062e..7177da08e8 100644
--- a/tests/Feature/CopyButtonComponentTest.php
+++ b/tests/Feature/CopyButtonComponentTest.php
@@ -1,16 +1,42 @@
blade('');
$html->assertSee('Copy backup path')
->assertSee('backup\/path.sql', false)
- ->assertSee('window.copyToClipboard', false)
- ->assertSee('size-6', false);
+ ->assertSee('x-data="copyButton"', false)
+ ->assertDontSee('window.copyToClipboard', false);
});
-it('uses the reusable copy button for database backup paths', function () {
- $view = file_get_contents(resource_path('views/livewire/project/database/backup-executions.blade.php'));
+it('disables the button when no backend value is available', function () {
+ $html = $this->blade('');
- expect($view)->toContain('');
+ $html->assertSee('disabled', false);
+});
+
+it('evaluates a resolve expression at click time instead of a static value', function () {
+ $html = $this->blade('');
+
+ $html->assertSee('await ($wire.copyValue())', false)
+ ->assertDontSee('disabled', false);
+});
+
+it('is the single clipboard implementation shared by its call sites', function () {
+ expect(file_get_contents(resource_path('js/copy-button.js')))
+ ->toContain("window.Alpine.data('copyButton'");
+
+ expect(file_get_contents(resource_path('js/app.js')))
+ ->toContain('initializeCopyButtonComponent');
+
+ $modalConfirmation = file_get_contents(resource_path('views/components/modal-confirmation.blade.php'));
+ $backupExecutions = file_get_contents(resource_path('views/livewire/project/database/backup-executions.blade.php'));
+
+ expect($modalConfirmation)
+ ->toContain('not->toContain('navigator.clipboard');
+
+ expect($backupExecutions)
+ ->toContain('not->toContain('navigator.clipboard');
});
diff --git a/tests/Feature/ResourceDetailsVisibilityTest.php b/tests/Feature/ResourceDetailsVisibilityTest.php
index 29f611cbaa..4cac570f7e 100644
--- a/tests/Feature/ResourceDetailsVisibilityTest.php
+++ b/tests/Feature/ResourceDetailsVisibilityTest.php
@@ -27,7 +27,7 @@ it('keeps the resource details helper text visible below the modal header', func
])->render();
expect($html)
- ->toContain('Identifiers for this resource. Read-only')
+ ->toContain('readonly')
->toContain('pt-1')
->not->toContain('-mt-4');
});
@@ -38,20 +38,18 @@ it('renders copy fields as visible readonly controls with an accessible copy act
expect($html)
->toContain('label class="flex gap-1 items-center mb-1 text-sm font-medium text-black dark:text-white"')
->toContain('readonly')
- ->toContain('window.copyToClipboard')
+ ->toContain('x-data="copyButton"')
->toContain('input-with-copy-button')
- ->toContain('copy-button')
->toContain('aria-label="Copy to clipboard"')
- ->toContain('title="Copy to clipboard"')
- ->toContain('class="size-[18px] text-green-500"');
+ ->toContain('title="Copy to clipboard"');
});
-it('uses the shared copy field for newly issued api tokens', function () {
+it('uses the shared copy button for newly issued api tokens', function () {
$blade = file_get_contents(resource_path('views/livewire/security/api-tokens.blade.php'));
expect($blade)
- ->toContain('')
- ->not->toContain('navigator.clipboard.writeText(@js(session(\'token\')))');
+ ->toContain('not->toContain('navigator.clipboard');
});
it('keeps copy button padding above settings-workspace input overrides', function () {
diff --git a/tests/Feature/TeamInvitationUiTest.php b/tests/Feature/TeamInvitationUiTest.php
index 80a4a146df..38c8910986 100644
--- a/tests/Feature/TeamInvitationUiTest.php
+++ b/tests/Feature/TeamInvitationUiTest.php
@@ -51,25 +51,19 @@ it('renders a real copy button for pending invitation links', function () {
$view = file_get_contents(resource_path('views/livewire/team/invitations.blade.php'));
expect($view)
- ->toContain('aria-label="Copy invitation link"')
- ->toContain('window.copyToClipboard(@js($invite->link))')
- ->toContain('class="button h-7! shrink-0 px-2!"');
+ ->toContain('');
Livewire::test(Invitations::class, [
'invitations' => TeamInvitation::ownedByCurrentTeam()->get(),
])
->assertSee($invitation->link)
->assertSeeHtml('aria-label="Copy invitation link"')
- ->assertSeeHtml('window.copyToClipboard(')
+ ->assertSeeHtml('x-data="copyButton"')
->assertSeeHtml('type="button"');
});
-it('exposes a resilient global copyToClipboard helper', function () {
+it('keeps clipboard logic in the shared copy button instead of a global helper', function () {
$layout = file_get_contents(resource_path('views/layouts/base.blade.php'));
- expect($layout)
- ->toContain('async function copyToClipboard(text)')
- ->toContain('window.copyToClipboard = copyToClipboard')
- ->toContain('document.execCommand(\'copy\')')
- ->toContain('window.isSecureContext');
+ expect($layout)->not->toContain('copyToClipboard');
});