Files
AgrarmonitorConnector/test/session-detection.test.js
bjoernpoettkerandClaude Opus 5 b844b772b8 Detect expired session only via login page markup
The session check treated any response containing "Anmeldung" or
"Einloggen" as an expired session. Regular content pages (e.g. the FAQ)
mention these words in body text, which triggered a needless re-login and
returned the login page instead of the requested content.

Detection now relies on the status code and isLoginPageText() alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 17:36:05 +02:00

110 lines
3.0 KiB
JavaScript

const assert = require('node:assert/strict');
const http = require('node:http');
const test = require('node:test');
const { AgrarmonitorConnector, MemoryCookieStore } = require('../dist');
const loginPage = `
<html>
<head><title>Anmeldung - AGRARMONITOR</title></head>
<body>
<form>
<input name="nonce" value="test-nonce" />
<button>Einloggen</button>
</form>
</body>
</html>
`;
// Regulaere Inhaltsseite einer gueltigen Session, die die Woerter "Anmeldung"
// und "Einloggen" im Fliesstext enthaelt - z. B. die FAQ-Seite.
const faqPage = `
<html>
<head><title>FAQ - AGRARMONITOR</title></head>
<body>
<h2>Haeufige Fragen</h2>
<p>Wie aendere ich mein Passwort fuer die Anmeldung?</p>
<p>Warum kann ich mich nicht Einloggen?</p>
</body>
</html>
`;
function createServer() {
let loggedIn = false;
const requests = [];
const server = http.createServer((req, res) => {
requests.push({ method: req.method, url: req.url });
if (req.method === 'GET' && req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(loggedIn ? '<html><body>Mein AM</body></html>' : loginPage);
return;
}
if (req.method === 'GET' && req.url === '/faq') {
if (!loggedIn) {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(loginPage);
return;
}
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(faqPage);
return;
}
if (req.method === 'POST' && req.url === '/login/api/login.php') {
let body = '';
req.on('data', chunk => {
body += chunk;
});
req.on('end', () => {
loggedIn = true;
res.writeHead(200, {
'Content-Type': 'application/json',
'Set-Cookie': 'agrar_session=test; Path=/',
});
res.end(JSON.stringify({ success: true }));
});
return;
}
res.writeHead(404);
res.end('not found');
});
return { server, requests };
}
test('content pages mentioning Anmeldung do not count as expired session', async t => {
const { server, requests } = createServer();
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
t.after(() => new Promise(resolve => server.close(resolve)));
const baseUrl = `http://127.0.0.1:${server.address().port}`;
const connector = new AgrarmonitorConnector({
baseUrl,
username: 'demo',
password: 'secret',
cookieStore: new MemoryCookieStore(),
});
await connector.init();
const loginsAfterInit = requests.filter(request => request.url === '/login/api/login.php').length;
assert.equal(loginsAfterInit, 1, 'init soll genau einmal einloggen');
const response = await connector.http.get('/faq');
assert.equal(response.status, 200);
assert.match(response.data, /Haeufige Fragen/);
assert.equal(
requests.filter(request => request.url === '/login/api/login.php').length,
loginsAfterInit,
'gueltige Inhaltsseite darf keinen erneuten Login ausloesen'
);
});