From 23e918954b587ff5a8567516eaff8b4314a8a7ed Mon Sep 17 00:00:00 2001 From: William Allen Date: Sat, 27 Jun 2026 11:18:00 -0400 Subject: [PATCH] Add "copy" button to all output boxes --- .../js/vue/components/shared/CodeBox.vue | 79 ++++++++++++++++--- tests/cypress/component/code-box.cy.js | 61 ++++++++++++++ tests/cypress/e2e/tests.cy.js | 4 +- 3 files changed, 129 insertions(+), 15 deletions(-) diff --git a/resources/js/vue/components/shared/CodeBox.vue b/resources/js/vue/components/shared/CodeBox.vue index 557edf69ee..def8d3f4ba 100644 --- a/resources/js/vue/components/shared/CodeBox.vue +++ b/resources/js/vue/components/shared/CodeBox.vue @@ -1,25 +1,45 @@ diff --git a/tests/cypress/component/code-box.cy.js b/tests/cypress/component/code-box.cy.js index 6854c6ef0b..4829a0543b 100644 --- a/tests/cypress/component/code-box.cy.js +++ b/tests/cypress/component/code-box.cy.js @@ -77,4 +77,65 @@ describe('CodeBox', () => { cy.get('a').eq(0).should('have.attr', 'href', 'https://example.com'); cy.get('a').eq(1).should('have.attr', 'href', 'https://example.com'); }); + + it('shows the copy button by default when text is present', () => { + cy.mount(CodeBox, { + props: { + text: 'some text', + }, + }); + + cy.get('[data-test="copy-button"]').should('exist'); + }); + + it('hides the copy button when showCopyButton is false', () => { + cy.mount(CodeBox, { + props: { + text: 'some text', + showCopyButton: false, + }, + }); + + cy.get('[data-test="copy-button"]').should('not.exist'); + }); + + it('hides the copy button when the text is empty', () => { + cy.mount(CodeBox, { + props: { + text: '', + }, + }); + + cy.get('[data-test="copy-button"]').should('not.exist'); + }); + + it('hides the copy button when the text becomes empty', () => { + cy.mount(CodeBox, { + props: { + text: 'some text', + }, + }).then(({ wrapper }) => { + cy.get('[data-test="copy-button"]').should('exist').then(() => { + wrapper.setProps({ text: '' }); + cy.get('[data-test="copy-button"]').should('not.exist'); + }); + }); + }); + + it('copies the text to the clipboard when the copy button is clicked', () => { + const code = 'const message = "Hello, World!";'; + + cy.mount(CodeBox, { + props: { + text: code, + }, + }).then(() => { + cy.window().then((win) => { + cy.stub(win.navigator.clipboard, 'writeText').resolves().as('writeText'); + }); + + cy.get('[data-test="copy-button"]').click(); + cy.get('@writeText').should('have.been.calledWith', code); + }); + }); }); diff --git a/tests/cypress/e2e/tests.cy.js b/tests/cypress/e2e/tests.cy.js index 342e7f4c58..339373d634 100644 --- a/tests/cypress/e2e/tests.cy.js +++ b/tests/cypress/e2e/tests.cy.js @@ -63,13 +63,13 @@ describe('the test page', () => { // expand the test command line cy.get('a#commandlinelink').should('contain', 'Show Command Line').click(); cy.get('a#commandlinelink').should('contain', 'Hide Command Line'); - cy.get('pre#commandline').should('contain', '/a/path/to/test/nap --run-test .'); + cy.get('#commandline').should('contain', '/a/path/to/test/nap --run-test .'); // toggle it back cy.get('a#commandlinelink').click(); cy.get('a#commandlinelink').should('contain', 'Show Command Line'); // verify the test output field - cy.get('pre#test_output').should('contain', 'PASS'); + cy.get('#test_output').should('contain', 'PASS'); });