[MM-64371] Prevent WS being closed by browser due to navigation (#31367)
* prevent ws being closed by browser due to navigation * add href back --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e2b6e807c4
Коммит
254f641182
@@ -0,0 +1,73 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {screen, fireEvent} from '@testing-library/react';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import {renderWithContext} from 'tests/react_testing_utils';
|
||||||
|
|
||||||
|
import ProfilePopoverEmail from './profile_popover_email';
|
||||||
|
|
||||||
|
// Mock window.open
|
||||||
|
const mockWindowOpen = jest.fn();
|
||||||
|
Object.defineProperty(window, 'open', {
|
||||||
|
writable: true,
|
||||||
|
value: mockWindowOpen,
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('components/ProfilePopoverEmail', () => {
|
||||||
|
const baseProps = {
|
||||||
|
email: 'test@example.com',
|
||||||
|
haveOverrideProp: false,
|
||||||
|
isBot: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockWindowOpen.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not render when email is empty', () => {
|
||||||
|
const props = {
|
||||||
|
...baseProps,
|
||||||
|
email: '',
|
||||||
|
};
|
||||||
|
const {container} = renderWithContext(<ProfilePopoverEmail {...props}/>);
|
||||||
|
expect(container.firstChild).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should handle different email formats', () => {
|
||||||
|
const props = {
|
||||||
|
...baseProps,
|
||||||
|
email: 'user.name+tag@domain.co.uk',
|
||||||
|
};
|
||||||
|
renderWithContext(<ProfilePopoverEmail {...props}/>);
|
||||||
|
|
||||||
|
const email = 'user.name+tag@domain.co.uk';
|
||||||
|
const emailLink = screen.getByText(email);
|
||||||
|
expect(emailLink).toBeInTheDocument();
|
||||||
|
expect(emailLink.tagName).toBe('A');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should open email client when clicked', () => {
|
||||||
|
renderWithContext(<ProfilePopoverEmail {...baseProps}/>);
|
||||||
|
|
||||||
|
const email = 'test@example.com';
|
||||||
|
const emailLink = screen.getByText(email);
|
||||||
|
|
||||||
|
fireEvent.click(emailLink);
|
||||||
|
|
||||||
|
expect(mockWindowOpen).toHaveBeenCalledWith('mailto:test@example.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should prevent default click behavior', () => {
|
||||||
|
renderWithContext(<ProfilePopoverEmail {...baseProps}/>);
|
||||||
|
|
||||||
|
const email = 'test@example.com';
|
||||||
|
const emailLink = screen.getByText(email);
|
||||||
|
|
||||||
|
const clickEvent = fireEvent.click(emailLink);
|
||||||
|
|
||||||
|
expect(clickEvent).toBe(false); // fireEvent.click returns false when preventDefault was called
|
||||||
|
expect(mockWindowOpen).toHaveBeenCalledWith('mailto:test@example.com');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -17,6 +17,11 @@ const ProfilePopoverEmail = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleEmailClick(e: React.MouseEvent<HTMLAnchorElement>) {
|
||||||
|
e.preventDefault();
|
||||||
|
window.open(`mailto:${email}`);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
title={email}
|
title={email}
|
||||||
@@ -28,7 +33,8 @@ const ProfilePopoverEmail = ({
|
|||||||
aria-hidden='true'
|
aria-hidden='true'
|
||||||
/>
|
/>
|
||||||
<a
|
<a
|
||||||
href={'mailto:' + email}
|
href={`mailto:${email}`}
|
||||||
|
onClick={handleEmailClick}
|
||||||
>
|
>
|
||||||
{email}
|
{email}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import {screen} from '@testing-library/react';
|
import {screen, fireEvent} from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import type {UserPropertyField} from '@mattermost/types/properties';
|
import type {UserPropertyField} from '@mattermost/types/properties';
|
||||||
@@ -12,6 +12,13 @@ import ProfilePopoverPhone from './profile_popover_phone';
|
|||||||
|
|
||||||
import {TestHelper} from '../../utils/test_helper';
|
import {TestHelper} from '../../utils/test_helper';
|
||||||
|
|
||||||
|
// Mock window.open
|
||||||
|
const mockWindowOpen = jest.fn();
|
||||||
|
Object.defineProperty(window, 'open', {
|
||||||
|
writable: true,
|
||||||
|
value: mockWindowOpen,
|
||||||
|
});
|
||||||
|
|
||||||
describe('components/ProfilePopoverPhone', () => {
|
describe('components/ProfilePopoverPhone', () => {
|
||||||
const attribute: UserPropertyField = {
|
const attribute: UserPropertyField = {
|
||||||
id: 'phone_attribute_id',
|
id: 'phone_attribute_id',
|
||||||
@@ -38,6 +45,10 @@ describe('components/ProfilePopoverPhone', () => {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockWindowOpen.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
test('should not render when phone is missing', () => {
|
test('should not render when phone is missing', () => {
|
||||||
const props = {
|
const props = {
|
||||||
...baseProps,
|
...baseProps,
|
||||||
@@ -46,8 +57,8 @@ describe('components/ProfilePopoverPhone', () => {
|
|||||||
custom_profile_attributes: {},
|
custom_profile_attributes: {},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
renderWithContext(<ProfilePopoverPhone {...props}/>);
|
const {container} = renderWithContext(<ProfilePopoverPhone {...props}/>);
|
||||||
expect(screen.queryByRole('link')).not.toBeInTheDocument();
|
expect(container.firstChild).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should not render when phone is empty', () => {
|
test('should not render when phone is empty', () => {
|
||||||
@@ -60,17 +71,17 @@ describe('components/ProfilePopoverPhone', () => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
renderWithContext(<ProfilePopoverPhone {...props}/>);
|
const {container} = renderWithContext(<ProfilePopoverPhone {...props}/>);
|
||||||
expect(screen.queryByRole('link')).not.toBeInTheDocument();
|
expect(container.firstChild).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should render phone with icon', () => {
|
test('should render phone with icon', () => {
|
||||||
renderWithContext(<ProfilePopoverPhone {...baseProps}/>);
|
renderWithContext(<ProfilePopoverPhone {...baseProps}/>);
|
||||||
|
|
||||||
const phone = '+1 (555) 123-4567';
|
const phone = '+1 (555) 123-4567';
|
||||||
const link = screen.getByRole('link');
|
const phoneLink = screen.getByText(phone);
|
||||||
expect(link).toHaveAttribute('href', 'tel:+1 (555) 123-4567');
|
expect(phoneLink).toBeInTheDocument();
|
||||||
expect(link).toHaveTextContent(phone);
|
expect(phoneLink.tagName).toBe('A');
|
||||||
expect(screen.getByTitle(phone)).toBeInTheDocument();
|
expect(screen.getByTitle(phone)).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText('phone icon')).toBeInTheDocument();
|
expect(screen.getByLabelText('phone icon')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
@@ -88,8 +99,31 @@ describe('components/ProfilePopoverPhone', () => {
|
|||||||
renderWithContext(<ProfilePopoverPhone {...props}/>);
|
renderWithContext(<ProfilePopoverPhone {...props}/>);
|
||||||
|
|
||||||
const phone = '+44 20 7123 4567';
|
const phone = '+44 20 7123 4567';
|
||||||
const link = screen.getByRole('link');
|
const phoneLink = screen.getByText(phone);
|
||||||
expect(link).toHaveAttribute('href', 'tel:+44 20 7123 4567');
|
expect(phoneLink).toBeInTheDocument();
|
||||||
expect(link).toHaveTextContent(phone);
|
expect(phoneLink.tagName).toBe('A');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should open phone dialer when clicked', () => {
|
||||||
|
renderWithContext(<ProfilePopoverPhone {...baseProps}/>);
|
||||||
|
|
||||||
|
const phone = '+1 (555) 123-4567';
|
||||||
|
const phoneLink = screen.getByText(phone);
|
||||||
|
|
||||||
|
fireEvent.click(phoneLink);
|
||||||
|
|
||||||
|
expect(mockWindowOpen).toHaveBeenCalledWith('tel:+1 (555) 123-4567');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should prevent default click behavior', () => {
|
||||||
|
renderWithContext(<ProfilePopoverPhone {...baseProps}/>);
|
||||||
|
|
||||||
|
const phone = '+1 (555) 123-4567';
|
||||||
|
const phoneLink = screen.getByText(phone);
|
||||||
|
|
||||||
|
const clickEvent = fireEvent.click(phoneLink);
|
||||||
|
|
||||||
|
expect(clickEvent).toBe(false); // fireEvent.click returns false when preventDefault was called
|
||||||
|
expect(mockWindowOpen).toHaveBeenCalledWith('tel:+1 (555) 123-4567');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ const ProfilePopoverPhone = ({attribute, userProfile}: Props) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handlePhoneClick(e: React.MouseEvent<HTMLAnchorElement>) {
|
||||||
|
e.preventDefault();
|
||||||
|
window.open(`tel:${phone}`);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
title={phone}
|
title={phone}
|
||||||
@@ -29,7 +34,8 @@ const ProfilePopoverPhone = ({attribute, userProfile}: Props) => {
|
|||||||
aria-label='phone icon'
|
aria-label='phone icon'
|
||||||
/>
|
/>
|
||||||
<a
|
<a
|
||||||
href={'tel:' + phone}
|
href={`tel:${phone}`}
|
||||||
|
onClick={handlePhoneClick}
|
||||||
>
|
>
|
||||||
{phone}
|
{phone}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user