diff --git a/package-lock.json b/package-lock.json index 6ce7e1c88..f4278517d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -96,6 +96,7 @@ "@types/sinon": "^17.0.4", "axios": "^1.12.2", "chai": "^6.2.0", + "@types/tar-fs": "^2.0.4", "eslint": "^9.36.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.2", @@ -106,7 +107,8 @@ "supertest": "^7.1.4", "tsx": "^4.20.6", "typescript": "^5.7.3", - "typescript-eslint": "^8.45.0" + "typescript-eslint": "^8.45.0", + "undici": "^7.16.0" }, "engines": { "minimum-node": "20.0.0", @@ -3638,6 +3640,27 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/tar-fs": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/tar-fs/-/tar-fs-2.0.4.tgz", + "integrity": "sha512-ipPec0CjTmVDWE+QKr9cTmIIoTl7dFG/yARCM5MqK8i6CNLIG1P8x4kwDsOQY1ChZOZjH0wO9nvfgBvWl4R3kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tar-stream": "*" + } + }, + "node_modules/@types/tar-stream": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/tar-stream/-/tar-stream-3.1.4.tgz", + "integrity": "sha512-921gW0+g29mCJX0fRvqeHzBlE/XclDaAG0Ousy1LCghsOhvaKacDeRGEVzQP9IPfKn8Vysy7FEXAIxycpc/CMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.45.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.45.0.tgz", @@ -9775,6 +9798,16 @@ "layerr": "^0.1.2" } }, + "node_modules/undici": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", + "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", diff --git a/package.json b/package.json index a1985c4e2..7880e80fc 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "format:check": "prettier --check .", "format:write": "prettier --write .", "test:integration": "node --test integrationTests/apiTests/tests/testSuite.mjs", - "test:unit": "npm run build || true; npx mocha unitTests --config unitTests/.mocharc.json" + "test:unit": "npm run build || true; npx mocha unitTests --config unitTests/.mocharc.json", + "test:static-plugin-integration": "node --test test/staticPluginIntegrationTests/testSuite.test.mts" }, "engines": { "node": ">=20", @@ -61,6 +62,7 @@ "@types/sinon": "^17.0.4", "axios": "^1.12.2", "chai": "^6.2.0", + "@types/tar-fs": "^2.0.4", "eslint": "^9.36.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.2", @@ -71,7 +73,8 @@ "supertest": "^7.1.4", "tsx": "^4.20.6", "typescript": "^5.7.3", - "typescript-eslint": "^8.45.0" + "typescript-eslint": "^8.45.0", + "undici": "^7.16.0" }, "dependencies": { "@aws-sdk/client-s3": "3.824.0", diff --git a/test/staticPluginIntegrationTests/fixtures/defaultConfig/defaultConfig.test.mts b/test/staticPluginIntegrationTests/fixtures/defaultConfig/defaultConfig.test.mts new file mode 100644 index 000000000..1c25f9b4f --- /dev/null +++ b/test/staticPluginIntegrationTests/fixtures/defaultConfig/defaultConfig.test.mts @@ -0,0 +1,69 @@ +import { request } from 'undici'; +import { suite, test, before, after } from 'node:test'; +import assert from 'node:assert/strict'; +import { join } from 'node:path'; +import { pack } from 'tar-fs'; +import { createGzip } from 'node:zlib'; +import { setTimeout as sleep } from 'node:timers/promises'; + +async function packFixture(): Promise { + const fixturePath = join(import.meta.dirname, 'fixture'); + const chunks: Buffer[] = []; + return new Promise((resolve, reject) => { + pack(fixturePath) + .pipe(createGzip()) + .on('data', (chunk: Buffer) => chunks.push(chunk)) + .on('end', () => { + resolve(Buffer.concat(chunks).toString('base64')); + }) + .on('error', reject); + }); +} + +async function dropFixture() { + const { statusCode, body } = await request('http://localhost:9925', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + operation: 'drop_component', + project: 'static-plugin-defaults' + }) + }); + assert.equal(statusCode, 200, `Failed to remove application: ${await body.text()}`); +} + +void suite('Static Plugin - Defaults', async () => { + before(async () => { + await dropFixture(); + const payload = await packFixture(); + const { statusCode, body } = await request('http://localhost:9925', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + operation: 'deploy_component', + project: 'static-plugin-defaults', + payload, + restart: true + }) + }); + assert.equal(statusCode, 200, `Failed to deploy application: ${await body.text()}`); + await sleep(1000); + }); + + after(async () => { + await dropFixture(); + }); + + await test('can access Harper instance', async () => { + const { statusCode, body } = await request('http://localhost:9925/health'); + assert.equal(statusCode, 200); + const responseBody = await body.text(); + assert.equal(responseBody, 'HarperDB is running.'); + }); + + void test('can access index path', async () => { + const { statusCode, body, headers } = await request('http://localhost:9926/'); + assert.equal(statusCode, 200); + assert.ok(headers['content-type'].includes('text/html')); + }); +}); \ No newline at end of file diff --git a/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/config.yaml b/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/config.yaml new file mode 100644 index 000000000..5cc2a2f13 --- /dev/null +++ b/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/config.yaml @@ -0,0 +1,2 @@ +static: + files: 'static/**/*' \ No newline at end of file diff --git a/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/package.json b/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/package.json new file mode 100644 index 000000000..b697b7abd --- /dev/null +++ b/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/package.json @@ -0,0 +1,5 @@ +{ + "name": "static-plugin-integration-tests-fixture", + "version": "1.0.0", + "private": true +} \ No newline at end of file diff --git a/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/static/index.html b/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/static/index.html new file mode 100644 index 000000000..f5553a9f1 --- /dev/null +++ b/test/staticPluginIntegrationTests/fixtures/defaultConfig/fixture/static/index.html @@ -0,0 +1,9 @@ + + + + Root HTML File + + +

Harper!

+ + \ No newline at end of file diff --git a/test/staticPluginIntegrationTests/tsconfig.json b/test/staticPluginIntegrationTests/tsconfig.json new file mode 100644 index 000000000..32709d792 --- /dev/null +++ b/test/staticPluginIntegrationTests/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "**/*.mts", + ] +} \ No newline at end of file