Skip to content

Commit cdaf756

Browse files
authored
Fix saved object share link (#66771) (#67039)
1 parent 8761b94 commit cdaf756

File tree

3 files changed

+175
-20
lines changed

3 files changed

+175
-20
lines changed

src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/plugins/share/public/components/url_panel_content.test.tsx

Lines changed: 170 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
* under the License.
1818
*/
1919

20-
jest.mock('../lib/url_shortener', () => ({}));
20+
import { EuiCopy, EuiRadioGroup, EuiSwitch, EuiSwitchEvent } from '@elastic/eui';
21+
22+
jest.mock('../lib/url_shortener', () => ({ shortenUrl: jest.fn() }));
2123

2224
import React from 'react';
2325
import { shallow } from 'enzyme';
2426

25-
import { UrlPanelContent } from './url_panel_content';
27+
import { ExportUrlAsType, UrlPanelContent } from './url_panel_content';
28+
import { act } from 'react-dom/test-utils';
29+
import { shortenUrl } from '../lib/url_shortener';
2630

2731
const defaultProps = {
2832
allowShortUrl: true,
@@ -31,19 +35,170 @@ const defaultProps = {
3135
post: () => Promise.resolve({} as any),
3236
};
3337

34-
test('render', () => {
35-
const component = shallow(<UrlPanelContent {...defaultProps} />);
36-
expect(component).toMatchSnapshot();
37-
});
38+
describe('share url panel content', () => {
39+
test('render', () => {
40+
const component = shallow(<UrlPanelContent {...defaultProps} />);
41+
expect(component).toMatchSnapshot();
42+
});
3843

39-
test('should enable saved object export option when objectId is provided', () => {
40-
const component = shallow(<UrlPanelContent {...defaultProps} objectId="id1" />);
41-
expect(component).toMatchSnapshot();
42-
});
44+
test('should enable saved object export option when objectId is provided', () => {
45+
const component = shallow(<UrlPanelContent {...defaultProps} objectId="id1" />);
46+
expect(component).toMatchSnapshot();
47+
});
48+
49+
test('should hide short url section when allowShortUrl is false', () => {
50+
const component = shallow(
51+
<UrlPanelContent {...defaultProps} allowShortUrl={false} objectId="id1" />
52+
);
53+
expect(component).toMatchSnapshot();
54+
});
55+
56+
test('should remove _a query parameter in saved object mode', () => {
57+
const component = shallow(
58+
<UrlPanelContent
59+
{...defaultProps}
60+
shareableUrl="http://localhost:5601/app/myapp#/?_g=()&_a=()"
61+
allowShortUrl={false}
62+
objectId="id1"
63+
/>
64+
);
65+
act(() => {
66+
component.find(EuiRadioGroup).prop('onChange')!(ExportUrlAsType.EXPORT_URL_AS_SAVED_OBJECT);
67+
});
68+
expect(component.find(EuiCopy).prop('textToCopy')).toEqual(
69+
'http://localhost:5601/app/myapp#/?_g=()'
70+
);
71+
});
72+
73+
describe('short url', () => {
74+
test('should generate short url and put it in copy button', async () => {
75+
const shortenUrlMock = shortenUrl as jest.Mock;
76+
shortenUrlMock.mockReset();
77+
shortenUrlMock.mockResolvedValue('http://localhost/short/url');
78+
79+
const component = shallow(
80+
<UrlPanelContent
81+
{...defaultProps}
82+
shareableUrl="http://localhost:5601/app/myapp#/?_g=()&_a=()"
83+
objectId="id1"
84+
/>
85+
);
86+
await act(async () => {
87+
component.find(EuiSwitch).prop('onChange')!(({
88+
target: { checked: true },
89+
} as unknown) as EuiSwitchEvent);
90+
});
91+
expect(shortenUrlMock).toHaveBeenCalledWith(
92+
'http://localhost:5601/app/myapp#/?_g=()&_a=()',
93+
expect.anything()
94+
);
95+
expect(component.find(EuiCopy).prop('textToCopy')).toContain('http://localhost/short/url');
96+
});
97+
98+
test('should hide short url for saved object mode', async () => {
99+
const component = shallow(
100+
<UrlPanelContent
101+
{...defaultProps}
102+
shareableUrl="http://localhost:5601/app/myapp#/"
103+
objectId="id1"
104+
/>
105+
);
106+
act(() => {
107+
component.find(EuiRadioGroup).prop('onChange')!(ExportUrlAsType.EXPORT_URL_AS_SAVED_OBJECT);
108+
});
109+
expect(component.exists(EuiSwitch)).toEqual(false);
110+
});
111+
});
112+
113+
describe('embedded', () => {
114+
const asIframe = (url: string) => `<iframe src="${url}" height="600" width="800"></iframe>`;
115+
116+
test('should add embedded flag to target code in snapshot mode', () => {
117+
const component = shallow(
118+
<UrlPanelContent
119+
{...defaultProps}
120+
shareableUrl="http://localhost:5601/app/myapp#/"
121+
isEmbedded
122+
allowShortUrl={false}
123+
objectId="id1"
124+
/>
125+
);
126+
expect(component.find(EuiCopy).prop('textToCopy')).toEqual(
127+
asIframe('http://localhost:5601/app/myapp#/?embed=true')
128+
);
129+
});
130+
131+
test('should add embedded flag to target code in snapshot mode with existing query parameters', () => {
132+
const component = shallow(
133+
<UrlPanelContent
134+
{...defaultProps}
135+
shareableUrl="http://localhost:5601/app/myapp#/?_g=()&_a=()"
136+
isEmbedded
137+
allowShortUrl={false}
138+
objectId="id1"
139+
/>
140+
);
141+
expect(component.find(EuiCopy).prop('textToCopy')).toEqual(
142+
asIframe('http://localhost:5601/app/myapp#/?embed=true&_g=()&_a=()')
143+
);
144+
});
145+
146+
test('should remove _a query parameter and add embedded flag in saved object mode', () => {
147+
const component = shallow(
148+
<UrlPanelContent
149+
{...defaultProps}
150+
shareableUrl="http://localhost:5601/app/myapp#/?_g=()&_a=()"
151+
isEmbedded
152+
allowShortUrl={false}
153+
objectId="id1"
154+
/>
155+
);
156+
act(() => {
157+
component.find(EuiRadioGroup).prop('onChange')!(ExportUrlAsType.EXPORT_URL_AS_SAVED_OBJECT);
158+
});
159+
expect(component.find(EuiCopy).prop('textToCopy')).toEqual(
160+
asIframe('http://localhost:5601/app/myapp#/?embed=true&_g=()')
161+
);
162+
});
163+
164+
test('should generate short url with embed flag and put it in copy button', async () => {
165+
const shortenUrlMock = shortenUrl as jest.Mock;
166+
shortenUrlMock.mockReset();
167+
shortenUrlMock.mockResolvedValue('http://localhost/short/url');
168+
169+
const component = shallow(
170+
<UrlPanelContent
171+
{...defaultProps}
172+
isEmbedded
173+
shareableUrl="http://localhost:5601/app/myapp#/?_g=()&_a=()"
174+
objectId="id1"
175+
/>
176+
);
177+
await act(async () => {
178+
component.find(EuiSwitch).prop('onChange')!(({
179+
target: { checked: true },
180+
} as unknown) as EuiSwitchEvent);
181+
});
182+
expect(shortenUrlMock).toHaveBeenCalledWith(
183+
'http://localhost:5601/app/myapp#/?embed=true&_g=()&_a=()',
184+
expect.anything()
185+
);
186+
expect(component.find(EuiCopy).prop('textToCopy')).toContain('http://localhost/short/url');
187+
});
43188

44-
test('should hide short url section when allowShortUrl is false', () => {
45-
const component = shallow(
46-
<UrlPanelContent {...defaultProps} allowShortUrl={false} objectId="id1" />
47-
);
48-
expect(component).toMatchSnapshot();
189+
test('should hide short url for saved object mode', async () => {
190+
const component = shallow(
191+
<UrlPanelContent
192+
{...defaultProps}
193+
isEmbedded
194+
shareableUrl="http://localhost:5601/app/myapp#/"
195+
objectId="id1"
196+
/>
197+
);
198+
act(() => {
199+
component.find(EuiRadioGroup).prop('onChange')!(ExportUrlAsType.EXPORT_URL_AS_SAVED_OBJECT);
200+
});
201+
expect(component.exists(EuiSwitch)).toEqual(false);
202+
});
203+
});
49204
});

src/plugins/share/public/components/url_panel_content.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ interface Props {
5252
post: HttpStart['post'];
5353
}
5454

55-
enum ExportUrlAsType {
55+
export enum ExportUrlAsType {
5656
EXPORT_URL_AS_SAVED_OBJECT = 'savedObject',
5757
EXPORT_URL_AS_SNAPSHOT = 'snapshot',
5858
}
@@ -181,7 +181,7 @@ export class UrlPanelContent extends Component<Props, State> {
181181
}),
182182
});
183183
if (this.props.isEmbedded) {
184-
formattedUrl = this.makeUrlEmbeddable(url);
184+
formattedUrl = this.makeUrlEmbeddable(formattedUrl);
185185
}
186186

187187
return formattedUrl;

0 commit comments

Comments
 (0)