[Maintenance] improve testing utils and add delete-user-file test (#421)

* improve testing utils and add delete-user-file test

* remove linting errors

* add release notes

* match npm scripts naming style

Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk>

* add raw middleware for /sync

---------

Co-authored-by: Matt Fiddaman <github@m.fiddaman.uk>
This commit is contained in:
Tom Crasset
2024-08-15 18:52:39 +02:00
committed by GitHub
parent a879960a2d
commit baf04a4d48
5 changed files with 103 additions and 4 deletions

View File

@@ -9,6 +9,10 @@
"lint": "eslint . --max-warnings 0",
"build": "tsc",
"test": "NODE_ENV=test NODE_OPTIONS='--experimental-vm-modules --trace-warnings' jest --coverage",
"db:migrate": "NODE_ENV=development node src/run-migrations.js up",
"db:downgrade": "NODE_ENV=development node src/run-migrations.js down",
"db:test-migrate": "NODE_ENV=test node src/run-migrations.js up",
"db:test-downgrade": "NODE_ENV=test node src/run-migrations.js down",
"types": "tsc --noEmit --incremental",
"verify": "yarn lint && yarn types",
"reset-password": "node src/scripts/reset-password.js",

View File

@@ -13,8 +13,13 @@ import { SyncProtoBuf } from '@actual-app/crdt';
const app = express();
app.use(errorMiddleware);
app.use(express.json());
app.use(express.raw({ type: 'application/actual-sync' }));
export { app as handlers };
const OK_RESPONSE = { status: 'ok' };
// This is a version representing the internal format of sync
// messages. When this changes, all sync files need to be reset. We
// will check this version when syncing and notify the user if they
@@ -160,7 +165,7 @@ app.post('/user-create-key', (req, res) => {
[keySalt, keyId, testContent, fileId],
);
res.send(JSON.stringify({ status: 'ok' }));
res.send(OK_RESPONSE);
});
app.post('/reset-user-file', async (req, res) => {
@@ -190,7 +195,7 @@ app.post('/reset-user-file', async (req, res) => {
}
}
res.send(JSON.stringify({ status: 'ok' }));
res.send(OK_RESPONSE);
});
app.post('/upload-user-file', async (req, res) => {
@@ -333,7 +338,7 @@ app.post('/update-user-filename', (req, res) => {
accountDb.mutate('UPDATE files SET name = ? WHERE id = ?', [name, fileId]);
res.send(JSON.stringify({ status: 'ok' }));
res.send(OK_RESPONSE);
});
app.get('/list-user-files', (req, res) => {
@@ -399,6 +404,20 @@ app.post('/delete-user-file', (req, res) => {
let accountDb = getAccountDb();
let { fileId } = req.body;
if (!fileId) {
return res.status(422).send({
details: 'fileId-required',
reason: 'unprocessable-entity',
status: 'error',
});
}
let rows = accountDb.all('SELECT * FROM files WHERE id = ?', [fileId]);
if (rows.length === 0) {
return res.status(400).send('file-not-found');
}
accountDb.mutate('UPDATE files SET deleted = TRUE WHERE id = ?', [fileId]);
res.send(JSON.stringify({ status: 'ok' }));
res.send(OK_RESPONSE);
});

View File

@@ -75,3 +75,65 @@ describe('/download-user-file', () => {
});
});
});
describe('/delete-user-file', () => {
it('returns 401 if the user is not authenticated', async () => {
const res = await request(app).post('/delete-user-file');
expect(res.statusCode).toEqual(401);
expect(res.body).toEqual({
details: 'token-not-found',
reason: 'unauthorized',
status: 'error',
});
});
// it returns 422 if the fileId is not provided
it('returns 422 if the fileId is not provided', async () => {
const res = await request(app)
.post('/delete-user-file')
.set('x-actual-token', 'valid-token');
expect(res.statusCode).toEqual(422);
expect(res.body).toEqual({
details: 'fileId-required',
reason: 'unprocessable-entity',
status: 'error',
});
});
it('returns 400 if the file does not exist', async () => {
const res = await request(app)
.post('/delete-user-file')
.set('x-actual-token', 'valid-token')
.send({ fileId: 'non-existing-file-id' });
expect(res.statusCode).toEqual(400);
expect(res.text).toEqual('file-not-found');
});
it('marks the file as deleted', async () => {
const accountDb = getAccountDb();
const fileId = 'existing-file-id';
// Insert a file into the database
accountDb.mutate(
'INSERT OR IGNORE INTO files (id, deleted) VALUES (?, FALSE)',
[fileId],
);
const res = await request(app)
.post('/delete-user-file')
.set('x-actual-token', 'valid-token')
.send({ fileId });
expect(res.statusCode).toEqual(200);
expect(res.body).toEqual({ status: 'ok' });
// Verify that the file is marked as deleted
const rows = accountDb.all('SELECT deleted FROM files WHERE id = ?', [
fileId,
]);
expect(rows[0].deleted).toBe(1);
});
});

8
src/run-migrations.js Normal file
View File

@@ -0,0 +1,8 @@
import run from './migrations.js';
const direction = process.argv[2] || 'up';
run(direction).catch((err) => {
console.error('Migration failed:', err);
process.exit(1);
});

View File

@@ -0,0 +1,6 @@
---
category: Maintenance
authors: [tcrasset]
---
Improve testing utils and add delete-user-file test