- 新增日食、月食、本地可见性、中心线、半影区域、SVG 图示与沙罗周期信息 - 新增行星冲合、留、方照、物理星历、视直径、相位、亮肢角、轨道节点等计算 - 新增木星伽利略卫星位置、现象与接触事件计算 - 新增恒星星表、星座判定、自行修正与观测辅助能力 - 新增 coord、formula、orbit、sundial、lite/sun、lite/moon 等扩展包 - 完善农历年号、月相英文别名、视差角、大气质量、折射、日晷与双星计算 - 增加 NASA、JPL Horizons、IMCCE 等回归测试数据与基线测试 - 重构基础算法文件组织,补充大量公开 API 注释和语义回归测试 - 更新中文和英文 README,补充示例、精度说明、SVG 配图
143 lines
4.0 KiB
Go
143 lines
4.0 KiB
Go
package svg
|
|
|
|
import (
|
|
"math"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestLocalSolarEclipseSVG(t *testing.T) {
|
|
svg, ok := LocalSolarEclipseSVG(
|
|
time.Date(2024, 4, 8, 12, 0, 0, 0, time.UTC),
|
|
-96.7970,
|
|
32.7767,
|
|
0,
|
|
LocalSolarEclipseSVGOptions{Width: 640, Height: 480, Step: 5 * time.Minute},
|
|
)
|
|
if !ok {
|
|
t.Fatalf("expected local solar eclipse SVG")
|
|
}
|
|
for _, want := range []string{"<svg", "站心日全食", "全局路径", "阶段视圆图", "黄道", "C1", "食既", "食甚", "生光", "C4", "方位", "左东右西", "UTC+8", "太阳位于", "沙罗", "全食历时", `fill="#efefed"`, `class="contact-point"`} {
|
|
if !strings.Contains(svg, want) {
|
|
t.Fatalf("SVG missing %q", want)
|
|
}
|
|
}
|
|
for _, notWant := range []string{"中心食始", "中心食终"} {
|
|
if strings.Contains(svg, notWant) {
|
|
t.Fatalf("SVG should not contain %q for total eclipse", notWant)
|
|
}
|
|
}
|
|
if got := strings.Count(svg, `class="event-moon"`); got != 3 {
|
|
t.Fatalf("event moon count = %d, want 3", got)
|
|
}
|
|
if got := strings.Count(svg, `class="stage-moon"`); got != 5 {
|
|
t.Fatalf("stage moon count = %d, want 5", got)
|
|
}
|
|
if got := strings.Count(svg, `class="event-center"`); got != 5 {
|
|
t.Fatalf("event center count = %d, want 5", got)
|
|
}
|
|
}
|
|
|
|
func TestLocalSolarEclipseSVGEnglishOption(t *testing.T) {
|
|
svg, ok := LocalSolarEclipseSVG(
|
|
time.Date(2024, 4, 8, 12, 0, 0, 0, time.UTC),
|
|
-96.7970,
|
|
32.7767,
|
|
0,
|
|
LocalSolarEclipseSVGOptions{Language: "en", Location: time.UTC},
|
|
)
|
|
if !ok {
|
|
t.Fatalf("expected local solar eclipse SVG")
|
|
}
|
|
for _, want := range []string{"Local Solar Eclipse", "Greatest", "PA", "East is left", "Ecliptic", "Contacts (UTC)", "Sun in", "Solar Saros", "Totality"} {
|
|
if !strings.Contains(svg, want) {
|
|
t.Fatalf("SVG missing %q", want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLocalSolarEclipseSVGCustomText(t *testing.T) {
|
|
svg, ok := LocalSolarEclipseSVG(
|
|
time.Date(2024, 4, 8, 12, 0, 0, 0, time.UTC),
|
|
-96.7970,
|
|
32.7767,
|
|
0,
|
|
LocalSolarEclipseSVGOptions{
|
|
Title: "Custom solar title",
|
|
SummaryText: "Custom solar summary",
|
|
GreatestText: "Custom solar greatest",
|
|
MetaText: "Custom solar meta",
|
|
OverviewTitle: "Custom solar overview",
|
|
PhasePanelsTitle: "Custom solar phases",
|
|
ContactsTitle: "Custom solar contacts",
|
|
DirectionText: "Custom solar direction",
|
|
FooterNote: "Custom solar footer",
|
|
},
|
|
)
|
|
if !ok {
|
|
t.Fatalf("expected local solar eclipse SVG")
|
|
}
|
|
for _, want := range []string{
|
|
"Custom solar title",
|
|
"Custom solar summary",
|
|
"Custom solar greatest",
|
|
"Custom solar meta",
|
|
"Custom solar overview",
|
|
"Custom solar phases",
|
|
"Custom solar contacts",
|
|
"Custom solar direction",
|
|
"Custom solar footer",
|
|
} {
|
|
if !strings.Contains(svg, want) {
|
|
t.Fatalf("SVG missing custom text %q", want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLocalSolarEclipseSVGStagePanelsShareScale(t *testing.T) {
|
|
svg, ok := LocalSolarEclipseSVG(
|
|
time.Date(2024, 4, 8, 12, 0, 0, 0, time.UTC),
|
|
-96.7970,
|
|
32.7767,
|
|
0,
|
|
LocalSolarEclipseSVGOptions{Width: 640, Height: 480, Step: 5 * time.Minute},
|
|
)
|
|
if !ok {
|
|
t.Fatalf("expected local solar eclipse SVG")
|
|
}
|
|
re := regexp.MustCompile(`<circle cx="[-0-9.]+" cy="[-0-9.]+" r="([0-9.]+)" fill="url\(#se-sun\)" stroke="#c78211" stroke-width="1"/>`)
|
|
matches := re.FindAllStringSubmatch(svg, -1)
|
|
if got, want := len(matches), 5; got != want {
|
|
t.Fatalf("stage sun count = %d, want %d", got, want)
|
|
}
|
|
first, err := strconv.ParseFloat(matches[0][1], 64)
|
|
if err != nil {
|
|
t.Fatalf("parse first radius: %v", err)
|
|
}
|
|
for i := 1; i < len(matches); i++ {
|
|
radius, err := strconv.ParseFloat(matches[i][1], 64)
|
|
if err != nil {
|
|
t.Fatalf("parse radius %d: %v", i, err)
|
|
}
|
|
if math.Abs(radius-first) > 1e-9 {
|
|
t.Fatalf("stage panel radii differ: first=%f current=%f", first, radius)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLocalSolarEclipseSVGNoEvent(t *testing.T) {
|
|
_, ok := LocalSolarEclipseSVG(
|
|
time.Date(2024, 5, 15, 12, 0, 0, 0, time.UTC),
|
|
-96.7970,
|
|
32.7767,
|
|
0,
|
|
LocalSolarEclipseSVGOptions{},
|
|
)
|
|
if ok {
|
|
t.Fatalf("unexpected local solar eclipse SVG for no-event date")
|
|
}
|
|
}
|