diff --git a/editions/test/playwright.spec.js b/editions/test/playwright.spec.js index 1d8c624c7..526d7541a 100644 --- a/editions/test/playwright.spec.js +++ b/editions/test/playwright.spec.js @@ -12,9 +12,9 @@ test('get started link', async ({ page }) => { // Load the generated test TW html await page.goto(`file:///${crossPlatformIndexPath}`); - + const title = await page.title(); // Sanity check - await expect(page.locator('.tc-site-title'), "Expected correct page title to verify the test page was loaded").toHaveText('TiddlyWiki5'); + await expect(title, "Expected correct page title to verify the test page was loaded").toContain('TiddlyWiki5'); // Wait for jasmine results bar to appear await expect(page.locator('.jasmine-overall-result'), "Expected jasmine test results bar to be present").toBeVisible({timeout}); diff --git a/package-lock.json b/package-lock.json index 3532bc512..b83166c5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,10 @@ "version": "5.3.6-prerelease", "license": "BSD", "dependencies": { + "@playwright/test": "^1.46.1", "better-sqlite3": "^9.4.3", - "node-sqlite3-wasm": "^0.8.10" + "node-sqlite3-wasm": "^0.8.10", + "playwright": "^1.46.1" }, "bin": { "tiddlywiki": "tiddlywiki.js" @@ -174,6 +176,20 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@playwright/test": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.1.tgz", + "integrity": "sha512-Fq6SwLujA/DOIvNC2EL/SojJnkKf/rAwJ//APpJJHRyMi1PdKrY3Az+4XNQ51N4RTbItbIByQ0jgd1tayq1aeA==", + "dependencies": { + "playwright": "1.46.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -793,6 +809,19 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -1175,6 +1204,34 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", + "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", + "dependencies": { + "playwright-core": "1.46.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", + "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", diff --git a/package.json b/package.json index 063445b27..41c6c5e6a 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,9 @@ "lint": "eslint ." }, "dependencies": { + "@playwright/test": "^1.46.1", "better-sqlite3": "^9.4.3", - "node-sqlite3-wasm": "^0.8.10" + "node-sqlite3-wasm": "^0.8.10", + "playwright": "^1.46.1" } } diff --git a/plugins/tiddlywiki/multiwikiserver/modules/tests/test-attachment.js b/plugins/tiddlywiki/multiwikiserver/modules/tests/test-attachment.js index 6198d9606..69eafca6f 100644 --- a/plugins/tiddlywiki/multiwikiserver/modules/tests/test-attachment.js +++ b/plugins/tiddlywiki/multiwikiserver/modules/tests/test-attachment.js @@ -6,170 +6,176 @@ tags: [[$:/tags/test-spec]] Tests attachments. \*/ -var fs = require('fs'); -var path = require('path'); -var assert = require('assert'); -var AttachmentStore = require('$:/plugins/tiddlywiki/multiwikiserver/store/attachments.js').AttachmentStore; -const {Buffer} = require('buffer'); +if(typeof window === 'undefined' && typeof process !== 'undefined' && process.versions && process.versions.node) { + var fs = require('fs'); + var path = require('path'); + var assert = require('assert'); + var AttachmentStore = require('$:/plugins/tiddlywiki/multiwikiserver/store/attachments.js').AttachmentStore; + const {Buffer} = require('buffer'); -function generateFileWithSize(filePath, sizeInBytes) { - return new Promise((resolve, reject) => { - var buffer = Buffer.alloc(sizeInBytes); - for(var i = 0; i < sizeInBytes; i++) { - buffer[i] = Math.floor(Math.random() * 256); - } - - fs.writeFile(filePath, buffer, (err) => { - if(err) { - console.error('Error writing file:', err); - reject(err); - } else { - console.log('File '+filePath+' generated with size '+sizeInBytes+' bytes'); - fs.readFile(filePath, (err, data) => { - if(err) { - console.error('Error reading file:', err); - reject(err); - } else { - resolve(data); - } - }); + function generateFileWithSize(filePath, sizeInBytes) { + return new Promise((resolve, reject) => { + var buffer = Buffer.alloc(sizeInBytes); + for(var i = 0; i < sizeInBytes; i++) { + buffer[i] = Math.floor(Math.random() * 256); } - }); - }); -} -(function() { -'use strict'; -if($tw.node) { - describe('AttachmentStore', function() { - var storePath = './editions/test/test-store'; - var attachmentStore = new AttachmentStore({ storePath: storePath }); - var originalTimeout; - - beforeAll(function() { - originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; - jasmine.DEFAULT_TIMEOUT_INTERVAL = 50000; - }); - - afterAll(function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; - fs.readdirSync(storePath).forEach(function(file) { - var filePath = path.join(storePath, file); - if(fs.lstatSync(filePath).isFile()) { - fs.unlinkSync(filePath); - } else if(fs.lstatSync(filePath).isDirectory()) { - fs.rmdirSync(filePath, { recursive: true }); + fs.writeFile(filePath, buffer, (err) => { + if(err) { + console.error('Error writing file:', err); + reject(err); + } else { + console.log('File '+filePath+' generated with size '+sizeInBytes+' bytes'); + fs.readFile(filePath, (err, data) => { + if(err) { + console.error('Error reading file:', err); + reject(err); + } else { + resolve(data); + } + }); } }); }); + } - it('isValidAttachmentName', function() { - expect(attachmentStore.isValidAttachmentName('abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890')).toBe(true); - expect(attachmentStore.isValidAttachmentName('invalid-name')).toBe(false); - }); + (function() { + 'use strict'; + if($tw.node) { + describe('AttachmentStore', function() { + var storePath = './editions/test/test-store'; + var attachmentStore = new AttachmentStore({ storePath: storePath }); + var originalTimeout; - it('saveAttachment', function() { - var options = { - text: 'Hello, World!', - type: 'text/plain', - reference: 'test-reference', - }; - var contentHash = attachmentStore.saveAttachment(options); - assert.strictEqual(contentHash.length, 64); - assert.strictEqual(fs.existsSync(path.resolve(storePath, 'files', contentHash)), true); - }); - - it('adoptAttachment', function() { - var incomingFilepath = path.resolve(storePath, 'incoming-file.txt'); - fs.writeFileSync(incomingFilepath, 'Hello, World!'); - var type = 'text/plain'; - var hash = 'abcdef0123456789abcdef0123456789'; - var _canonical_uri = 'test-canonical-uri'; - attachmentStore.adoptAttachment(incomingFilepath, type, hash, _canonical_uri); - expect(fs.existsSync(path.resolve(storePath, 'files', hash))).toBe(true); - }); - - it('getAttachmentStream', function() { - var options = { - text: 'Hello, World!', - type: 'text/plain', - filename: 'data.txt', - }; - var contentHash = attachmentStore.saveAttachment(options); - var stream = attachmentStore.getAttachmentStream(contentHash); - expect(stream).not.toBeNull(); - expect(stream.type).toBe('text/plain'); - }); + beforeAll(function() { + const dirPath = path.dirname(`${storePath}/files`); + if(!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } + originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; + jasmine.DEFAULT_TIMEOUT_INTERVAL = 50000; + }); - it('getAttachmentFileSize', function() { - var options = { - text: 'Hello, World!', - type: 'text/plain', - reference: 'test-reference', - }; - var contentHash = attachmentStore.saveAttachment(options); - var fileSize = attachmentStore.getAttachmentFileSize(contentHash); - expect(fileSize).toBe(13); - }); + afterAll(function() { + jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; + fs.readdirSync(storePath).forEach(function(file) { + var filePath = path.join(storePath, file); + if(fs.lstatSync(filePath).isFile()) { + fs.unlinkSync(filePath); + } else if(fs.lstatSync(filePath).isDirectory()) { + fs.rmdirSync(filePath, { recursive: true }); + } + }); + }); - it('getAttachmentMetadata', function() { - var options = { - text: 'Hello, World!', - type: 'text/plain', - filename: 'data.txt', - }; - var contentHash = attachmentStore.saveAttachment(options); - var metadata = attachmentStore.getAttachmentMetadata(contentHash); - expect(metadata).not.toBeNull(); - expect(metadata.type).toBe('text/plain'); - expect(metadata.filename).toBe('data.txt'); - }); + it('isValidAttachmentName', function() { + expect(attachmentStore.isValidAttachmentName('abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890')).toBe(true); + expect(attachmentStore.isValidAttachmentName('invalid-name')).toBe(false); + }); - it('saveAttachment large file', async function() { - var sizeInMB = 10 - const file = await generateFileWithSize('./editions/test/test-store/large-file.txt', 1024 * 1024 * sizeInMB) - var options = { - text: file, - type: 'application/octet-stream', - reference: 'test-reference', - }; - var contentHash = attachmentStore.saveAttachment(options); - assert.strictEqual(contentHash.length, 64); - assert.strictEqual(fs.existsSync(path.resolve(storePath, 'files', contentHash)), true); - }); - - it('saveAttachment multiple large files', async function() { - var sizeInMB = 10; - var numFiles = 5; - for (var i = 0; i < numFiles; i++) { - const file = await generateFileWithSize(`./editions/test/test-store/large-file-${i}.txt`, 1024 * 1024 * sizeInMB); + it('saveAttachment', function() { var options = { - text: file, - type: 'application/octet-stream', - reference: `test-reference-${i}`, + text: 'Hello, World!', + type: 'text/plain', + reference: 'test-reference', }; var contentHash = attachmentStore.saveAttachment(options); assert.strictEqual(contentHash.length, 64); assert.strictEqual(fs.existsSync(path.resolve(storePath, 'files', contentHash)), true); - } - }); - - it('getAttachmentStream multiple large files', async function() { - var sizeInMB = 10; - var numFiles = 5; - for (var i = 0; i < numFiles; i++) { - const file = await generateFileWithSize(`./editions/test/test-store/large-file-${i}.txt`, 1024 * 1024 * sizeInMB); + }); + + it('adoptAttachment', function() { + var incomingFilepath = path.resolve(storePath, 'incoming-file.txt'); + fs.writeFileSync(incomingFilepath, 'Hello, World!'); + var type = 'text/plain'; + var hash = 'abcdef0123456789abcdef0123456789'; + var _canonical_uri = 'test-canonical-uri'; + attachmentStore.adoptAttachment(incomingFilepath, type, hash, _canonical_uri); + expect(fs.existsSync(path.resolve(storePath, 'files', hash))).toBe(true); + }); + + it('getAttachmentStream', function() { var options = { - text: file, - type: 'application/octet-stream', - reference: `test-reference-${i}`, + text: 'Hello, World!', + type: 'text/plain', + filename: 'data.txt', }; var contentHash = attachmentStore.saveAttachment(options); var stream = attachmentStore.getAttachmentStream(contentHash); - assert.notStrictEqual(stream, null); - assert.strictEqual(stream.type, 'application/octet-stream'); - } + expect(stream).not.toBeNull(); + expect(stream.type).toBe('text/plain'); + }); + + it('getAttachmentFileSize', function() { + var options = { + text: 'Hello, World!', + type: 'text/plain', + reference: 'test-reference', + }; + var contentHash = attachmentStore.saveAttachment(options); + var fileSize = attachmentStore.getAttachmentFileSize(contentHash); + expect(fileSize).toBe(13); + }); + + it('getAttachmentMetadata', function() { + var options = { + text: 'Hello, World!', + type: 'text/plain', + filename: 'data.txt', + }; + var contentHash = attachmentStore.saveAttachment(options); + var metadata = attachmentStore.getAttachmentMetadata(contentHash); + expect(metadata).not.toBeNull(); + expect(metadata.type).toBe('text/plain'); + expect(metadata.filename).toBe('data.txt'); + }); + + it('saveAttachment large file', async function() { + var sizeInMB = 10 + const file = await generateFileWithSize('./editions/test/test-store/large-file.txt', 1024 * 1024 * sizeInMB) + var options = { + text: file, + type: 'application/octet-stream', + reference: 'test-reference', + }; + var contentHash = attachmentStore.saveAttachment(options); + assert.strictEqual(contentHash.length, 64); + assert.strictEqual(fs.existsSync(path.resolve(storePath, 'files', contentHash)), true); + }); + + it('saveAttachment multiple large files', async function() { + var sizeInMB = 10; + var numFiles = 5; + for (var i = 0; i < numFiles; i++) { + const file = await generateFileWithSize(`./editions/test/test-store/large-file-${i}.txt`, 1024 * 1024 * sizeInMB); + var options = { + text: file, + type: 'application/octet-stream', + reference: `test-reference-${i}`, + }; + var contentHash = attachmentStore.saveAttachment(options); + assert.strictEqual(contentHash.length, 64); + assert.strictEqual(fs.existsSync(path.resolve(storePath, 'files', contentHash)), true); + } + }); + + it('getAttachmentStream multiple large files', async function() { + var sizeInMB = 10; + var numFiles = 5; + for (var i = 0; i < numFiles; i++) { + const file = await generateFileWithSize(`./editions/test/test-store/large-file-${i}.txt`, 1024 * 1024 * sizeInMB); + var options = { + text: file, + type: 'application/octet-stream', + reference: `test-reference-${i}`, + }; + var contentHash = attachmentStore.saveAttachment(options); + var stream = attachmentStore.getAttachmentStream(contentHash); + assert.notStrictEqual(stream, null); + assert.strictEqual(stream.type, 'application/octet-stream'); + } + }); }); - }); + } + })(); } -})();