eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

1package main
2
3// The ≈ display's rate snapshot (fx.go): fetch, parse, last-good fallback,
4// and the empty-until-fetched public shape.
5
6import (
7 "encoding/json"
8 "net/http"
9 "net/http/httptest"
10 "testing"
11)
12
13const ecbSample = `<?xml version="1.0" encoding="UTF-8"?>
14<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
15 <gesmes:subject>Reference rates</gesmes:subject>
16 <Cube>
17 <Cube time="2026-07-17">
18 <Cube currency="USD" rate="1.0876"/>
19 <Cube currency="GBP" rate="0.8433"/>
20 <Cube currency="JPY" rate="170.61"/>
21 </Cube>
22 </Cube>
23</gesmes:Envelope>`
24
25func TestFXRefreshAndServe(t *testing.T) {
26 feed := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
27 w.Write([]byte(ecbSample))
28 }))
29 defer feed.Close()
30 ts, s := newTestServer(t)
31
32 get := func() (string, map[string]float64) {
33 t.Helper()
34 resp, err := http.Get(ts.URL + "/api/fx")
35 if err != nil {
36 t.Fatal(err)
37 }
38 defer resp.Body.Close()
39 if resp.StatusCode != http.StatusOK {
40 t.Fatalf("fx: HTTP %d", resp.StatusCode)
41 }
42 var body struct {
43 Base string `json:"base"`
44 Date string `json:"date"`
45 Rates map[string]float64 `json:"rates"`
46 }
47 if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
48 t.Fatal(err)
49 }
50 if body.Base != "EUR" {
51 t.Fatalf("base = %q", body.Base)
52 }
53 return body.Date, body.Rates
54 }
55
56 // Before any fetch: an empty snapshot, still a clean 200 (the client just
57 // shows no ≈ figure).
58 if date, rates := get(); date != "" || len(rates) != 0 {
59 t.Fatalf("pre-fetch snapshot = %q %v, want empty", date, rates)
60 }
61
62 if err := s.fx.refresh(http.DefaultClient, feed.URL); err != nil {
63 t.Fatal(err)
64 }
65 date, rates := get()
66 if date != "2026-07-17" || rates["USD"] != 1.0876 || rates["GBP"] != 0.8433 || len(rates) != 3 {
67 t.Fatalf("snapshot = %q %v", date, rates)
68 }
69
70 // A failing feed keeps the last-good snapshot.
71 feed.Close()
72 if err := s.fx.refresh(http.DefaultClient, feed.URL); err == nil {
73 t.Fatal("refresh against a dead feed reported success")
74 }
75 if date, rates := get(); date != "2026-07-17" || len(rates) != 3 {
76 t.Fatalf("post-failure snapshot = %q %v, want last-good kept", date, rates)
77 }
78
79 // So does a feed that answers but parses to nothing.
80 empty := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
81 w.Write([]byte(`<Envelope><Cube><Cube time="2026-07-18"></Cube></Cube></Envelope>`))
82 }))
83 defer empty.Close()
84 if err := s.fx.refresh(http.DefaultClient, empty.URL); err == nil {
85 t.Fatal("empty feed reported success")
86 }
87 if date, _ := get(); date != "2026-07-17" {
88 t.Fatalf("empty feed replaced the snapshot (date %q)", date)
89 }
90}
91