You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.7 KiB
JavaScript
120 lines
3.7 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const test = require('node:test');
|
|
|
|
const temporaryLogs = fs.mkdtempSync(path.join(os.tmpdir(), 'photobioreactor-'));
|
|
process.env.LOGS_DIRECTORY = temporaryLogs;
|
|
|
|
const { app, HISTORY_FILES } = require('../api/server');
|
|
|
|
let server;
|
|
let baseUrl;
|
|
|
|
test.before(async () => {
|
|
await new Promise((resolve) => {
|
|
server = app.listen(0, '127.0.0.1', resolve);
|
|
});
|
|
|
|
const address = server.address();
|
|
baseUrl = `http://127.0.0.1:${address.port}`;
|
|
});
|
|
|
|
test.after(async () => {
|
|
await new Promise((resolve, reject) => {
|
|
server.close((error) => error ? reject(error) : resolve());
|
|
});
|
|
fs.rmSync(temporaryLogs, { recursive: true, force: true });
|
|
});
|
|
|
|
test('returns simulated history for all sensors', async () => {
|
|
const response = await fetch(`${baseUrl}/api/sensors/all`);
|
|
const data = await response.json();
|
|
|
|
assert.equal(response.status, 200);
|
|
assert.equal(data.length, 61);
|
|
assert.ok(data[0].Timestamp);
|
|
assert.ok(data[0].Temperatura_C);
|
|
});
|
|
|
|
test('serves the dashboard in local development mode', async () => {
|
|
const response = await fetch(`${baseUrl}/`);
|
|
const html = await response.text();
|
|
|
|
assert.equal(response.status, 200);
|
|
assert.match(html, /Panel del Fotobiorreactor/);
|
|
});
|
|
|
|
test('validates sensor commands', async () => {
|
|
const invalidResponse = await fetch(`${baseUrl}/api/sensors/invalid/command`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ command: 'r' })
|
|
});
|
|
assert.equal(invalidResponse.status, 400);
|
|
|
|
const validResponse = await fetch(`${baseUrl}/api/sensors/ph/command`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ command: 'r' })
|
|
});
|
|
const validData = await validResponse.json();
|
|
|
|
assert.equal(validResponse.status, 200);
|
|
assert.equal(validData.success, true);
|
|
assert.equal(validData.mode, 'demo');
|
|
});
|
|
|
|
test('rejects undocumented calibration syntax', async () => {
|
|
const response = await fetch(`${baseUrl}/api/sensors/do/command`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ command: 'Cal,atm' })
|
|
});
|
|
const data = await response.json();
|
|
|
|
assert.equal(response.status, 400);
|
|
assert.match(data.error, /documentados/);
|
|
});
|
|
|
|
test('validates simulated logging rates', async () => {
|
|
const invalidResponse = await fetch(`${baseUrl}/api/config/logging`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ rate: 3 })
|
|
});
|
|
assert.equal(invalidResponse.status, 400);
|
|
|
|
const validResponse = await fetch(`${baseUrl}/api/config/logging`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ rate: 5 })
|
|
});
|
|
const validData = await validResponse.json();
|
|
|
|
assert.equal(validResponse.status, 200);
|
|
assert.equal(validData.rate, 5);
|
|
assert.equal(validData.simulated, true);
|
|
});
|
|
|
|
test('clears historical CSV files and preserves headers', async () => {
|
|
for (const name of Object.keys(HISTORY_FILES)) {
|
|
fs.writeFileSync(path.join(temporaryLogs, `${name}.csv`), 'old,data\n1,2\n');
|
|
}
|
|
|
|
const response = await fetch(`${baseUrl}/api/history/clear`, {
|
|
method: 'POST'
|
|
});
|
|
|
|
assert.equal(response.status, 200);
|
|
|
|
for (const [name, header] of Object.entries(HISTORY_FILES)) {
|
|
const content = fs.readFileSync(
|
|
path.join(temporaryLogs, `${name}.csv`),
|
|
'utf8'
|
|
);
|
|
assert.equal(content, header);
|
|
}
|
|
});
|