Analyse: Zeitraum = abgeschlossene Tage, "Heute bisher" getrennt, Feinschliff
Final-Review-Fixwelle der Cockpit-Übersicht:
- F1 Collector: Der Zeitraum sind die range Kalendertage bis gestern (Berliner Tag),
der Vorzeitraum die range Tage davor; heute steht getrennt in today { day, pv, visitors,
contacts }. Kein Einbruch mehr am rechten Rand von Diagramm und Mini-Verläufen,
kein falsches "x % weniger" tagsüber. Portal: weekdayStats bekommt die ganze Reihe
(completedDays entfällt), "Vergleich ab" = firstDay + 2 x range, Kopfzeile
"Analyse aktiv · Heute bisher: N Aufrufe · Stand: HH:MM Uhr" (alter Collector ohne today
bleibt ohne "Heute bisher").
- F2 "direkt kontaktiert" zählt nur Telefon, E-Mail und WhatsApp (auch im Vorzeitraum),
Links nach außen nicht.
- F3 Mini-Verlauf "Ø Zeit pro Seite": Tage ohne Messung sind Lücken statt 0-Tälern.
- F4 Fehlerfarbe beim Ausschalten rot, --an-faint auf 55 %, Achsenschrift per
Container-Abfragen auf 11-12 px (y-Rand wächst mit der Stellenzahl, x-Beschriftungen mit
Mindestabstand), Ranglisten-Anteile an allen Seitenaufrufen, Tippflächen bis 880 px
mindestens 40 px hoch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
eadb768d1a
commit
0db59d38e9
11 files changed
+376
-135
No files matched your search
@@ -14,6 +14,7 @@ const prev = {
|
||||
}
|
||||
const stats = (over = {}) => ({
|
||||
range: 30, from: '2026-09-05', to: '2026-10-04', firstDay: '2026-07-01',
|
||||
today: { day: '2026-10-05', pv: 42, visitors: 20, contacts: 1 },
|
||||
totals: t,
|
||||
series: days('2026-09-05', 30, 231),
|
||||
pages: [{ key: '/', count: 3200 }, { key: '/preise', count: 1310 }, { key: '/kontakt', count: 900 }],
|
||||
@@ -66,8 +67,8 @@ test('fmtDuration, dayLabel, periodLabel, fmtNum', () => {
|
||||
|
||||
test('compareFrom: ok, Datum bei neuer Website, nichts ohne previous', () => {
|
||||
assert.deepEqual(compareFrom(stats()), { ok: true, from: '' })
|
||||
assert.deepEqual(compareFrom(stats({ firstDay: '2026-09-20', previous: { ...prev, complete: false } })), { ok: false, from: '18.11.' }) // range 30: +59 Tage
|
||||
assert.deepEqual(compareFrom(stats({ range: 7, firstDay: '2026-09-28', previous: { ...prev, complete: false } })), { ok: false, from: '11.10.' }) // range 7: +13 Tage
|
||||
assert.deepEqual(compareFrom(stats({ firstDay: '2026-09-20', previous: { ...prev, complete: false } })), { ok: false, from: '19.11.' }) // range 30: +60 Tage (2 × range, der erste Tag mit vollem Vorzeitraum)
|
||||
assert.deepEqual(compareFrom(stats({ range: 7, firstDay: '2026-09-28', previous: { ...prev, complete: false } })), { ok: false, from: '12.10.' }) // range 7: +14 Tage
|
||||
assert.deepEqual(compareFrom(stats({ firstDay: '', previous: { ...prev, complete: false } })), { ok: false, from: '' })
|
||||
assert.deepEqual(compareFrom({ totals: { pv: 50 }, series: [] }), { ok: false, from: '' })
|
||||
assert.equal(compareFrom(stats({ previous: { ...prev, totals: { ...prev.totals, pv: 19 } } })).ok, false)
|
||||
@@ -116,7 +117,7 @@ test('summarize: Wachstum mit Prozent', () => {
|
||||
const s = summarize(stats())
|
||||
assert.equal(s.lead, 'Deine Website wurde in den letzten 30 Tagen <b>6.930-mal</b> aufgerufen – <b>14 % mehr</b> als in den 30 Tagen davor.')
|
||||
assert.equal(s.items[0].icon, 'contact')
|
||||
assert.equal(s.items[0].html, '188-mal hat dich jemand direkt kontaktiert, meist per Telefon (96). Das sind 45 mehr als zuvor.')
|
||||
assert.equal(s.items[0].html, '178-mal hat dich jemand direkt kontaktiert, meist per Telefon (96). Das sind 35 mehr als zuvor.') // Telefon + E-Mail + WhatsApp: 96 + 52 + 30 gegen 80 + 40 + 23
|
||||
assert.ok(s.items.length <= 4)
|
||||
})
|
||||
|
||||
@@ -148,7 +149,7 @@ test('summarize: ohne Vergleich und neu gestartet', () => {
|
||||
// auch das Startdatum wird maskiert, falls der Collector je Unsinn liefert
|
||||
assert.ok(!summarize(stats({ firstDay: '<i>x</i>', previous: { ...prev, complete: false } })).lead.includes('<i>'))
|
||||
// ohne Vergleich kein „Das sind … mehr als zuvor“
|
||||
assert.equal(neu.items[0].html, '188-mal hat dich jemand direkt kontaktiert, meist per Telefon (96).')
|
||||
assert.equal(neu.items[0].html, '178-mal hat dich jemand direkt kontaktiert, meist per Telefon (96).')
|
||||
// 7 Tage: „7 Tagen“
|
||||
assert.match(summarize(stats({ range: 7 })).lead, /in den letzten 7 Tagen .* als in den 7 Tagen davor\.$/)
|
||||
})
|
||||
@@ -164,16 +165,26 @@ test('summarize: zu wenig Daten → null; keine Kontakte → Hinweis nur ab 30 B
|
||||
assert.notEqual(wenig.items[0].icon, 'contact')
|
||||
})
|
||||
|
||||
test('summarize: Kontakte – Vergleichssatz und häufigste Art', () => {
|
||||
const html = (contactsNow, contactsBefore, kinds) => summarize(stats({
|
||||
totals: { ...t, contacts: contactsNow },
|
||||
test('summarize: Kontakte – Vergleichssatz und häufigste Art, Links nach außen zählen nicht mit', () => {
|
||||
const tel = (n) => ({ key: 'tel', count: n })
|
||||
const html = (kinds, before) => summarize(stats({
|
||||
totals: { ...t, contacts: kinds.reduce((a, k) => a + k.count, 0) },
|
||||
contacts: kinds,
|
||||
previous: { ...prev, totals: { ...prev.totals, contacts: contactsBefore } },
|
||||
previous: { ...prev, contacts: before, totals: { ...prev.totals, contacts: before.reduce((a, k) => a + k.count, 0) } },
|
||||
})).items[0].html
|
||||
assert.equal(html(188, 200, [{ key: 'tel', count: 96 }]), '188-mal hat dich jemand direkt kontaktiert, meist per Telefon (96). Das sind 12 weniger als zuvor.')
|
||||
assert.equal(html(188, 188, [{ key: 'mail', count: 100 }]), '188-mal hat dich jemand direkt kontaktiert, meist per E-Mail (100). Genauso oft wie zuvor.')
|
||||
assert.equal(html(5, 0, [{ key: 'wa', count: 3 }]), '5-mal hat dich jemand direkt kontaktiert, meist per WhatsApp (3).') // Vorwert 0: kein Vergleichssatz
|
||||
assert.equal(html(5, 2, [{ key: 'out', count: 3 }]), '5-mal hat dich jemand direkt kontaktiert, meist über einen Link nach außen (3). Das sind 3 mehr als zuvor.')
|
||||
assert.equal(html([tel(96)], [tel(108)]), '96-mal hat dich jemand direkt kontaktiert, meist per Telefon (96). Das sind 12 weniger als zuvor.')
|
||||
assert.equal(html([{ key: 'mail', count: 100 }], [{ key: 'mail', count: 100 }]), '100-mal hat dich jemand direkt kontaktiert, meist per E-Mail (100). Genauso oft wie zuvor.')
|
||||
assert.equal(html([{ key: 'wa', count: 5 }], []), '5-mal hat dich jemand direkt kontaktiert, meist per WhatsApp (5).') // Vorwert 0: kein Vergleichssatz
|
||||
assert.equal(html([tel(5)], [tel(2)]), '5-mal hat dich jemand direkt kontaktiert, meist per Telefon (5). Das sind 3 mehr als zuvor.')
|
||||
// Links nach außen sind Klicks auf andere Seiten, kein Kontakt: weder in der Zahl noch als häufigste Art, auch nicht im Vorzeitraum
|
||||
assert.equal(html([{ key: 'out', count: 300 }, tel(40)], [{ key: 'out', count: 900 }, tel(40)]), '40-mal hat dich jemand direkt kontaktiert, meist per Telefon (40). Genauso oft wie zuvor.')
|
||||
assert.equal(html([{ key: 'out', count: 300 }, tel(40)], [{ key: 'out', count: 900 }]), '40-mal hat dich jemand direkt kontaktiert, meist per Telefon (40).')
|
||||
// nur Links nach außen (Besucher ≥ 30): wie „keine Kontakte“
|
||||
const nurOut = summarize(stats({ totals: { ...t, contacts: 300, visitors: 400 }, contacts: [{ key: 'out', count: 300 }] }))
|
||||
assert.deepEqual(nurOut.items[0], { icon: 'contact', html: 'Von den Besuchern mit Zustimmung hat noch niemand über die Website angerufen oder geschrieben.' })
|
||||
// Collector ohne Kontaktliste: kein Satz, der etwas Falsches behauptet
|
||||
const { contacts, ...ohneListe } = stats({ totals: { ...t, contacts: 0, visitors: 400 } })
|
||||
assert.notEqual(summarize(ohneListe).items[0].icon, 'contact')
|
||||
})
|
||||
|
||||
test('summarize: Herkunft, Gerät, Seite und Reihenfolge, höchstens 4', () => {
|
||||
@@ -219,30 +230,24 @@ test('summarize: Wochentag und Spitzentag in einem Hinweis', () => {
|
||||
assert.ok(!summarize(stats({ firstDay: '2026-09-30', series: days('2026-09-05', 30, spike) })).items.some((i) => i.icon === 'day'))
|
||||
})
|
||||
|
||||
test('summarize: der heutige, unvollständige Tag zählt beim Wochentag-Hinweis nicht mit', () => {
|
||||
test('summarize: Wochentag-Hinweis zählt alle Tage der Reihe (alle sind abgeschlossen), auch in der 7-Tage-Ansicht', () => {
|
||||
const isSat = (day) => new Date(day + 'T00:00:00Z').getUTCDay() === 6
|
||||
const dayHtml = (s) => s.items.find((i) => i.icon === 'day')?.html
|
||||
// Reihe 04.09.–03.10.2026, heute = Samstag 03.10. mit erst 5 Aufrufen; Samstage sonst 280, alle anderen Tage 200
|
||||
const today = '2026-10-03'
|
||||
const sat = (i, day) => (day === today ? 5 : isSat(day) ? 280 : 200)
|
||||
const series = days('2026-09-04', 30, sat)
|
||||
const base = { from: '2026-09-04', to: today, series }
|
||||
// zählte der Tag mit, läge der Samstag-Schnitt (225) unter 1,2 × Gesamtschnitt (204) → kein Hinweis
|
||||
assert.equal(weekdayStats(series, '').best, null)
|
||||
// ohne den heutigen Tag: Samstag Ø 280 ≥ 1,2 × 211, stärkster Tag; Spitzentag nein (280 < 1,8 × 211)
|
||||
assert.equal(dayHtml(summarize(stats(base))), 'Samstag ist im Schnitt dein stärkster Tag.')
|
||||
// Spitzentag: Mi., 16.09. mit 365 (zählte heute mit, wäre 365 ≥ 1,8 × 199 ein Spitzentag; ohne heute 365 < 1,8 × 205,7)
|
||||
const wed = days('2026-09-04', 30, (i, day) => (day === today ? 5 : day === '2026-09-16' ? 365 : 200))
|
||||
assert.ok(weekdayStats(wed, '').peak)
|
||||
assert.equal(dayHtml(summarize(stats({ ...base, series: wed }))), undefined)
|
||||
// fehlt `to`, entfällt der letzte Tag trotzdem
|
||||
assert.equal(dayHtml(summarize(stats({ ...base, to: undefined }))), 'Samstag ist im Schnitt dein stärkster Tag.')
|
||||
// endet die Reihe nicht auf `to`, ist der letzte Tag ein abgeschlossener Tag und zählt mit
|
||||
assert.equal(dayHtml(summarize(stats({ ...base, to: '2026-10-04' }))), undefined)
|
||||
// 7-Tage-Ansicht: nur 6 abgeschlossene Tage → kein Wochentag-Hinweis, auch bei deutlichem Muster
|
||||
// Reihe 04.09.–03.10.2026 (Ende = gestern, heute steht getrennt in `today`); der letzte Tag, Samstag 03.10., zählt mit
|
||||
const last = '2026-10-03'
|
||||
const base = { from: '2026-09-04', to: last, today: { day: '2026-10-04', pv: 5, visitors: 3, contacts: 0 } }
|
||||
assert.equal(dayHtml(summarize(stats({ ...base, series: days('2026-09-04', 30, (i, day) => (isSat(day) ? 280 : 200)) }))), 'Samstag ist im Schnitt dein stärkster Tag.')
|
||||
// Spitzentag am letzten Tag der Reihe wird erkannt
|
||||
const spike = days('2026-09-04', 30, (i, day) => (day === last ? 400 : 100))
|
||||
assert.equal(dayHtml(summarize(stats({ ...base, series: spike }))), 'Samstag ist im Schnitt dein stärkster Tag. Spitzentag war Sa., 03.10. mit 400 Aufrufen.')
|
||||
// 7-Tage-Ansicht: genau 7 abgeschlossene Tage reichen für den Hinweis (28.09.–04.10., Sa. 03.10.)
|
||||
const week = days('2026-09-28', 7, (i, day) => (isSat(day) ? 500 : 100))
|
||||
assert.equal(dayHtml(summarize(stats({ range: 7, from: '2026-09-28', to: '2026-10-04', series: week }))), undefined)
|
||||
assert.ok(weekdayStats(week, '')) // mit allen 7 Tagen wäre es ein Ergebnis gewesen
|
||||
assert.equal(dayHtml(summarize(stats({ range: 7, from: '2026-09-28', to: '2026-10-04', series: week }))), 'Samstag ist im Schnitt dein stärkster Tag. Spitzentag war Sa., 03.10. mit 500 Aufrufen.')
|
||||
// weniger als 7 Tage (neue Website): weiter kein Hinweis
|
||||
assert.equal(dayHtml(summarize(stats({ range: 7, from: '2026-09-28', to: '2026-10-04', firstDay: '2026-09-29', series: week }))), undefined)
|
||||
// alter Collector ohne `today`: derselbe Hinweis, kein Absturz
|
||||
const { today, ...alt } = stats({ ...base, series: days('2026-09-04', 30, (i, day) => (isSat(day) ? 280 : 200)) })
|
||||
assert.equal(dayHtml(summarize(alt)), 'Samstag ist im Schnitt dein stärkster Tag.')
|
||||
})
|
||||
|
||||
test('summarize: Pfade und Hosts werden maskiert', () => {
|
||||
|
||||
Reference in new issue
Block a user