Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a192e9-c28b-7533-bf25-e2341364c22a
94 lines
4.9 KiB
JavaScript
94 lines
4.9 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import {chromium} from 'playwright';
|
|
|
|
const base = new URL(process.argv[2]);
|
|
assert.equal(base.protocol, 'http:');
|
|
assert.ok(['localhost', '127.0.0.1'].includes(base.hostname));
|
|
const browser = await chromium.launch({headless: true});
|
|
try {
|
|
const context = await browser.newContext();
|
|
const unexpected = [];
|
|
await context.route('**/*', route => {
|
|
if (new URL(route.request().url()).origin === base.origin) return route.continue();
|
|
unexpected.push(route.request().url());
|
|
return route.abort();
|
|
});
|
|
const page = await context.newPage();
|
|
page.setDefaultTimeout(10000);
|
|
async function login(subject) {
|
|
await page.goto(`${base.origin}/auth/dev-login/`);
|
|
await page.getByLabel('Subject').fill(subject);
|
|
await page.getByLabel('Tenant').fill('tenant:attachment-test');
|
|
await page.getByRole('button', {name: 'Establish session'}).click();
|
|
await page.waitForURL('**/app/');
|
|
}
|
|
const shared = `${base.origin}/app/spaces/attachments-shared/`;
|
|
const destination = `${base.origin}/app/spaces/attachments-private/`;
|
|
const source = `${shared}?page=notes`;
|
|
async function menu(url, author) {
|
|
await page.goto(url);
|
|
await page.locator('summary', {hasText: 'Attachments'}).click();
|
|
await page.getByRole('link', {name: author
|
|
? 'Open, download or manage attachments' : 'Open or download attachments', exact: true}).click();
|
|
await page.waitForURL('**/attachments/');
|
|
}
|
|
async function downloadedBytes() {
|
|
const pending = page.waitForEvent('download');
|
|
await page.getByRole('link', {name: 'Download', exact: true}).click();
|
|
const stream = await (await pending).createReadStream();
|
|
const chunks = [];
|
|
for await (const chunk of stream) chunks.push(chunk);
|
|
return Buffer.concat(chunks).toString();
|
|
}
|
|
await login('file-author');
|
|
await menu(source, true);
|
|
await page.getByLabel('File (up to 16 MiB)').setInputFiles({
|
|
name: 'meeting-notes.txt', mimeType: 'text/plain', buffer: Buffer.from('Synthetic attachment bytes'),
|
|
});
|
|
await page.getByRole('button', {name: 'Add attachment', exact: true}).click();
|
|
await page.waitForURL('**/attachments/');
|
|
assert.match(await page.locator('main').innerText(), /Attachment added/);
|
|
const originalDownload = await page.getByRole('link', {name: 'Download', exact: true}).getAttribute('href');
|
|
assert.equal(await downloadedBytes(), 'Synthetic attachment bytes');
|
|
await login('file-reader');
|
|
await menu(source, false);
|
|
assert.equal(await page.getByRole('button', {name: 'Add attachment', exact: true}).count(), 0);
|
|
assert.equal(await page.getByRole('button', {name: 'Remove from page', exact: true}).count(), 0);
|
|
assert.equal(await downloadedBytes(), 'Synthetic attachment bytes');
|
|
await login('file-outsider');
|
|
assert.equal((await page.goto(new URL(originalDownload, base).href)).status(), 404);
|
|
assert.equal((await page.goto(`${shared}pages/notes/attachments/`)).status(), 404);
|
|
await login('file-author');
|
|
await page.goto(source);
|
|
await page.getByRole('link', {name: 'Duplicate page', exact: true}).click();
|
|
await page.getByLabel('Destination space').selectOption('attachments-private');
|
|
await page.getByLabel('Title', {exact: false}).fill('Independent files');
|
|
await page.getByLabel('New page slug', {exact: false}).fill('copied');
|
|
await page.getByRole('button', {name: 'Create duplicate'}).click();
|
|
await page.waitForURL('**?page=copied');
|
|
await menu(`${destination}?page=copied`, true);
|
|
assert.equal(await downloadedBytes(), 'Synthetic attachment bytes');
|
|
const copiedDownload = await page.getByRole('link', {name: 'Download', exact: true}).getAttribute('href');
|
|
assert.notEqual(copiedDownload, originalDownload);
|
|
await page.getByRole('button', {name: 'Remove from page', exact: true}).click();
|
|
await page.waitForURL('**/attachments/');
|
|
assert.match(await page.locator('main').innerText(), /No attachments on this page/);
|
|
await menu(source, true);
|
|
assert.equal(await downloadedBytes(), 'Synthetic attachment bytes');
|
|
await page.goto(source);
|
|
await page.getByRole('link', {name: 'Transfer', exact: true}).click();
|
|
await page.getByLabel('Destination space').selectOption('attachments-private');
|
|
await page.getByLabel('Slug in destination', {exact: false}).fill('moved');
|
|
await page.getByRole('button', {name: 'Transfer page', exact: true}).click();
|
|
await page.waitForURL('**?page=moved');
|
|
await menu(`${destination}?page=moved`, true);
|
|
assert.equal(await downloadedBytes(), 'Synthetic attachment bytes');
|
|
const movedDownload = await page.getByRole('link', {name: 'Download', exact: true}).getAttribute('href');
|
|
await login('file-reader');
|
|
assert.equal((await page.goto(source)).status(), 404);
|
|
assert.equal((await page.goto(new URL(movedDownload, base).href)).status(), 404);
|
|
assert.deepEqual(unexpected, []);
|
|
console.log('Attachment menu upload, download, independent copy, move and removal passed');
|
|
} finally {
|
|
await browser.close();
|
|
}
|