ZDDC/tests/transmittal.spec.js
2026-06-11 13:32:31 -05:00

174 lines
8.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test, expect } from '@playwright/test';
import { MOCK_FS_INIT_SCRIPT } from './fixtures/mock-fs-api.js';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
const HTML_PATH = path.resolve('transmittal/dist/transmittal.html');
// Tab-separated clipboard data simulating a paste from a document register
const PASTED_FILE_TEXT = [
'123456-EL-SPC-2623\tMaterial Specification\tA\tIFC\tpdf',
'123456-EL-SPC-2624\tInstallation Drawing\tB\tIFR\tdwg',
].join('\n');
test.describe('Transmittal pasted files survive a save/load cycle', () => {
test.beforeEach(async ({ page }) => {
await page.addInitScript(MOCK_FS_INIT_SCRIPT);
});
test('files pasted from clipboard appear after opening the saved draft', async ({ page }) => {
// ── 1. Load the app ──────────────────────────────────────────────────
await page.goto(`file://${HTML_PATH}`, { waitUntil: 'networkidle' });
// ── Wait for table tbody ──────────────────────────────────────────────
await page.waitForSelector('table tbody', { timeout: 30000 });
// ── 2. Inject pasted files directly into app state ───────────────────
// Simulates what "Paste Append Rows" does without needing real clipboard.
await page.evaluate((clipText) => {
const app = window.transmittalApp;
// Parse through the app's own paste parser
const result = app.modules.files._parseClipboardTextForTest
? app.modules.files._parseClipboardTextForTest(clipText)
: null;
// Direct injection: build the same structure columnsToFileRow produces
const rows = clipText.trim().split('\n').map(line => {
const cols = line.split('\t');
return {
trackingNumber: cols[0] || '',
title: cols[1] || '',
revision: cols[2] || '',
status: cols[3] || '',
extension: (cols[4] || '').toLowerCase(),
path: '', name: '', size: 0, fileSize: 0, sha256: ''
};
});
app.data.files = rows;
app.modules.files.updateFilesInJson(app.data.files);
app.modules.files.render();
}, PASTED_FILE_TEXT);
// Verify the files are visible in the table
const rowsBefore = await page.locator('table tbody tr').count();
// Self-entry row (row 0) + 2 pasted files
expect(rowsBefore).toBeGreaterThanOrEqual(3);
// ── 3. Sync UI to JSON and build the draft HTML ──────────────────────
const draftHtml = await page.evaluate(async () => {
const pub = window.transmittalApp.modules.publish;
await pub.syncUiToJson({ sign: false, computeDigest: false });
return pub.buildHtmlString();
});
expect(typeof draftHtml).toBe('string');
expect(draftHtml.length).toBeGreaterThan(1000);
// The draft HTML must contain the tracking numbers in the JSON block
expect(draftHtml).toContain('123456-EL-SPC-2623');
expect(draftHtml).toContain('123456-EL-SPC-2624');
// ── 4. Write the draft to a temp file and open it in a new page ──────
const tmp = path.join(os.tmpdir(), `transmittal-draft-test-${Date.now()}.html`);
fs.writeFileSync(tmp, draftHtml, 'utf8');
try {
const draftPage = await page.context().newPage();
await draftPage.addInitScript(MOCK_FS_INIT_SCRIPT);
await draftPage.goto(`file://${tmp}`);
await draftPage.waitForSelector('table tbody');
// ── 5. Assert files survived the round-trip ───────────────────────
const rowsAfter = await draftPage.locator('table tbody tr').count();
// Self-entry + 2 pasted files
expect(rowsAfter).toBeGreaterThanOrEqual(3);
// Check that the tracking numbers are visible in the table
await expect(draftPage.locator('table tbody')).toContainText('123456-EL-SPC-2623');
await expect(draftPage.locator('table tbody')).toContainText('123456-EL-SPC-2624');
// Check the in-memory data too
const appFiles = await draftPage.evaluate(() => window.transmittalApp.data.files);
expect(appFiles.length).toBe(2);
expect(appFiles[0].trackingNumber).toBe('123456-EL-SPC-2623');
expect(appFiles[1].trackingNumber).toBe('123456-EL-SPC-2624');
// Files must have usable names even though path/filename are empty
expect(appFiles[0].name).toBeTruthy();
expect(appFiles[1].name).toBeTruthy();
await draftPage.close();
} finally {
fs.unlinkSync(tmp);
}
});
test('files selected from filesystem survive a save/load cycle', async ({ page }) => {
// ── 1. Load the app ──────────────────────────────────────────────────
await page.goto(`file://${HTML_PATH}`, { waitUntil: 'networkidle' });
await page.waitForSelector('table tbody', { state: 'attached' });
await page.waitForTimeout(300);
// ── 2. Inject filesystem-style files (have real path + sha256) ───────
await page.evaluate(() => {
const app = window.transmittalApp;
app.data.files = [
{
trackingNumber: '123456-EL-SPC-0001', title: 'Spec One',
revision: 'A', status: 'IFC', extension: 'pdf',
path: 'project-dir/123456-EL-SPC-0001_A (IFC) - Spec One.pdf',
name: '123456-EL-SPC-0001_A (IFC) - Spec One.pdf',
size: 10000, fileSize: 10000,
sha256: 'aabbccddeeff001122334455667788990011223344556677889900aabbccddee'
},
{
trackingNumber: '123456-EL-DRW-0002', title: 'Drawing Two',
revision: 'B', status: 'IFR', extension: 'dwg',
path: 'project-dir/123456-EL-DRW-0002_B (IFR) - Drawing Two.dwg',
name: '123456-EL-DRW-0002_B (IFR) - Drawing Two.dwg',
size: 20000, fileSize: 20000,
sha256: 'ffeeddccbbaa998877665544332211ffeeddccbbaa998877665544332211ffee'
},
];
app.modules.files.updateFilesInJson(app.data.files);
app.modules.files.render();
});
await page.waitForTimeout(300);
const rowsBefore = await page.locator('table tbody tr').count();
expect(rowsBefore).toBeGreaterThanOrEqual(3);
// ── 3. Build the draft HTML ──────────────────────────────────────────
const draftHtml = await page.evaluate(async () => {
const pub = window.transmittalApp.modules.publish;
await pub.syncUiToJson({ sign: false, computeDigest: false });
return pub.buildHtmlString();
});
expect(draftHtml).toContain('123456-EL-SPC-0001');
expect(draftHtml).toContain('123456-EL-DRW-0002');
// ── 4. Open draft and verify ─────────────────────────────────────────
const tmp = path.join(os.tmpdir(), `transmittal-draft-fs-${Date.now()}.html`);
fs.writeFileSync(tmp, draftHtml, 'utf8');
try {
const draftPage = await page.context().newPage();
await draftPage.addInitScript(MOCK_FS_INIT_SCRIPT);
await draftPage.goto(`file://${tmp}`);
await draftPage.waitForSelector('table tbody');
const rowsAfter = await draftPage.locator('table tbody tr').count();
expect(rowsAfter).toBeGreaterThanOrEqual(3);
await expect(draftPage.locator('table tbody')).toContainText('123456-EL-SPC-0001');
await expect(draftPage.locator('table tbody')).toContainText('123456-EL-DRW-0002');
const appFiles = await draftPage.evaluate(() => window.transmittalApp.data.files);
expect(appFiles.length).toBe(2);
await draftPage.close();
} finally {
fs.unlinkSync(tmp);
}
});
});