Ueberschrittene Servicetermine werden markiert
Wunsch des Eigentuemers: faellige oder ueberschrittene Termine dezent
gelb/orange hinterlegen und mit "ueberschritten" markieren - Service-Seite und
Mein Audi; auf der Uebersicht zusaetzlich die Kennzahl im Warnton.
Erkannt wird am DATUM, nicht an den Restkilometern. Gemessen: die Sensoren
melden -28600 bzw. -22000 bei Faelligkeit 2028 bzw. 2027, negativ heisst hier
also "noch so weit hin". Welches Vorzeichen ein tatsaechlich ueberschrittener
Wert traegt, ist an den vorliegenden Daten nicht beobachtbar - geraten wird es
nicht. Der km-Fall faellt ohnehin unter die Datumsregel: servicePrognose()
setzt datum auf heute, sobald restKm auf 0 laeuft. Der Faelligkeitstag zaehlt
mit ("bereits faellig bzw. ueberschritten").
Dabei eine Luecke im Panel gefunden, vom Test und nicht im Betrieb:
datumAusText() ist verankert und nimmt keine vollen Zeitstempel - die
Fahrzeugmeldung ist aber genau das und bei Oelwechsel und Inspektion die
Hauptquelle. Sie waere still nie als ueberschritten erkannt worden.
zeitstempelAlsDatum() schliesst sie; die App hatte die Luecke nie.
Farbe nach Rolle geteilt wie --bad/--bad-flaeche: --warn ist die Flaeche,
--warn-text die Schrift. Grund: #FF9F0A als Text auf Weiss sind 2.06:1. Auf dem
12% hinterlegten Grund misst --warn-text 4.90:1 (Tag, #A15800) bzw. 9.30:1
(Nacht).
Geprueft: 15 Faelle gegen die echten Panel-Funktionen, 7 in der App, 14
Paritaetsfaelle Panel gegen App, 3 Rendertests ueber alle drei Anzeigestellen.
Gegenprobe: mit ausgehaengter Entscheidung fallen 9 Tests. 327/327, tsc sauber,
Panel als Modul geparst, Manifest und Buendel auf 2026.9.6.6, Container sauber
gestartet.
Offen: optisch nicht gesehen - der Testbestand enthaelt keinen ueberschrittenen
Termin. In OFFEN.md vermerkt.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import { readFileSync } from "node:fs"
|
||||
import { describe, expect, it } from "vitest"
|
||||
import { terminUeberschritten } from "./service"
|
||||
|
||||
/* Beide Codebasen müssen denselben Termin gleich beurteilen - sonst steht auf
|
||||
der Übersicht "überschritten" und auf derselben Seite im Panel nicht. Geprüft
|
||||
wird gegen die ECHTE Panel-Funktion, aus der Panel-Quelle herausgeschnitten,
|
||||
nicht gegen einen Nachbau. Muster wie in paritaet_hu.test.ts. */
|
||||
const quelle = readFileSync(
|
||||
"../custom_components/audi_dashboard/frontend/audi-dashboard-app.js", "utf8")
|
||||
const block = (kopf: string) => {
|
||||
const i = quelle.indexOf(kopf)
|
||||
if (i < 0) throw new Error("fehlt: " + kopf)
|
||||
let tiefe = 0
|
||||
for (let k = quelle.indexOf("{", i); k < quelle.length; k++) {
|
||||
if (quelle[k] === "{") tiefe++
|
||||
else if (quelle[k] === "}" && !--tiefe) return quelle.slice(i, k + 1)
|
||||
}
|
||||
throw new Error("unvollstaendig: " + kopf)
|
||||
}
|
||||
const zeile = (muster: RegExp) => {
|
||||
const m = muster.exec(quelle)
|
||||
if (!m) throw new Error("fehlt: " + muster)
|
||||
return m[0]
|
||||
}
|
||||
|
||||
const panel = new Function(`
|
||||
${zeile(/^const DATUM_ISO = .*$/m)}
|
||||
${zeile(/^const DATUM_TAG = .*$/m)}
|
||||
${zeile(/^const DATUM_MONAT = .*$/m)}
|
||||
${zeile(/^const DATUM_ISO_MONAT = .*$/m)}
|
||||
${zeile(/^const DATUM_ZEITSTEMPEL = .*$/m)}
|
||||
${zeile(/^const gueltigesDatum = .*$/m)}
|
||||
${block("function datumBauen")}
|
||||
${block("function datumAusText")}
|
||||
${block("function zeitstempelAlsDatum")}
|
||||
${block("function terminUeberschritten")}
|
||||
return { terminUeberschritten };
|
||||
`)() as { terminUeberschritten: (...k: (string | Date | null)[]) => boolean }
|
||||
|
||||
const tag = (versatz: number) => {
|
||||
const x = new Date()
|
||||
x.setDate(x.getDate() + versatz)
|
||||
return `${String(x.getDate()).padStart(2, "0")}.${String(x.getMonth() + 1).padStart(2, "0")}.${x.getFullYear()}`
|
||||
}
|
||||
|
||||
describe("terminUeberschritten: Panel und App urteilen gleich", () => {
|
||||
const faelle: { name: string; args: (string | null)[] }[] = [
|
||||
{ name: "gestern", args: [tag(-1)] },
|
||||
{ name: "heute", args: [tag(0)] },
|
||||
{ name: "morgen", args: [tag(1)] },
|
||||
{ name: "ISO vorbei", args: ["2024-03-01"] },
|
||||
{ name: "ISO Zukunft", args: ["2028-07-23"] },
|
||||
{ name: "Fahrzeug-Zeitstempel vorbei", args: ["2025-10-21T00:00:00+00:00"] },
|
||||
{ name: "Fahrzeug-Zeitstempel Zukunft", args: ["2027-10-21T00:00:00+00:00"] },
|
||||
{ name: "monatsgenau vorbei", args: ["03/2025"] },
|
||||
{ name: "monatsgenau Zukunft", args: ["03/2099"] },
|
||||
{ name: "kein Datum", args: [null] },
|
||||
{ name: "leer", args: [""] },
|
||||
{ name: "unlesbar", args: ["irgendwas"] },
|
||||
{ name: "erstes lesbares: null, dann gestern", args: [null, tag(-1)] },
|
||||
{ name: "erstes lesbares: morgen vor gestern", args: [tag(1), tag(-1)] },
|
||||
]
|
||||
|
||||
for (const f of faelle) {
|
||||
it(f.name, () => {
|
||||
expect(terminUeberschritten(...f.args)).toBe(panel.terminUeberschritten(...f.args))
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,16 +1,6 @@
|
||||
import { describe, expect, it } from "vitest"
|
||||
|
||||
import {
|
||||
hauptuntersuchungFaellig,
|
||||
inspektionPrognose,
|
||||
kmProTagAusFahrten,
|
||||
letzterOelwechsel,
|
||||
meldungsPrognose,
|
||||
meldungsPrognoseEigenesIntervall,
|
||||
naechsterService,
|
||||
oelMeldungsPrognose,
|
||||
oelwechselPrognose,
|
||||
} from "./service"
|
||||
import { hauptuntersuchungFaellig, inspektionPrognose, kmProTagAusFahrten, letzterOelwechsel, meldungsPrognose, meldungsPrognoseEigenesIntervall, naechsterService, oelMeldungsPrognose, oelwechselPrognose, terminUeberschritten } from "./service"
|
||||
import type { Fahrzeug } from "./profilAdapter"
|
||||
|
||||
function fahrzeug(odo: number, modus = "hersteller"): Fahrzeug {
|
||||
@@ -400,3 +390,50 @@ describe("Hauptuntersuchung", () => {
|
||||
expect(hauptuntersuchungFaellig([], "keine Ahnung")).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe("terminUeberschritten", () => {
|
||||
const tag = (versatz: number) => {
|
||||
const x = new Date()
|
||||
x.setDate(x.getDate() + versatz)
|
||||
return `${String(x.getDate()).padStart(2, "0")}.${String(x.getMonth() + 1).padStart(2, "0")}.${x.getFullYear()}`
|
||||
}
|
||||
|
||||
it("gestern ist überschritten", () => {
|
||||
expect(terminUeberschritten(tag(-1))).toBe(true)
|
||||
})
|
||||
|
||||
it("heute zählt mit - 'bereits fällig' ist gemeint", () => {
|
||||
expect(terminUeberschritten(tag(0))).toBe(true)
|
||||
})
|
||||
|
||||
it("morgen nicht", () => {
|
||||
expect(terminUeberschritten(tag(1))).toBe(false)
|
||||
})
|
||||
|
||||
it("erkennt den vollen Zeitstempel des Fahrzeugs", () => {
|
||||
// Genau die Form, die oelwechselFaelligTs/inspektionFaelligTs tragen. Im
|
||||
// Panel war das die Lücke: dessen Datumsleser ist verankert und nahm sie
|
||||
// nicht an, die Fahrzeugmeldung wäre dort still nie überschritten gewesen.
|
||||
expect(terminUeberschritten("2025-10-21T00:00:00+00:00")).toBe(true)
|
||||
expect(terminUeberschritten("2027-10-21T00:00:00+00:00")).toBe(false)
|
||||
})
|
||||
|
||||
it("versteht monatsgenaue Angaben (Hauptuntersuchung)", () => {
|
||||
expect(terminUeberschritten("03/2025")).toBe(true)
|
||||
expect(terminUeberschritten("03/2099")).toBe(false)
|
||||
})
|
||||
|
||||
it("ohne lesbares Datum wird nichts behauptet", () => {
|
||||
expect(terminUeberschritten(null)).toBe(false)
|
||||
expect(terminUeberschritten("")).toBe(false)
|
||||
expect(terminUeberschritten("irgendwas")).toBe(false)
|
||||
expect(terminUeberschritten(undefined)).toBe(false)
|
||||
})
|
||||
|
||||
it("nimmt das erste LESBARE Datum, nicht das erste beliebige", () => {
|
||||
// So kann die Markierung nicht von dem abweichen, was daneben steht.
|
||||
expect(terminUeberschritten(null, tag(-1))).toBe(true)
|
||||
expect(terminUeberschritten(tag(1), tag(-1))).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -401,3 +401,39 @@ export function hauptuntersuchungFaellig(
|
||||
const ziel = monatePlus(isoTag(z.zeit), HU_MONATE_ERSTE)
|
||||
return z.genau === "monat" ? ziel.slice(0, 7) : ziel
|
||||
}
|
||||
|
||||
/** Ist dieser Servicetermin bereits fällig oder überschritten?
|
||||
*
|
||||
* Der Fälligkeitstag selbst zählt mit („bereits fällig bzw. überschritten",
|
||||
* Ansage des Eigentümers 07.09.2026).
|
||||
*
|
||||
* Entschieden wird am DATUM, nicht an den Restkilometern - und das ist keine
|
||||
* Bequemlichkeit. Die Kilometerseite trägt je nach Quelle ein anderes
|
||||
* Vorzeichen: die Sensoren des Fahrzeugs melden negativ, solange noch Strecke
|
||||
* bleibt (am 07.09.2026 gemessen: oil_change_distance -28600 bei Fälligkeit
|
||||
* 2028), und servicePrognose() klemmt ihre Restkilometer ohnehin mit
|
||||
* Math.max(0, ...). Welches Vorzeichen ein überschrittener Fahrzeugwert trägt,
|
||||
* lässt sich an den vorliegenden Daten nicht beobachten - geraten wird es
|
||||
* nicht. Der km-Fall fällt ohnehin unter die Datumsregel: servicePrognose()
|
||||
* setzt datum auf heute, sobald restKm auf 0 läuft.
|
||||
*
|
||||
* Genommen wird das ERSTE lesbare Datum der übergebenen Kandidaten - also das,
|
||||
* das an dieser Stelle auch angezeigt wird. So kann die Markierung nicht von
|
||||
* dem abweichen, was daneben steht. Wortgleich mit terminUeberschritten() im
|
||||
* Panel. */
|
||||
export function terminUeberschritten(
|
||||
...kandidaten: (string | Date | null | undefined)[]
|
||||
): boolean {
|
||||
for (const kandidat of kandidaten) {
|
||||
if (kandidat === null || kandidat === undefined || kandidat === "") continue
|
||||
const z = alsZeitpunkt(kandidat)
|
||||
if (!z) continue
|
||||
const d = z.zeit
|
||||
const h = new Date()
|
||||
return (
|
||||
new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime() <=
|
||||
new Date(h.getFullYear(), h.getMonth(), h.getDate()).getTime()
|
||||
)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ import { useRef, useState, type PointerEvent as ReactPointerEvent } from "react"
|
||||
import { Tile } from "@audi-dash/ui"
|
||||
|
||||
import { useDaten } from "../daten/DatenKontext"
|
||||
import { hauptuntersuchungFaellig, inspektionPrognose, oelwechselPrognose } from "../daten/service"
|
||||
import { hauptuntersuchungFaellig, inspektionPrognose, oelwechselPrognose, terminUeberschritten } from "../daten/service"
|
||||
import { datum, de, deOderStrich, eur } from "../format"
|
||||
import type { SeitenName } from "../navigation"
|
||||
import { Wertzeile, Werteliste } from "./bausteine"
|
||||
import { UeberschrittenMarke, Werteliste, Wertzeile } from "./bausteine"
|
||||
import { Bild } from "./Bild"
|
||||
import { GALERIE } from "./bilder"
|
||||
import type { ServicebuchEintrag } from "./Service"
|
||||
@@ -115,13 +115,14 @@ export function MeinAudi({ geheZu }: { geheZu: (name: SeitenName, id?: string) =
|
||||
const huFaellig = hauptuntersuchungFaellig(buch, fahrzeug.erstzulassung)
|
||||
const oelProg = oelwechselPrognose(fahrzeug, buch)
|
||||
const inspProg = inspektionPrognose(fahrzeug, buch)
|
||||
const termine: { art: string; prognose: string | null; haupt: string; neben: string | null }[] = [
|
||||
const termine: { art: string; prognose: string | null; haupt: string; neben: string | null; ueber: boolean }[] = [
|
||||
{
|
||||
art: "Ölwechsel",
|
||||
prognose: oelProg
|
||||
? `${de(oelProg.restKm)} km, voraussichtlich am ${datum(oelProg.datum)}`
|
||||
: null,
|
||||
haupt: fahrzeug.oelwechselFaelligTs ? datum(fahrzeug.oelwechselFaelligTs) : "–",
|
||||
ueber: terminUeberschritten(fahrzeug.oelwechselFaelligTs, oelProg?.datum),
|
||||
neben:
|
||||
fahrzeug.oelwechselFaelligKm != null
|
||||
? `in ${de(Math.abs(fahrzeug.oelwechselFaelligKm))} km`
|
||||
@@ -131,6 +132,7 @@ export function MeinAudi({ geheZu }: { geheZu: (name: SeitenName, id?: string) =
|
||||
art: "Inspektion",
|
||||
prognose: inspProg ? `voraussichtlich am ${datum(inspProg.datum)}` : null,
|
||||
haupt: fahrzeug.inspektionFaelligTs ? datum(fahrzeug.inspektionFaelligTs) : "–",
|
||||
ueber: terminUeberschritten(fahrzeug.inspektionFaelligTs, inspProg?.datum),
|
||||
neben:
|
||||
fahrzeug.inspektionFaelligKm != null
|
||||
? `in ${de(Math.abs(fahrzeug.inspektionFaelligKm))} km`
|
||||
@@ -142,6 +144,7 @@ export function MeinAudi({ geheZu }: { geheZu: (name: SeitenName, id?: string) =
|
||||
art: "Hauptuntersuchung",
|
||||
prognose: null,
|
||||
haupt: huFaellig ? datum(huFaellig) : "–",
|
||||
ueber: terminUeberschritten(huFaellig),
|
||||
neben: null,
|
||||
},
|
||||
]
|
||||
@@ -270,7 +273,15 @@ export function MeinAudi({ geheZu }: { geheZu: (name: SeitenName, id?: string) =
|
||||
)}
|
||||
</>
|
||||
}
|
||||
wert={t.haupt}
|
||||
wert={
|
||||
t.ueber ? (
|
||||
<>
|
||||
{t.haupt} <UeberschrittenMarke />
|
||||
</>
|
||||
) : (
|
||||
t.haupt
|
||||
)
|
||||
}
|
||||
{...(t.neben ? { zusatz: t.neben } : {})}
|
||||
/>
|
||||
))
|
||||
|
||||
@@ -14,15 +14,11 @@ import { ActionButton, Feld, Fig, Tile } from "@audi-dash/ui"
|
||||
|
||||
import { kartendienstUrl } from "../daten/tankstelle"
|
||||
import { useDaten } from "../daten/DatenKontext"
|
||||
import { hauptuntersuchungFaellig, inspektionPrognose, letzterInspektion, letzterOelwechsel, meldungsPrognose, oelMeldungsPrognose, oelwechselPrognose, serviceKandidaten } from "../daten/service"
|
||||
import { hauptuntersuchungFaellig, inspektionPrognose, letzterInspektion, letzterOelwechsel, meldungsPrognose, oelMeldungsPrognose, oelwechselPrognose, serviceKandidaten, terminUeberschritten } from "../daten/service"
|
||||
import { datum, de, eur, isoTag } from "../format"
|
||||
import type { SeitenName } from "../navigation"
|
||||
import { SymbolInspektion, SymbolOelwechsel } from "../symbole"
|
||||
import {
|
||||
Blattzeile,
|
||||
Leerzustand,
|
||||
Zahnradknopf,
|
||||
} from "./bausteine"
|
||||
import { Blattzeile, Leerzustand, UeberschrittenMarke, Zahnradknopf } from "./bausteine"
|
||||
import { LOESCH_HINWEIS, LOESCH_TEXT, bestaetigen } from "./bestaetigung"
|
||||
import { Datumsfeld } from "./Datumsfeld"
|
||||
import { terminUebernehmen } from "./kalender"
|
||||
@@ -127,14 +123,25 @@ export function Service({ geheZu }: { geheZu: (name: SeitenName, id?: string) =>
|
||||
const huDatum = huFaellig ? new Date(huFaellig) : null
|
||||
const huGueltig = !!huDatum && !Number.isNaN(huDatum.getTime())
|
||||
|
||||
// Dasselbe Datum, das gleich als Wert erscheint - siehe
|
||||
// terminUeberschritten(). Die Fahrzeugmeldung geht vor, weil sie oben steht.
|
||||
const oelUeber = terminUeberschritten(
|
||||
oelHatMeldung ? fahrzeug.oelwechselFaelligTs : prognose?.datum,
|
||||
)
|
||||
const inspUeber = terminUeberschritten(
|
||||
inspHatMeldung ? fahrzeug.inspektionFaelligTs : inspektionsprognose?.datum,
|
||||
)
|
||||
const huUeber = huGueltig && terminUeberschritten(huFaellig)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tile>
|
||||
|
||||
<div className="dm-termingruppe">
|
||||
<div className={`dm-termingruppe${oelUeber ? " dm-termingruppe--ueberschritten" : ""}`}>
|
||||
<div className="dm-tgkopf">
|
||||
<SymbolOelwechsel groesse={26} />
|
||||
<span>Ölwechsel</span>
|
||||
{oelUeber && <UeberschrittenMarke />}
|
||||
</div>
|
||||
{oelHatEintrag || oelHatMeldung ? (
|
||||
<>
|
||||
@@ -147,10 +154,11 @@ export function Service({ geheZu }: { geheZu: (name: SeitenName, id?: string) =>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="dm-termingruppe">
|
||||
<div className={`dm-termingruppe${inspUeber ? " dm-termingruppe--ueberschritten" : ""}`}>
|
||||
<div className="dm-tgkopf">
|
||||
<SymbolInspektion groesse={20} />
|
||||
<span>Inspektion</span>
|
||||
{inspUeber && <UeberschrittenMarke />}
|
||||
</div>
|
||||
{inspHatEintrag || inspHatMeldung ? (
|
||||
<>
|
||||
@@ -163,9 +171,10 @@ export function Service({ geheZu }: { geheZu: (name: SeitenName, id?: string) =>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="dm-termingruppe">
|
||||
<div className={`dm-termingruppe${huUeber ? " dm-termingruppe--ueberschritten" : ""}`}>
|
||||
<div className="dm-tgkopf">
|
||||
<span>Hauptuntersuchung</span>
|
||||
{huUeber && <UeberschrittenMarke />}
|
||||
</div>
|
||||
{huGueltig ? (
|
||||
<div className="dm-tgwert">{datum(huFaellig)}</div>
|
||||
|
||||
@@ -11,11 +11,11 @@ import { Fig, ProgressBar, StatusRow, Tile } from "@audi-dash/ui"
|
||||
import { useState } from "react"
|
||||
|
||||
import { useDaten } from "../daten/DatenKontext"
|
||||
import { naechsterService } from "../daten/service"
|
||||
import { naechsterService, terminUeberschritten } from "../daten/service"
|
||||
import { datum, de, deOderStrich, eur, streckeText } from "../format"
|
||||
import type { SeitenName } from "../navigation"
|
||||
import { BILDPLAETZE, bildInfo } from "./bilder"
|
||||
import { Blattzeile, Leerzustand } from "./bausteine"
|
||||
import { Blattzeile, Leerzustand, UeberschrittenMarke } from "./bausteine"
|
||||
// Dieselbe Ortsangabe wie in der Fahrtenliste - eine Quelle, damit "Zuletzt"
|
||||
// und die Liste nicht auseinanderlaufen koennen.
|
||||
import { strecke } from "./Fahrten"
|
||||
@@ -81,6 +81,9 @@ export function Uebersicht({ geheZu }: { geheZu: (name: SeitenName, id?: string)
|
||||
|
||||
const buch = (fahrzeug.service["buch"] ?? []) as ServicebuchEintrag[]
|
||||
const service = naechsterService(fahrzeug, buch, fahrten)
|
||||
// Auf der Uebersicht wechselt zusaetzlich die Kennzahl die Farbe - sie ist
|
||||
// hier die Aussage, nicht nur ihr Rahmen (Ansage des Eigentuemers).
|
||||
const serviceUeber = !!service && terminUeberschritten(service.datum)
|
||||
|
||||
const letzteFahrt = fahrten
|
||||
.slice()
|
||||
@@ -238,7 +241,11 @@ export function Uebersicht({ geheZu }: { geheZu: (name: SeitenName, id?: string)
|
||||
"differentiate controls from content" gilt auch für die
|
||||
Abwesenheit von Inhalt. */}
|
||||
{service ? (
|
||||
<button type="button" className="dm-serviceblock" onClick={() => geheZu("service")}>
|
||||
<button
|
||||
type="button"
|
||||
className={`dm-serviceblock${serviceUeber ? " dm-serviceblock--ueberschritten" : ""}`}
|
||||
onClick={() => geheZu("service")}
|
||||
>
|
||||
<span className="ads-eyebrow">Nächster Service:</span>
|
||||
{/* Gezeichneter Pfeil wie .go im Panel, kein Schriftzeichen: das
|
||||
">" war ein 15px-Glyph der Textschrift und damit erkennbar
|
||||
@@ -265,6 +272,11 @@ export function Uebersicht({ geheZu }: { geheZu: (name: SeitenName, id?: string)
|
||||
fig
|
||||
)
|
||||
})()}
|
||||
{serviceUeber && (
|
||||
<div className="dm-servicemarke">
|
||||
<UeberschrittenMarke />
|
||||
</div>
|
||||
)}
|
||||
{/* Im Panel ist auch diese Nebenzeile ein `.label` (13px, --fg3),
|
||||
nicht die kleinere Fußnote (11,5px/300), die hier stand. */}
|
||||
<span className="ads-eyebrow" style={{ marginTop: "8px" }}>
|
||||
|
||||
@@ -537,3 +537,10 @@ export function Markenlogo({
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
/** „überschritten" neben einem fälligen Servicetermin. Eigener Baustein, damit
|
||||
* die drei Anzeigestellen (Service, Mein Audi, Übersicht) nicht auseinander
|
||||
* laufen. Gegenstück zu UEBERSCHRITTEN_MARKE im Panel. */
|
||||
export function UeberschrittenMarke() {
|
||||
return <span className="dm-ueberschritten-marke">überschritten</span>
|
||||
}
|
||||
|
||||
@@ -12,13 +12,19 @@ import { Shell } from "../Shell"
|
||||
import type { SeitenName } from "../navigation"
|
||||
import { TITEL } from "../navigation"
|
||||
import { SeiteFuer } from "./register"
|
||||
import { beispielApi } from "../tests/beispieldaten"
|
||||
import { beispielApi, beispielProfil } from "../tests/beispieldaten"
|
||||
import type { Profil } from "../api/types"
|
||||
import { bildschirmbreiteSetzen } from "../tests/aufbau"
|
||||
|
||||
const ALLE_SEITEN = Object.keys(TITEL) as SeitenName[]
|
||||
|
||||
function zeige(name: SeitenName, id?: string, geheZu: (name: SeitenName, id?: string) => void = () => {}) {
|
||||
const api = beispielApi()
|
||||
function zeige(
|
||||
name: SeitenName,
|
||||
id?: string,
|
||||
geheZu: (name: SeitenName, id?: string) => void = () => {},
|
||||
profil?: Profil,
|
||||
) {
|
||||
const api = profil ? beispielApi(profil) : beispielApi()
|
||||
return render(
|
||||
<div className="ads-root" data-theme="nacht">
|
||||
<DatenAnbieter api={api}>
|
||||
@@ -194,3 +200,38 @@ describe("Inhalte kommen wirklich aus den Daten", () => {
|
||||
expect(artAuswahl.value).toBe("arbeitsweg")
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
/* Überschrittene Servicetermine werden markiert - an allen drei Stellen, die
|
||||
der Eigentümer genannt hat (07.09.2026). Die Beispieldaten tragen
|
||||
erstzulassung 2023-04-01, die Hauptuntersuchung liegt damit auf 04/2026 und
|
||||
ist überschritten; getestet wird also am vorhandenen Bestand, nicht an einer
|
||||
eigens gebauten Fixtur. */
|
||||
describe("Überschrittene Servicetermine", () => {
|
||||
/* Der Regelbestand hat keinen ueberschrittenen Termin (Wartungsplan
|
||||
2026-02-10 + 24 Monate). Hier deshalb ein Profil, dessen letzter Eintrag
|
||||
lange zurueckliegt - die Hauptuntersuchung faellt damit in die
|
||||
Vergangenheit. */
|
||||
const ueberfaellig: Profil = {
|
||||
...beispielProfil,
|
||||
fahrzeug: { ...beispielProfil.fahrzeug, erstzulassung: "2019-04-01" },
|
||||
service: { ...beispielProfil.service, buch: [] },
|
||||
}
|
||||
|
||||
it("markiert die Gruppe auf der Service-Seite", async () => {
|
||||
const { container } = zeige("service", undefined, () => {}, ueberfaellig)
|
||||
await waitFor(() => expect(screen.getAllByText("überschritten").length).toBeGreaterThan(0))
|
||||
expect(container.querySelector(".dm-termingruppe--ueberschritten")).not.toBeNull()
|
||||
})
|
||||
|
||||
it("markiert die Zeile in Mein Audi", async () => {
|
||||
zeige("audi", undefined, () => {}, ueberfaellig)
|
||||
await waitFor(() => expect(screen.getAllByText("überschritten").length).toBeGreaterThan(0))
|
||||
})
|
||||
|
||||
it("markiert den Serviceblock auf der Übersicht und färbt die Kennzahl", async () => {
|
||||
const { container } = zeige("home", undefined, () => {}, ueberfaellig)
|
||||
await waitFor(() => expect(screen.getAllByText("überschritten").length).toBeGreaterThan(0))
|
||||
expect(container.querySelector(".dm-serviceblock--ueberschritten")).not.toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
+2409
-2365
File diff suppressed because it is too large
Load Diff
@@ -162,7 +162,10 @@ export const beispielTankvorgaenge: Tankvorgang[] = [
|
||||
]
|
||||
|
||||
/** Datenschicht-Ersatz für Tests: liefert Beispieldaten, schreibt ins Leere. */
|
||||
export function beispielApi(): DataMetricApi {
|
||||
/** Die Beispieldaten mit einem abweichenden Profil - fuer Tests, die einen
|
||||
* Zustand brauchen, den der Regelbestand nicht hergibt (etwa einen bereits
|
||||
* ueberschrittenen Servicetermin). Ohne Argument bleibt alles wie bisher. */
|
||||
export function beispielApi(profil: Profil = beispielProfil): DataMetricApi {
|
||||
const horcher = { verbindung: [] as ((z: string) => void)[] }
|
||||
return {
|
||||
rest: {
|
||||
@@ -196,7 +199,7 @@ export function beispielApi(): DataMetricApi {
|
||||
},
|
||||
anzahl: 0,
|
||||
},
|
||||
profilLesen: async () => beispielProfil,
|
||||
profilLesen: async () => profil,
|
||||
fahrtenLesen: async () => beispielFahrten,
|
||||
tankvorgaengeLesen: async () => beispielTankvorgaenge,
|
||||
fahrzeugstatusLesen: async () => beispielStatus,
|
||||
|
||||
Reference in New Issue
Block a user