Added tests for astronomical data. Let's merge this for now as 0.0.7
This commit is contained in:
parent
7ffd3943e0
commit
0608c4ecaa
141
astroinfo_test.go
Normal file
141
astroinfo_test.go
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Winni Neessen <wn@neessen.dev>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
package meteologix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestClient_AstronomicalInfoByCoordinates(t *testing.T) {
|
||||||
|
la := 52.5067296
|
||||||
|
lo := 13.2599306
|
||||||
|
loc, err := time.LoadLocation("Europe/Berlin")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to load time location data for Europe/Berlin: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rt := time.Date(2023, 5, 28, 15, 8, 33, 0, loc)
|
||||||
|
nfmt := time.Date(2023, 6, 4, 5, 43, 56, 0, loc)
|
||||||
|
nnmt := time.Date(2023, 6, 18, 6, 39, 10, 0, loc)
|
||||||
|
c := New(withMockAPI())
|
||||||
|
ai, err := c.AstronomicalInfoByCoordinates(la, lo)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to fetch astronomical information: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ai.Latitude != la {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected lat: %f, got: %f", la,
|
||||||
|
ai.Latitude)
|
||||||
|
}
|
||||||
|
if ai.Longitude != lo {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected lon: %f, got: %f", lo,
|
||||||
|
ai.Longitude)
|
||||||
|
}
|
||||||
|
if ai.Run.UnixMilli() != rt.UnixMilli() {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected run time: %s, got: %s",
|
||||||
|
rt.String(), ai.Run.String())
|
||||||
|
}
|
||||||
|
if ai.TimeZone != loc.String() {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected time zone: %s, got: %s",
|
||||||
|
loc.String(), ai.TimeZone)
|
||||||
|
}
|
||||||
|
if ai.NextFullMoon.UnixMilli() != nfmt.UnixMilli() {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected next full moon: %s, got: %s",
|
||||||
|
nfmt.String(), ai.NextFullMoon.String())
|
||||||
|
}
|
||||||
|
if ai.NextNewMoon.UnixMilli() != nnmt.UnixMilli() {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected next new moon: %s, got: %s",
|
||||||
|
nnmt.String(), ai.NextNewMoon.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_AstronomicalInfoByLocation(t *testing.T) {
|
||||||
|
la := 52.5067296
|
||||||
|
lo := 13.2599306
|
||||||
|
loc, err := time.LoadLocation("Europe/Berlin")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to load time location data for Europe/Berlin: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rt := time.Date(2023, 5, 28, 15, 8, 33, 0, loc)
|
||||||
|
nfmt := time.Date(2023, 6, 4, 5, 43, 56, 0, loc)
|
||||||
|
nnmt := time.Date(2023, 6, 18, 6, 39, 10, 0, loc)
|
||||||
|
c := New(withMockAPI())
|
||||||
|
ai, err := c.AstronomicalInfoByLocation("Berlin, Germany")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to fetch astronomical information: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ai.Latitude != la {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected lat: %f, got: %f", la,
|
||||||
|
ai.Latitude)
|
||||||
|
}
|
||||||
|
if ai.Longitude != lo {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected lon: %f, got: %f", lo,
|
||||||
|
ai.Longitude)
|
||||||
|
}
|
||||||
|
if ai.Run.UnixMilli() != rt.UnixMilli() {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected run time: %s, got: %s",
|
||||||
|
rt.String(), ai.Run.String())
|
||||||
|
}
|
||||||
|
if ai.TimeZone != loc.String() {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected time zone: %s, got: %s",
|
||||||
|
loc.String(), ai.TimeZone)
|
||||||
|
}
|
||||||
|
if ai.NextFullMoon.UnixMilli() != nfmt.UnixMilli() {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected next full moon: %s, got: %s",
|
||||||
|
nfmt.String(), ai.NextFullMoon.String())
|
||||||
|
}
|
||||||
|
if ai.NextNewMoon.UnixMilli() != nnmt.UnixMilli() {
|
||||||
|
t.Errorf("AstronomicalInfoByCoordinates failed, expected next new moon: %s, got: %s",
|
||||||
|
nnmt.String(), ai.NextNewMoon.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAstronomicalInfo_SunsetByDateString(t *testing.T) {
|
||||||
|
la := 52.5067296
|
||||||
|
lo := 13.2599306
|
||||||
|
loc, err := time.LoadLocation("Europe/Berlin")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to load time location data for Europe/Berlin: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ti := time.Date(2023, 5, 28, 21, 16, 37, 0, loc)
|
||||||
|
c := New(withMockAPI())
|
||||||
|
ai, err := c.AstronomicalInfoByCoordinates(la, lo)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to fetch astronomical information: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !ai.SunsetByTime(ti).IsAvailable() {
|
||||||
|
t.Errorf("SunsetByTime failed, expected entry, but got 'not available'")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ai.SunsetByTime(ti).Value().UnixMilli() != ti.UnixMilli() {
|
||||||
|
t.Errorf("SunsetByTime failed, expected sunset: %s, got: %s",
|
||||||
|
ti.String(), ai.SunsetByTime(ti).Value().String())
|
||||||
|
}
|
||||||
|
if !ai.SunsetByDateString(ti.Format(DateFormat)).IsAvailable() {
|
||||||
|
t.Errorf("SunsetByDateString failed, expected entry, but got 'not available'")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ai.SunsetByTime(ti).String() != ti.String() {
|
||||||
|
t.Errorf("SunsetByTime failed, expected sunset: %s, got: %s",
|
||||||
|
ti.String(), ai.SunsetByTime(ti).String())
|
||||||
|
}
|
||||||
|
if ai.SunsetByDateString(ti.Format(DateFormat)).Value().UnixMilli() != ti.UnixMilli() {
|
||||||
|
t.Errorf("SunsetByDateString failed, expected sunset: %s, got: %s",
|
||||||
|
ti.String(), ai.SunsetByDateString(ti.Format(DateFormat)).Value().String())
|
||||||
|
}
|
||||||
|
ti = time.Time{}
|
||||||
|
if ai.SunsetByTime(ti).IsAvailable() {
|
||||||
|
t.Errorf("SunsetByTime failed, expected no entry, but got: %s",
|
||||||
|
ai.SunsetByTime(ti).Value().String())
|
||||||
|
}
|
||||||
|
if !ai.SunsetByTime(ti).Value().IsZero() {
|
||||||
|
t.Errorf("SunsetByTime failed, expected no entry, but got: %s",
|
||||||
|
ai.SunsetByTime(ti).Value().String())
|
||||||
|
}
|
||||||
|
}
|
17
datatype.go
17
datatype.go
|
@ -16,7 +16,7 @@ const DataUnavailable = "Data unavailable"
|
||||||
|
|
||||||
// DateFormat is the parsing format that is used for datetime strings
|
// DateFormat is the parsing format that is used for datetime strings
|
||||||
// that only hold the date but no time
|
// that only hold the date but no time
|
||||||
const DateFormat = "2006-02-01"
|
const DateFormat = "2006-01-02"
|
||||||
|
|
||||||
// Enum for different Fieldname values
|
// Enum for different Fieldname values
|
||||||
const (
|
const (
|
||||||
|
@ -120,7 +120,8 @@ type WeatherData struct {
|
||||||
// of an Observation
|
// of an Observation
|
||||||
type Fieldname int
|
type Fieldname int
|
||||||
|
|
||||||
// UnmarshalJSON interprets the API datestamp and converts it into a time.Time type
|
// UnmarshalJSON interprets the API datestamp and converts it into a
|
||||||
|
// time.Time type
|
||||||
func (a *APIDate) UnmarshalJSON(s []byte) error {
|
func (a *APIDate) UnmarshalJSON(s []byte) error {
|
||||||
d := string(s)
|
d := string(s)
|
||||||
d = strings.ReplaceAll(d, `"`, ``)
|
d = strings.ReplaceAll(d, `"`, ``)
|
||||||
|
@ -128,17 +129,7 @@ func (a *APIDate) UnmarshalJSON(s []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var pd time.Time
|
pd, err := time.Parse(DateFormat, d)
|
||||||
var err error
|
|
||||||
switch len(d) {
|
|
||||||
case 10:
|
|
||||||
pd, err = time.Parse(DateFormat, d)
|
|
||||||
case 20:
|
|
||||||
pd, err = time.Parse(time.RFC3339, d)
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("failed to parse JSON string as API date: " +
|
|
||||||
"unknown input date format")
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse JSON string as APIDate string: %w", err)
|
return fmt.Errorf("failed to parse JSON string as APIDate string: %w", err)
|
||||||
}
|
}
|
||||||
|
|
37
datatype_test.go
Normal file
37
datatype_test.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Winni Neessen <wn@neessen.dev>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
package meteologix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAPIDate_UnmarshalJSON(t *testing.T) {
|
||||||
|
type x struct {
|
||||||
|
Date APIDate `json:"date"`
|
||||||
|
}
|
||||||
|
okd := []byte(`{"date":"2023-05-28"}`)
|
||||||
|
nokd := []byte(`{"date":"2023-05-32"}`)
|
||||||
|
null := []byte(`{"date":null}`)
|
||||||
|
var d x
|
||||||
|
if err := json.Unmarshal(okd, &d); err != nil {
|
||||||
|
t.Errorf("APIDate_UnmarshalJSON failed: %s", err)
|
||||||
|
}
|
||||||
|
if d.Date.Format(DateFormat) != "2023-05-28" {
|
||||||
|
t.Errorf("APIDate_UnmarshalJSON failed, expected: %s, but got: %s",
|
||||||
|
"2023-05-28", d.Date.String())
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(nokd, &d); err == nil {
|
||||||
|
t.Errorf("APIDate_UnmarshalJSON was supposed to fail, but didn't")
|
||||||
|
}
|
||||||
|
d = x{}
|
||||||
|
if err := json.Unmarshal(null, &d); err != nil {
|
||||||
|
t.Errorf("APIDate_UnmarshalJSON failed: %s", err)
|
||||||
|
}
|
||||||
|
if !d.Date.IsZero() {
|
||||||
|
t.Errorf("APIDate_UnmarshalJSON with null was supposed to be empty, but got: %s",
|
||||||
|
d.Date.String())
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,13 @@ func (dt DateTime) IsAvailable() bool {
|
||||||
// Value will return time.Time with a zero value instead.
|
// Value will return time.Time with a zero value instead.
|
||||||
func (dt DateTime) Value() time.Time {
|
func (dt DateTime) Value() time.Time {
|
||||||
if dt.na {
|
if dt.na {
|
||||||
return time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC)
|
return time.Time{}
|
||||||
}
|
}
|
||||||
return dt.dv
|
return dt.dv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String satisfies the fmt.Stringer interface for the DateTime
|
||||||
|
// type
|
||||||
|
func (dt DateTime) String() string {
|
||||||
|
return dt.dv.String()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue