From ff444cbb21971098bf46192191282e8de74b64b2 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Tue, 9 Apr 2024 19:29:00 +0200 Subject: [PATCH] prep --- lib/handlers/get.js | 5 +- lib/handlers/patch.js | 1 + test/integration/prep-test.js | 131 ++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 test/integration/prep-test.js diff --git a/lib/handlers/get.js b/lib/handlers/get.js index cdf06e42..04b5e3f5 100644 --- a/lib/handlers/get.js +++ b/lib/handlers/get.js @@ -136,11 +136,12 @@ async function handler (req, res, next) { res.statusCode = 206 } - if (isRdf(contentType) && !res.sendEvents({ + // PREP response + /* if (isRdf(contentType) && !res.sendEvents({ config: { prep: '' }, body: stream, headers - })) return + })) return */ res.set(headers) return stream.pipe(res) } diff --git a/lib/handlers/patch.js b/lib/handlers/patch.js index d78cf6d8..307cac6f 100644 --- a/lib/handlers/patch.js +++ b/lib/handlers/patch.js @@ -96,6 +96,7 @@ async function patchHandler (req, res, next) { // Send the result to the client res.send(result) + // PREP response res.events.prep.trigger({ generateNotifications: () => `\r\n${rfc822Template({ res })}` }) diff --git a/test/integration/prep-test.js b/test/integration/prep-test.js new file mode 100644 index 00000000..2ea2d9f4 --- /dev/null +++ b/test/integration/prep-test.js @@ -0,0 +1,131 @@ +// Integration tests for PATCH with text/n3 +const { assert } = require('chai') +const ldnode = require('../../index') +const path = require('path') +const supertest = require('supertest') +const fs = require('fs') +const { read, rm, backup, restore } = require('../utils') + +// Server settings +const port = 7777 +const serverUri = `https://tim.localhost:${port}` +const root = path.join(__dirname, '../resources/patch') +const configPath = path.join(__dirname, '../resources/config') +const serverOptions = { + root, + configPath, + serverUri, + multiuser: false, + webid: true, + sslKey: path.join(__dirname, '../keys/key.pem'), + sslCert: path.join(__dirname, '../keys/cert.pem'), + forceUser: `${serverUri}/profile/card#me` +} + +describe('PATCH through text/n3', () => { + let request + let server + + // Start the server + before(done => { + server = ldnode.createServer(serverOptions) + server.listen(port, done) + request = supertest(serverUri) + }) + + after(() => { + server.close() + }) + + describe('with a patch document', () => { + describe('on a resource with append-only access', describePatch({ + path: '/append-only.ttl', + patch: `<> a solid:InsertDeletePatch; + solid:inserts { . }.` + }, { // expected: + status: 200, + text: 'Patch applied successfully', + result: '@prefix : .\n@prefix tim: .\n\ntim:a tim:b tim:c.\n\ntim:d tim:e tim:f.\n\ntim:x tim:y tim:z.\n\n' + })) + + describe('on a resource with write-only access', describePatch({ + path: '/write-only.ttl', + patch: `<> a solid:InsertDeletePatch; + solid:inserts { . }.` + }, { // expected: + status: 200, + text: 'Patch applied successfully', + result: '@prefix : .\n@prefix tim: .\n\ntim:a tim:b tim:c.\n\ntim:d tim:e tim:f.\n\ntim:x tim:y tim:z.\n\n' + })) + }) + + // Creates a PATCH test for the given resource with the given expected outcomes + function describePatch ({ path, exists = true, patch, contentType = 'text/n3' }, + { status = 200, text, result }) { + return () => { + const filename = `patch${path}` + let originalContents + // Back up and restore an existing file + if (exists) { + before(() => backup(filename)) + after(() => restore(filename)) + // Store its contents to verify non-modification + if (!result) { + originalContents = read(filename) + } + // Ensure a non-existing file is removed + } else { + before(() => rm(filename)) + after(() => rm(filename)) + } + + // Create the request and obtain the response + let response + before((done) => { + request.patch(path) + .set('Content-Type', contentType) + .send(`@prefix solid: .\n${patch}`) + .then(res => { response = res }) + .then(done, done) + }) + + // Verify the response's status code and body text + it(`returns HTTP status code ${status}`, () => { + assert.isObject(response) + assert.equal(response.statusCode, status) + }) + it(`has "${text}" in the response`, () => { + assert.isObject(response) + assert.include(response.text, text) + }) + + // For existing files, verify correct patch application + if (exists) { + if (result) { + it('patches the file correctly', () => { + assert.equal(read(filename), result) + }) + } else { + it('does not modify the file', () => { + assert.equal(read(filename), originalContents) + }) + } + // For non-existing files, verify creation and contents + } else { + if (result) { + it('creates the file', () => { + assert.isTrue(fs.existsSync(`${root}/${path}`)) + }) + + it('writes the correct contents', () => { + assert.equal(read(filename), result) + }) + } else { + it('does not create the file', () => { + assert.isFalse(fs.existsSync(`${root}/${path}`)) + }) + } + } + } + } +})