Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions apps/portal/src/components/common/PoweredBy.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ export default class PoweredBy extends React.Component {
// want it to be translated
/* eslint-disable i18next/no-literal-string */
return (
<a href='https://ghost.org' target='_blank' rel='noopener noreferrer' onClick={() => {
window.open('https://ghost.org', '_blank');
}}>
<a href='https://ghost.org' target='_blank' rel='noopener noreferrer' data-test-powered-by>
<GhostLogo />
Powered by Ghost
</a>
Expand Down
20 changes: 20 additions & 0 deletions apps/portal/src/tests/portal-links.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,4 +343,24 @@ describe('Portal Data links:', () => {
expect(helpPageTitle).toBeInTheDocument();
});
});

describe('PoweredBy Component', () => {
test('renders powered by link in portal popup', async () => {
window.location.hash = '#/portal/signup';
const {popupFrame} = await setup({
site: FixtureSite.singleTier.basic,
member: FixtureMember.free
});

expect(popupFrame).toBeInTheDocument();

const poweredByLink = within(popupFrame.contentDocument).getByRole('link', {name: /powered by ghost/i});
expect(poweredByLink).toBeInTheDocument();
expect(poweredByLink).toHaveAttribute('href', 'https://ghost.org');
expect(poweredByLink).toHaveAttribute('target', '_blank');
expect(poweredByLink).toHaveAttribute('rel', 'noopener noreferrer');
// Verify no onClick handler exists
expect(poweredByLink.onclick).toBeNull();
});
Comment on lines +357 to +364
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace brittle onclick check with an interaction-based assertion (spy on iframe window.open).

element.onclick is null even when a framework attaches an onClick via addEventListener. This check won’t catch regressions. Instead, spy on popupFrame.contentWindow.open, click the link, and assert it wasn’t called.

-            const poweredByLink = within(popupFrame.contentDocument).getByRole('link', {name: /powered by ghost/i});
+            const poweredByLink = within(popupFrame.contentDocument).getByRole('link', {name: /powered by ghost/i});
             expect(poweredByLink).toBeInTheDocument();
             expect(poweredByLink).toHaveAttribute('href', 'https://ghost.org');
             expect(poweredByLink).toHaveAttribute('target', '_blank');
             expect(poweredByLink).toHaveAttribute('rel', 'noopener noreferrer');
-            // Verify no onClick handler exists
-            expect(poweredByLink.onclick).toBeNull();
+            // Clicking the link should not invoke script-driven window.open (prevents "two tabs" regression)
+            const openSpy = jest.spyOn(popupFrame.contentWindow, 'open').mockImplementation(() => null);
+            fireEvent.click(poweredByLink);
+            expect(openSpy).not.toHaveBeenCalled();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const poweredByLink = within(popupFrame.contentDocument).getByRole('link', {name: /powered by ghost/i});
expect(poweredByLink).toBeInTheDocument();
expect(poweredByLink).toHaveAttribute('href', 'https://ghost.org');
expect(poweredByLink).toHaveAttribute('target', '_blank');
expect(poweredByLink).toHaveAttribute('rel', 'noopener noreferrer');
// Verify no onClick handler exists
expect(poweredByLink.onclick).toBeNull();
});
const poweredByLink = within(popupFrame.contentDocument).getByRole('link', {name: /powered by ghost/i});
expect(poweredByLink).toBeInTheDocument();
expect(poweredByLink).toHaveAttribute('href', 'https://ghost.org');
expect(poweredByLink).toHaveAttribute('target', '_blank');
expect(poweredByLink).toHaveAttribute('rel', 'noopener noreferrer');
// Clicking the link should not invoke script-driven window.open (prevents "two tabs" regression)
const openSpy = jest.spyOn(popupFrame.contentWindow, 'open').mockImplementation(() => null);
fireEvent.click(poweredByLink);
expect(openSpy).not.toHaveBeenCalled();
🤖 Prompt for AI Agents
In apps/portal/src/tests/portal-links.test.js around lines 357 to 364, replace
the brittle check of poweredByLink.onclick being null with an interaction-based
assertion: create a spy/mock on popupFrame.contentWindow.open (or
jest.spyOn(popupFrame.contentWindow, 'open')), simulate a user click on the
poweredByLink (use userEvent.click or element.click()), and assert that
contentWindow.open was not called; remove the onclick assertion and keep the
href/target/rel attribute expectations so the test verifies behavior rather than
presence of an onclick property.

});
});
Loading