Push-Zeitmail: Review-Fixes (Rate-Limit begrenzt, kein NaN-Datum, Störung ≠ gelöscht)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-09-30 13:46:04 +00:00
1 parent 7d4767a137
commit 6643283c6f
4 files changed
+104 -21

No files matched your search

+15
View File
@@ -17,6 +17,7 @@ before(async () => {
openGit('ws1'),
openGit('ws-race'),
{ $id: 'remote1', serviceType: 'Remote', startTime: '', totalTime: 0 },
{ ...openGit('broken'), endDate: '', endTime: 'xx' },
],
},
})
@@ -72,3 +73,17 @@ test('gleichzeitig: nur einer speichert', async () => {
const results = await Promise.all([applyPushTime('ws-race', 30), applyPushTime('ws-race', 90)])
assert.deepEqual(results.map((r) => r.status).sort(), ['already', 'saved'])
})
test('kaputtes Push-Datum: nichts speichern (Review-Fix)', async () => {
assert.equal(startFromEnd('', '', 30), null)
assert.equal(startFromEnd('30.09.2026', '16:46', 30), null)
assert.equal(startFromEnd('31.02.2026', '1646', 30), null)
assert.equal((await applyPushTime('broken', 30)).status, 'invalid')
const ws = fake.get('worksheets', 'broken')
assert.deepEqual([ws.startTime, ws.totalTime, ws.isComment], ['', 0, true])
})
test('Appwrite-Störung ist nicht „missing“ (Review-Fix)', async () => {
fake.failNext({ method: 'GET', pathIncludes: '/documents/ws-race', status: 500 })
await assert.rejects(applyPushTime('ws-race', 30))
})
+23
View File
@@ -8,6 +8,8 @@ let server
let baseUrl
let createPushTimeToken
let resetPushTimeRateLimitForTests
let isRateLimited
let rateLimitSize
const gitSheet = (id, extra = {}) => ({
$id: id, wsid: '100300', woid: '100118', workorderId: 't1', serviceType: 'GIT',
@@ -38,6 +40,8 @@ before(async () => {
})
const routes = await import('../server/routes/pushTime.js')
resetPushTimeRateLimitForTests = routes.resetPushTimeRateLimitForTests
isRateLimited = routes.isRateLimited
rateLimitSize = routes.pushTimeRateLimitSizeForTests
;({ createPushTimeToken } = await import('../server/services/pushTimeToken.js'))
const app = express()
@@ -159,3 +163,22 @@ test('Rate-Limit: 31. Anfrage → 429', async () => {
assert.equal(r.status, 429)
assert.match(r.html, /Zu viele Anfragen/)
})
test('Rate-Limit-Speicher bleibt begrenzt (Review-Fix)', () => {
const now = Date.now()
for (let i = 0; i < 12000; i += 1) isRateLimited(`10.0.${Math.floor(i / 250)}.${i % 250}`, now)
assert.ok(rateLimitSize() <= 10000, `Größe ${rateLimitSize()}`)
// nach Ablauf des Fensters wird aufgeräumt
isRateLimited('10.9.9.9', now + 16 * 60 * 1000)
assert.equal(rateLimitSize(), 1)
})
test('Appwrite-Störung: neutrale HTML-Seite statt „Nicht mehr vorhanden“ (Review-Fix)', async () => {
const t = token('open1')
fake.failNext({ method: 'GET', pathIncludes: '/documents/open1', status: 500 })
const r = await get(`/zeit/${t}`)
assert.equal(r.status, 503)
assert.match(r.headers.get('content-type'), /text\/html/)
assert.match(r.html, /Bitte versuch es gleich noch einmal/)
assert.doesNotMatch(r.html, /Nicht mehr vorhanden|fakeAppwrite/)
})