Aktualisiere die Version auf 1.8.12, passe die Protokollnachricht für den QTTR-Import an und füge Tests für die QTTR-Importsignatur hinzu.
Some checks failed
Code Analysis and Production Deploy / analyze (push) Failing after 5m15s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Has been skipped

This commit is contained in:
Torsten Schulz (local)
2026-09-30 09:30:24 +02:00
parent 835a31a72e
commit 87e08df93a
4 changed files with 33 additions and 4 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "harheimertc-website", "name": "harheimertc-website",
"version": "1.8.11", "version": "1.8.12",
"description": "Moderne Webseite für den Harheimer Tischtennis Club", "description": "Moderne Webseite für den Harheimer Tischtennis Club",
"private": true, "private": true,
"type": "module", "type": "module",

View File

@@ -141,7 +141,7 @@ function createQttrJob() {
return { return {
run: async (reason) => { run: async (reason) => {
const qttr = await importQttrValues() const qttr = await importQttrValues()
loggerInfo(`[qttr-import] ${reason}: ${qttr.rowCount} QTTR-Werte importiert`, { loggerInfo(`[qttr-import] ${reason}: ${qttr.rowCount} TTR-/QTTR-Werte importiert`, {
outputFile: qttr.outputFile, outputFile: qttr.outputFile,
tableCount: qttr.tableCount tableCount: qttr.tableCount
}) })

View File

@@ -287,15 +287,21 @@ async function importAuthenticatedTtrValues(connection) {
}) })
await sendOwnTtrChangePush(changes) await sendOwnTtrChangePush(changes)
if (previousQttrSignature && previousQttrSignature !== nextQttrSignature) { if (previousQttrSignature && previousQttrSignature !== nextQttrSignature) {
await sendQttrListUpdatedPush({ importedAt, rowCount: rows.length }) await sendQttrListUpdatedPush({
importedAt,
rowCount: rows.filter(row => row.currentQttr != null).length
})
} }
await saveMyTischtennisConnection({ ...connection, lastSuccessfulImportAt: importedAt, lastImportError: null }) await saveMyTischtennisConnection({ ...connection, lastSuccessfulImportAt: importedAt, lastImportError: null })
return { outputFile: OUTPUT_FILE, tableCount: 1, ...payload } return { outputFile: OUTPUT_FILE, tableCount: 1, ...payload }
} }
function qttrListSignature(rows) { export function qttrListSignature(rows) {
if (!Array.isArray(rows) || rows.length === 0) return '' if (!Array.isArray(rows) || rows.length === 0) return ''
return rows return rows
// TTR-only players are refreshed daily. They must neither alter the
// quarterly QTTR signature nor trigger a QTTR-list notification.
.filter(row => row?.currentQttr != null)
.map(row => [ .map(row => [
String(row?.playerNumber || row?.playerName || '').trim().toLocaleLowerCase('de-DE'), String(row?.playerNumber || row?.playerName || '').trim().toLocaleLowerCase('de-DE'),
row?.currentQttr ?? '' row?.currentQttr ?? ''

23
tests/qttr-import.spec.ts Normal file
View File

@@ -0,0 +1,23 @@
import { describe, expect, it } from 'vitest'
import { qttrListSignature } from '../server/utils/qttr-import.js'
describe('QTTR import signature', () => {
it('ignores TTR-only players so daily TTR changes cannot trigger a QTTR push', () => {
const qttrRows = [
{ playerNumber: 1, playerName: 'QTTR Spieler', currentQttr: 1500, currentTtr: 1512 }
]
const withChangedTtrOnlyPlayer = [
...qttrRows,
{ playerNumber: 2, playerName: 'Nur TTR', currentQttr: null, currentTtr: 1333 }
]
expect(qttrListSignature(withChangedTtrOnlyPlayer)).toBe(qttrListSignature(qttrRows))
})
it('changes when an actual QTTR value changes', () => {
const previous = [{ playerNumber: 1, playerName: 'QTTR Spieler', currentQttr: 1500 }]
const updated = [{ playerNumber: 1, playerName: 'QTTR Spieler', currentQttr: 1501 }]
expect(qttrListSignature(updated)).not.toBe(qttrListSignature(previous))
})
})