2023-07-26 22:31:52 -07:00
|
|
|
/*
|
2024-02-13 07:59:27 -08:00
|
|
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
2023-07-26 22:31:52 -07:00
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
*/
|
|
|
|
|
2023-03-19 00:59:31 -07:00
|
|
|
import { describe, test, assert, afterEach } from 'vitest';
|
|
|
|
import { render, cleanup, type RenderResult } from '@testing-library/vue';
|
|
|
|
import './init';
|
2023-12-30 16:45:35 -08:00
|
|
|
import type { summaly } from '@misskey-dev/summaly';
|
2023-10-21 02:38:07 -07:00
|
|
|
import { components } from '@/components/index.js';
|
|
|
|
import { directives } from '@/directives/index.js';
|
2023-03-19 00:59:31 -07:00
|
|
|
import MkUrlPreview from '@/components/MkUrlPreview.vue';
|
|
|
|
|
|
|
|
type SummalyResult = Awaited<ReturnType<typeof summaly>>;
|
|
|
|
|
2023-08-12 20:29:13 -07:00
|
|
|
describe('MkUrlPreview', () => {
|
2023-03-19 00:59:31 -07:00
|
|
|
const renderPreviewBy = async (summary: Partial<SummalyResult>): Promise<RenderResult> => {
|
|
|
|
if (!summary.player) {
|
|
|
|
summary.player = {
|
|
|
|
url: null,
|
|
|
|
width: null,
|
|
|
|
height: null,
|
|
|
|
allow: [],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
fetchMock.mockOnceIf(/^\/url?/, () => {
|
|
|
|
return {
|
|
|
|
status: 200,
|
|
|
|
body: JSON.stringify(summary),
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
const result = render(MkUrlPreview, {
|
|
|
|
props: { url: summary.url },
|
2023-04-04 22:30:03 -07:00
|
|
|
global: { directives, components },
|
2023-03-19 00:59:31 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
await new Promise<void>(resolve => {
|
|
|
|
const observer = new MutationObserver(() => {
|
|
|
|
resolve();
|
|
|
|
observer.disconnect();
|
|
|
|
});
|
|
|
|
observer.observe(result.container, { childList: true, subtree: true });
|
|
|
|
});
|
|
|
|
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
|
|
|
const renderAndOpenPreview = async (summary: Partial<SummalyResult>): Promise<HTMLIFrameElement | null> => {
|
|
|
|
const mkUrlPreview = await renderPreviewBy(summary);
|
|
|
|
const buttons = mkUrlPreview.getAllByRole('button');
|
|
|
|
buttons[0].click();
|
|
|
|
// Wait for the click event to be fired
|
|
|
|
await Promise.resolve();
|
|
|
|
|
|
|
|
return mkUrlPreview.container.querySelector('iframe');
|
|
|
|
};
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
fetchMock.resetMocks();
|
|
|
|
cleanup();
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Should render the description', async () => {
|
|
|
|
const mkUrlPreview = await renderPreviewBy({
|
|
|
|
url: 'https://example.local',
|
|
|
|
description: 'Mocked description',
|
|
|
|
});
|
|
|
|
mkUrlPreview.getByText('Mocked description');
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Having a player should render a button', async () => {
|
|
|
|
const mkUrlPreview = await renderPreviewBy({
|
|
|
|
url: 'https://example.local',
|
|
|
|
player: {
|
|
|
|
url: 'https://example.local/player',
|
|
|
|
width: null,
|
|
|
|
height: null,
|
|
|
|
allow: [],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
const buttons = mkUrlPreview.getAllByRole('button');
|
|
|
|
assert.strictEqual(buttons.length, 2, 'two buttons');
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Having a player should setup the iframe', async () => {
|
|
|
|
const iframe = await renderAndOpenPreview({
|
|
|
|
url: 'https://example.local',
|
|
|
|
player: {
|
|
|
|
url: 'https://example.local/player',
|
|
|
|
width: null,
|
|
|
|
height: null,
|
|
|
|
allow: [],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
assert.exists(iframe, 'iframe should exist');
|
|
|
|
assert.strictEqual(iframe?.src, 'https://example.local/player?autoplay=1&auto_play=1');
|
|
|
|
assert.strictEqual(
|
|
|
|
iframe?.sandbox.toString(),
|
|
|
|
'allow-popups allow-scripts allow-storage-access-by-user-activation allow-same-origin',
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Having a player with `allow` field should set permissions', async () => {
|
|
|
|
const iframe = await renderAndOpenPreview({
|
|
|
|
url: 'https://example.local',
|
|
|
|
player: {
|
|
|
|
url: 'https://example.local/player',
|
|
|
|
width: null,
|
|
|
|
height: null,
|
|
|
|
allow: ['fullscreen', 'web-share'],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
assert.exists(iframe, 'iframe should exist');
|
|
|
|
assert.strictEqual(iframe?.allow, 'fullscreen;web-share');
|
|
|
|
});
|
|
|
|
|
2024-02-07 20:16:22 -08:00
|
|
|
test('A Summaly proxy response without allow falls back to the default', async () => {
|
|
|
|
const iframe = await renderAndOpenPreview({
|
|
|
|
url: 'https://example.local',
|
|
|
|
player: {
|
|
|
|
url: 'https://example.local/player',
|
|
|
|
width: null,
|
|
|
|
height: null,
|
|
|
|
allow: undefined as any,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
assert.exists(iframe, 'iframe should exist');
|
|
|
|
assert.strictEqual(iframe?.allow, 'autoplay;encrypted-media;fullscreen');
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Filtering the allow list from the Summaly proxy', async () => {
|
|
|
|
const iframe = await renderAndOpenPreview({
|
|
|
|
url: 'https://example.local',
|
|
|
|
player: {
|
|
|
|
url: 'https://example.local/player',
|
|
|
|
width: null,
|
|
|
|
height: null,
|
|
|
|
allow: ['autoplay', 'camera', 'fullscreen'],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
assert.exists(iframe, 'iframe should exist');
|
|
|
|
assert.strictEqual(iframe?.allow, 'autoplay;fullscreen');
|
|
|
|
});
|
|
|
|
|
2023-03-19 00:59:31 -07:00
|
|
|
test('Having a player width should keep the fixed aspect ratio', async () => {
|
|
|
|
const iframe = await renderAndOpenPreview({
|
|
|
|
url: 'https://example.local',
|
|
|
|
player: {
|
|
|
|
url: 'https://example.local/player',
|
|
|
|
width: 400,
|
|
|
|
height: 200,
|
|
|
|
allow: [],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
assert.exists(iframe, 'iframe should exist');
|
|
|
|
assert.strictEqual(iframe?.parentElement?.style.paddingTop, '50%');
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Having a player width should keep the fixed height', async () => {
|
|
|
|
const iframe = await renderAndOpenPreview({
|
|
|
|
url: 'https://example.local',
|
|
|
|
player: {
|
|
|
|
url: 'https://example.local/player',
|
|
|
|
width: null,
|
|
|
|
height: 200,
|
|
|
|
allow: [],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
assert.exists(iframe, 'iframe should exist');
|
|
|
|
assert.strictEqual(iframe?.parentElement?.style.paddingTop, '200px');
|
|
|
|
});
|
2023-08-12 20:29:13 -07:00
|
|
|
|
|
|
|
test('Loading a tweet in iframe', async () => {
|
|
|
|
const iframe = await renderAndOpenPreview({
|
|
|
|
url: 'https://twitter.com/i/web/status/1685072521782325249',
|
|
|
|
});
|
|
|
|
assert.exists(iframe, 'iframe should exist');
|
|
|
|
assert.strictEqual(iframe?.getAttribute('allow'), 'fullscreen;web-share');
|
2023-11-21 17:19:30 -08:00
|
|
|
assert.strictEqual(iframe?.getAttribute('sandbox'), 'allow-popups allow-popups-to-escape-sandbox allow-scripts allow-same-origin');
|
2023-08-12 20:29:13 -07:00
|
|
|
});
|
2023-08-21 23:56:36 -07:00
|
|
|
|
|
|
|
test('Loading a post in iframe', async () => {
|
|
|
|
const iframe = await renderAndOpenPreview({
|
|
|
|
url: 'https://x.com/i/web/status/1685072521782325249',
|
|
|
|
});
|
|
|
|
assert.exists(iframe, 'iframe should exist');
|
|
|
|
assert.strictEqual(iframe?.getAttribute('allow'), 'fullscreen;web-share');
|
2023-11-21 17:19:30 -08:00
|
|
|
assert.strictEqual(iframe?.getAttribute('sandbox'), 'allow-popups allow-popups-to-escape-sandbox allow-scripts allow-same-origin');
|
2023-08-21 23:56:36 -07:00
|
|
|
});
|
2023-03-19 00:59:31 -07:00
|
|
|
});
|