🐛 Fixed comments block disappearing when performing certain actions (#19846)
closes https://linear.app/tryghost/issue/ENG-739 - `props.innerRef` in `<IFrame>` was inadvertently assumed to always exist, sometimes throwing an error on render when certain popups like the profile settings modal were opened resulting in the app crashing and the whole comments block disappearing - added a guard to ensure the ref exists before trying to set it - updated tests so the profile modal route is tested
This commit is contained in:
parent
5a5ddcb609
commit
dd3bc06761
@ -59,7 +59,9 @@ class IFrame extends Component<any> {
|
||||
|
||||
setNode(node: any) {
|
||||
this.node = node;
|
||||
this.props.innerRef.current = node;
|
||||
if (this.props.innerRef) {
|
||||
this.props.innerRef.current = node;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -160,6 +160,7 @@ const FormHeader: React.FC<FormHeaderProps> = ({show, name, expertise, editName,
|
||||
<div className="flex items-baseline justify-start">
|
||||
<button
|
||||
className={`group flex max-w-[80%] items-center justify-start whitespace-nowrap text-left font-sans text-[14px] tracking-tight text-[rgba(0,0,0,0.5)] transition duration-150 hover:text-[rgba(0,0,0,0.75)] sm:max-w-[90%] dark:text-[rgba(255,255,255,0.5)] dark:hover:text-[rgba(255,255,255,0.4)] ${!expertise && 'text-[rgba(0,0,0,0.3)] hover:text-[rgba(0,0,0,0.5)] dark:text-[rgba(255,255,255,0.3)]'}`}
|
||||
data-testid="expertise-button"
|
||||
type="button"
|
||||
onClick={editExpertise}
|
||||
>
|
||||
|
@ -116,7 +116,7 @@ const AddDetailsPopup = (props: Props) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="shadow-modal relative h-screen w-screen overflow-hidden rounded-none bg-white p-[28px] text-center sm:h-auto sm:w-[720px] sm:rounded-xl sm:p-0" onMouseDown={stopPropagation}>
|
||||
<div className="shadow-modal relative h-screen w-screen overflow-hidden rounded-none bg-white p-[28px] text-center sm:h-auto sm:w-[720px] sm:rounded-xl sm:p-0" data-testid="profile-modal" onMouseDown={stopPropagation}>
|
||||
<div className="flex">
|
||||
{!isMobile() &&
|
||||
<div className={`flex w-[40%] flex-col items-center justify-center bg-[#1C1C1C]`}>
|
||||
@ -146,6 +146,7 @@ const AddDetailsPopup = (props: Props) => {
|
||||
<input
|
||||
ref={inputNameRef}
|
||||
className={`flex h-[42px] w-full items-center rounded border border-neutral-200 px-3 font-sans text-[16px] outline-0 transition-[border-color] duration-200 focus:border-neutral-300 ${error.name && 'border-red-500 focus:border-red-500'}`}
|
||||
data-testid="name-input"
|
||||
id="comments-name"
|
||||
maxLength={64}
|
||||
name="name"
|
||||
@ -170,6 +171,7 @@ const AddDetailsPopup = (props: Props) => {
|
||||
<input
|
||||
ref={inputExpertiseRef}
|
||||
className={`flex h-[42px] w-full items-center rounded border border-neutral-200 px-3 font-sans text-[16px] outline-0 transition-[border-color] duration-200 focus:border-neutral-300 ${(expertiseCharsLeft === 0) && 'border-red-500 focus:border-red-500'}`}
|
||||
data-testid="expertise-input"
|
||||
id="comments-expertise"
|
||||
maxLength={maxExpertiseChars}
|
||||
name="expertise"
|
||||
@ -191,6 +193,7 @@ const AddDetailsPopup = (props: Props) => {
|
||||
/>
|
||||
<button
|
||||
className={`mt-10 flex h-[42px] w-full items-center justify-center rounded-md px-8 font-sans text-[15px] font-semibold text-white opacity-100 transition-opacity duration-200 ease-linear hover:opacity-90`}
|
||||
data-testid="save-button"
|
||||
style={{backgroundColor: accentColor ?? '#000000'}}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
|
@ -105,5 +105,46 @@ test.describe('Actions', async () => {
|
||||
await expect(frame.getByTestId('comment-component')).toHaveCount(4);
|
||||
await expect(frame.getByText('This is a reply 123')).toHaveCount(1);
|
||||
});
|
||||
|
||||
test('Can add expertise', async ({page}) => {
|
||||
const mockedApi = new MockedApi({});
|
||||
mockedApi.setMember({name: 'John Doe', expertise: null});
|
||||
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 1</p>'
|
||||
});
|
||||
|
||||
const {frame} = await initialize({
|
||||
mockedApi,
|
||||
page,
|
||||
publication: 'Publisher Weekly'
|
||||
});
|
||||
|
||||
const editor = frame.getByTestId('form-editor');
|
||||
await editor.click({force: true});
|
||||
await waitEditorFocused(editor);
|
||||
|
||||
const expertiseButton = frame.getByTestId('expertise-button');
|
||||
await expect(expertiseButton).toBeVisible();
|
||||
await expect(expertiseButton).toHaveText('Add your expertise');
|
||||
await expertiseButton.click();
|
||||
|
||||
const detailsFrame = page.frameLocator('iframe[title="addDetailsPopup"]');
|
||||
const profileModal = detailsFrame.getByTestId('profile-modal');
|
||||
await expect(profileModal).toBeVisible();
|
||||
|
||||
await expect(detailsFrame.getByTestId('name-input')).toHaveValue('John Doe');
|
||||
await expect(detailsFrame.getByTestId('expertise-input')).toHaveValue('');
|
||||
|
||||
await detailsFrame.getByTestId('name-input').fill('Testy McTest');
|
||||
await detailsFrame.getByTestId('expertise-input').fill('Software development');
|
||||
|
||||
await detailsFrame.getByTestId('save-button').click();
|
||||
|
||||
await expect(profileModal).not.toBeVisible();
|
||||
|
||||
await expect(frame.getByTestId('member-name')).toHaveText('Testy McTest');
|
||||
await expect(frame.getByTestId('expertise-button')).toHaveText('Software development');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -159,6 +159,14 @@ export class MockedApi {
|
||||
});
|
||||
}
|
||||
|
||||
if (route.request().method() === 'PUT') {
|
||||
const payload = JSON.parse(route.request().postData());
|
||||
this.member = {
|
||||
...this.member,
|
||||
...payload
|
||||
};
|
||||
}
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
body: JSON.stringify(this.member)
|
||||
@ -200,8 +208,8 @@ export class MockedApi {
|
||||
});
|
||||
});
|
||||
|
||||
// LIKE a single comment
|
||||
await page.route(`${path}/members/api/comments/*/like/`, async (route) => {
|
||||
// LIKE a single comment
|
||||
await page.route(`${path}/members/api/comments/*/like/`, async (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
const commentId = url.pathname.split('/').reverse()[2];
|
||||
|
||||
@ -233,7 +241,6 @@ export class MockedApi {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// GET a single comment
|
||||
await page.route(`${path}/members/api/comments/*/`, async (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
|
Loading…
Reference in New Issue
Block a user