diff --git a/webapp/src/components/link_tooltip/index.jsx b/webapp/src/components/link_tooltip/index.jsx index 00bd19fa4..7f1448e18 100644 --- a/webapp/src/components/link_tooltip/index.jsx +++ b/webapp/src/components/link_tooltip/index.jsx @@ -8,7 +8,10 @@ import manifest from '@/manifest'; import {LinkTooltip} from './link_tooltip'; const mapStateToProps = (state) => { - return {connected: state[`plugins-${manifest.id}`].connected}; + return { + connected: state[`plugins-${manifest.id}`].connected, + enterpriseURL: state[`plugins-${manifest.id}`].enterpriseURL, + }; }; export default connect(mapStateToProps, null)(LinkTooltip); diff --git a/webapp/src/components/link_tooltip/link_tooltip.jsx b/webapp/src/components/link_tooltip/link_tooltip.jsx index feff6df51..88de4b63f 100644 --- a/webapp/src/components/link_tooltip/link_tooltip.jsx +++ b/webapp/src/components/link_tooltip/link_tooltip.jsx @@ -13,32 +13,43 @@ import {getLabelFontColor, hexToRGB} from '../../utils/styles'; const maxTicketDescriptionLength = 160; -export const LinkTooltip = ({href, connected, show, theme}) => { +export const LinkTooltip = ({href, connected, show, theme, enterpriseURL}) => { const [data, setData] = useState(null); useEffect(() => { const initData = async () => { - if (href.includes('github.com/')) { - const [owner, repo, type, number] = href.split('github.com/')[1].split('/'); - if (!owner | !repo | !type | !number) { - return; + let owner; + let repo; + let type; + let number; + + if (enterpriseURL) { + const entURL = enterpriseURL.endsWith('/') ? enterpriseURL : enterpriseURL + '/'; + if (href.startsWith(entURL)) { + [owner, repo, type, number] = href.substring(entURL.length).split('/'); } + } else if (href.includes('github.com/')) { + [owner, repo, type, number] = href.split('github.com/')[1].split('/'); + } - let res; - switch (type) { - case 'issues': - res = await Client.getIssue(owner, repo, number); - break; - case 'pull': - res = await Client.getPullRequest(owner, repo, number); - break; - } - if (res) { - res.owner = owner; - res.repo = repo; - res.type = type; - } - setData(res); + if (!owner || !repo || !type || !number) { + return; + } + + let res; + switch (type) { + case 'issues': + res = await Client.getIssue(owner, repo, number); + break; + case 'pull': + res = await Client.getPullRequest(owner, repo, number); + break; + } + if (res) { + res.owner = owner; + res.repo = repo; + res.type = type; } + setData(res); }; // show is not provided for Mattermost Server < 5.28 @@ -47,7 +58,7 @@ export const LinkTooltip = ({href, connected, show, theme}) => { } initData(); - }, [connected, data, href, show]); + }, [connected, data, href, show, enterpriseURL]); const getIconElement = () => { const iconProps = { @@ -117,7 +128,7 @@ export const LinkTooltip = ({href, connected, show, theme}) => {
- { getIconElement() } + {getIconElement()} {/* info */} @@ -135,7 +146,7 @@ export const LinkTooltip = ({href, connected, show, theme}) => {

{'Opened by '} @@ -193,4 +204,5 @@ LinkTooltip.propTypes = { connected: PropTypes.bool.isRequired, theme: PropTypes.object.isRequired, show: PropTypes.bool, + enterpriseURL: PropTypes.string, }; diff --git a/webapp/src/components/link_tooltip/link_tooltip.test.jsx b/webapp/src/components/link_tooltip/link_tooltip.test.jsx new file mode 100644 index 000000000..a6ad64282 --- /dev/null +++ b/webapp/src/components/link_tooltip/link_tooltip.test.jsx @@ -0,0 +1,96 @@ +import React from 'react'; +import {mount} from 'enzyme'; + +import Client from '@/client'; + +import {LinkTooltip} from './link_tooltip'; + +jest.mock('@/client', () => ({ + getIssue: jest.fn(), + getPullRequest: jest.fn(), +})); + +jest.mock('react-markdown', () => () =>

); + +describe('LinkTooltip', () => { + const baseProps = { + href: 'https://github.com/mattermost/mattermost-plugin-github/issues/1', + connected: true, + show: true, + theme: { + centerChannelBg: '#ffffff', + centerChannelColor: '#333333', + }, + enterpriseURL: '', + }; + + let wrapper; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + afterEach(() => { + if (wrapper && wrapper.length) { + wrapper.unmount(); + } + }); + + test('should fetch issue for github.com link', () => { + // We need to use mount or wait for useEffect? + // shallow renders the component, useEffect is a hook. + // Enzyme shallow supports hooks in newer versions, but let's check if we need to manually trigger logic. + // The component uses useEffect to call initData. + wrapper = mount(); + expect(Client.getIssue).toHaveBeenCalledWith('mattermost', 'mattermost-plugin-github', '1'); + }); + + test('should fetch pull request for github.com link', () => { + const props = { + ...baseProps, + href: 'https://github.com/mattermost/mattermost-plugin-github/pull/2', + }; + wrapper = mount(); + expect(Client.getPullRequest).toHaveBeenCalledWith('mattermost', 'mattermost-plugin-github', '2'); + }); + + test('should fetch issue for enterprise link', () => { + const props = { + ...baseProps, + href: 'https://github.example.com/mattermost/mattermost-plugin-github/issues/3', + enterpriseURL: 'https://github.example.com', + }; + wrapper = mount(); + expect(Client.getIssue).toHaveBeenCalledWith('mattermost', 'mattermost-plugin-github', '3'); + }); + + test('should fetch pull request for enterprise link', () => { + const props = { + ...baseProps, + href: 'https://github.example.com/mattermost/mattermost-plugin-github/pull/4', + enterpriseURL: 'https://github.example.com', + }; + wrapper = mount(); + expect(Client.getPullRequest).toHaveBeenCalledWith('mattermost', 'mattermost-plugin-github', '4'); + }); + + test('should handle enterprise URL with trailing slash', () => { + const props = { + ...baseProps, + href: 'https://github.example.com/mattermost/mattermost-plugin-github/issues/5', + enterpriseURL: 'https://github.example.com/', + }; + wrapper = mount(); + expect(Client.getIssue).toHaveBeenCalledWith('mattermost', 'mattermost-plugin-github', '5'); + }); + + test('should not fetch if enterprise URL does not match', () => { + const props = { + ...baseProps, + href: 'https://other-github.com/mattermost/mattermost-plugin-github/issues/6', + enterpriseURL: 'https://github.example.com', + }; + wrapper = mount(); + expect(Client.getIssue).not.toHaveBeenCalled(); + }); +});