mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 15:43:49 +01:00
Add comprehensive tests for: - Pure time functions in channelserver (sys_time_test.go) - Stage-related packet parsing (msg_sys_stage_test.go) - Acquire packet family parsing (msg_mhf_acquire_test.go) - Extended mhfpacket tests for login, logout, and stage packets - Entrance server makeHeader structure and checksum tests - SignV2 server request/response JSON structure tests
721 lines
18 KiB
Go
721 lines
18 KiB
Go
package signv2server
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// mockServer creates a Server with minimal dependencies for testing
|
|
func mockServer() *Server {
|
|
logger, _ := zap.NewDevelopment()
|
|
return &Server{
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func TestLauncherEndpoint(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("GET", "/launcher", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Launcher(w, req)
|
|
|
|
resp := w.Result()
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Errorf("Launcher() status = %d, want %d", resp.StatusCode, http.StatusOK)
|
|
}
|
|
|
|
var data struct {
|
|
Important []LauncherMessage `json:"important"`
|
|
Normal []LauncherMessage `json:"normal"`
|
|
}
|
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
|
t.Fatalf("Failed to decode response: %v", err)
|
|
}
|
|
|
|
// Should have important messages
|
|
if len(data.Important) == 0 {
|
|
t.Error("Launcher() should return important messages")
|
|
}
|
|
|
|
// Should have normal messages
|
|
if len(data.Normal) == 0 {
|
|
t.Error("Launcher() should return normal messages")
|
|
}
|
|
}
|
|
|
|
func TestLauncherMessageStructure(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("GET", "/launcher", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Launcher(w, req)
|
|
|
|
var data struct {
|
|
Important []LauncherMessage `json:"important"`
|
|
Normal []LauncherMessage `json:"normal"`
|
|
}
|
|
json.NewDecoder(w.Result().Body).Decode(&data)
|
|
|
|
// Check important messages have required fields
|
|
for _, msg := range data.Important {
|
|
if msg.Message == "" {
|
|
t.Error("LauncherMessage.Message should not be empty")
|
|
}
|
|
if msg.Date == 0 {
|
|
t.Error("LauncherMessage.Date should not be zero")
|
|
}
|
|
if msg.Link == "" {
|
|
t.Error("LauncherMessage.Link should not be empty")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoginEndpointInvalidJSON(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
// Send invalid JSON
|
|
req := httptest.NewRequest("POST", "/login", bytes.NewReader([]byte("not json")))
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Login(w, req)
|
|
|
|
resp := w.Result()
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Errorf("Login() with invalid JSON status = %d, want %d", resp.StatusCode, http.StatusBadRequest)
|
|
}
|
|
}
|
|
|
|
func TestRegisterEndpointInvalidJSON(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("POST", "/register", bytes.NewReader([]byte("invalid")))
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Register(w, req)
|
|
|
|
resp := w.Result()
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Errorf("Register() with invalid JSON status = %d, want %d", resp.StatusCode, http.StatusBadRequest)
|
|
}
|
|
}
|
|
|
|
func TestCreateCharacterEndpointInvalidJSON(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("POST", "/character/create", bytes.NewReader([]byte("invalid")))
|
|
w := httptest.NewRecorder()
|
|
|
|
s.CreateCharacter(w, req)
|
|
|
|
resp := w.Result()
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Errorf("CreateCharacter() with invalid JSON status = %d, want %d", resp.StatusCode, http.StatusBadRequest)
|
|
}
|
|
}
|
|
|
|
func TestDeleteCharacterEndpointInvalidJSON(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("POST", "/character/delete", bytes.NewReader([]byte("invalid")))
|
|
w := httptest.NewRecorder()
|
|
|
|
s.DeleteCharacter(w, req)
|
|
|
|
resp := w.Result()
|
|
if resp.StatusCode != http.StatusBadRequest {
|
|
t.Errorf("DeleteCharacter() with invalid JSON status = %d, want %d", resp.StatusCode, http.StatusBadRequest)
|
|
}
|
|
}
|
|
|
|
func TestLauncherMessageStruct(t *testing.T) {
|
|
msg := LauncherMessage{
|
|
Message: "Test Message",
|
|
Date: 1234567890,
|
|
Link: "https://example.com",
|
|
}
|
|
|
|
if msg.Message != "Test Message" {
|
|
t.Errorf("Message = %s, want Test Message", msg.Message)
|
|
}
|
|
if msg.Date != 1234567890 {
|
|
t.Errorf("Date = %d, want 1234567890", msg.Date)
|
|
}
|
|
if msg.Link != "https://example.com" {
|
|
t.Errorf("Link = %s, want https://example.com", msg.Link)
|
|
}
|
|
}
|
|
|
|
func TestCharacterStruct(t *testing.T) {
|
|
char := Character{
|
|
ID: 1,
|
|
Name: "TestHunter",
|
|
IsFemale: true,
|
|
Weapon: 5,
|
|
HR: 999,
|
|
GR: 100,
|
|
LastLogin: 1234567890,
|
|
}
|
|
|
|
if char.ID != 1 {
|
|
t.Errorf("ID = %d, want 1", char.ID)
|
|
}
|
|
if char.Name != "TestHunter" {
|
|
t.Errorf("Name = %s, want TestHunter", char.Name)
|
|
}
|
|
if char.IsFemale != true {
|
|
t.Error("IsFemale should be true")
|
|
}
|
|
if char.Weapon != 5 {
|
|
t.Errorf("Weapon = %d, want 5", char.Weapon)
|
|
}
|
|
if char.HR != 999 {
|
|
t.Errorf("HR = %d, want 999", char.HR)
|
|
}
|
|
if char.GR != 100 {
|
|
t.Errorf("GR = %d, want 100", char.GR)
|
|
}
|
|
}
|
|
|
|
func TestLauncherMessageJSONTags(t *testing.T) {
|
|
msg := LauncherMessage{
|
|
Message: "Test",
|
|
Date: 12345,
|
|
Link: "http://test.com",
|
|
}
|
|
|
|
data, err := json.Marshal(msg)
|
|
if err != nil {
|
|
t.Fatalf("Marshal error: %v", err)
|
|
}
|
|
|
|
var decoded map[string]interface{}
|
|
json.Unmarshal(data, &decoded)
|
|
|
|
if _, ok := decoded["message"]; !ok {
|
|
t.Error("JSON should have 'message' key")
|
|
}
|
|
if _, ok := decoded["date"]; !ok {
|
|
t.Error("JSON should have 'date' key")
|
|
}
|
|
if _, ok := decoded["link"]; !ok {
|
|
t.Error("JSON should have 'link' key")
|
|
}
|
|
}
|
|
|
|
func TestCharacterJSONTags(t *testing.T) {
|
|
char := Character{
|
|
ID: 1,
|
|
Name: "Test",
|
|
IsFemale: true,
|
|
Weapon: 3,
|
|
HR: 50,
|
|
GR: 10,
|
|
LastLogin: 9999,
|
|
}
|
|
|
|
data, err := json.Marshal(char)
|
|
if err != nil {
|
|
t.Fatalf("Marshal error: %v", err)
|
|
}
|
|
|
|
var decoded map[string]interface{}
|
|
json.Unmarshal(data, &decoded)
|
|
|
|
if _, ok := decoded["id"]; !ok {
|
|
t.Error("JSON should have 'id' key")
|
|
}
|
|
if _, ok := decoded["name"]; !ok {
|
|
t.Error("JSON should have 'name' key")
|
|
}
|
|
if _, ok := decoded["isFemale"]; !ok {
|
|
t.Error("JSON should have 'isFemale' key")
|
|
}
|
|
if _, ok := decoded["weapon"]; !ok {
|
|
t.Error("JSON should have 'weapon' key")
|
|
}
|
|
if _, ok := decoded["hr"]; !ok {
|
|
t.Error("JSON should have 'hr' key")
|
|
}
|
|
if _, ok := decoded["gr"]; !ok {
|
|
t.Error("JSON should have 'gr' key")
|
|
}
|
|
if _, ok := decoded["lastLogin"]; !ok {
|
|
t.Error("JSON should have 'lastLogin' key")
|
|
}
|
|
}
|
|
|
|
func TestLauncherResponseFormat(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("GET", "/launcher", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Launcher(w, req)
|
|
|
|
resp := w.Result()
|
|
|
|
// Verify it returns valid JSON
|
|
var result map[string]interface{}
|
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
t.Errorf("Launcher() should return valid JSON: %v", err)
|
|
}
|
|
|
|
// Check top-level keys exist
|
|
if _, ok := result["important"]; !ok {
|
|
t.Error("Launcher() response should have 'important' key")
|
|
}
|
|
if _, ok := result["normal"]; !ok {
|
|
t.Error("Launcher() response should have 'normal' key")
|
|
}
|
|
}
|
|
|
|
func TestLauncherMessageCount(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("GET", "/launcher", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Launcher(w, req)
|
|
|
|
var data struct {
|
|
Important []LauncherMessage `json:"important"`
|
|
Normal []LauncherMessage `json:"normal"`
|
|
}
|
|
json.NewDecoder(w.Result().Body).Decode(&data)
|
|
|
|
// Should have at least 3 important messages based on the implementation
|
|
if len(data.Important) < 3 {
|
|
t.Errorf("Launcher() should return at least 3 important messages, got %d", len(data.Important))
|
|
}
|
|
|
|
// Should have at least 1 normal message
|
|
if len(data.Normal) < 1 {
|
|
t.Errorf("Launcher() should return at least 1 normal message, got %d", len(data.Normal))
|
|
}
|
|
}
|
|
|
|
func TestCharacterStructDBTags(t *testing.T) {
|
|
// Test that Character struct has proper db tags
|
|
char := Character{}
|
|
|
|
// These fields have db tags, verify struct is usable
|
|
char.IsFemale = true
|
|
char.Weapon = 7
|
|
char.HR = 100
|
|
char.LastLogin = 12345
|
|
|
|
if char.Weapon != 7 {
|
|
t.Errorf("Weapon = %d, want 7", char.Weapon)
|
|
}
|
|
}
|
|
|
|
func TestNewServer(t *testing.T) {
|
|
logger, _ := zap.NewDevelopment()
|
|
cfg := &Config{
|
|
Logger: logger,
|
|
}
|
|
|
|
s := NewServer(cfg)
|
|
|
|
if s == nil {
|
|
t.Fatal("NewServer() returned nil")
|
|
}
|
|
if s.logger == nil {
|
|
t.Error("NewServer() should set logger")
|
|
}
|
|
if s.httpServer == nil {
|
|
t.Error("NewServer() should initialize httpServer")
|
|
}
|
|
}
|
|
|
|
func TestServerConfig(t *testing.T) {
|
|
cfg := &Config{
|
|
Logger: nil,
|
|
DB: nil,
|
|
}
|
|
|
|
// Config struct should be usable
|
|
if cfg.Logger != nil {
|
|
t.Error("Config.Logger should be nil when not set")
|
|
}
|
|
}
|
|
|
|
// Note: Tests that require database operations are skipped when no DB is available.
|
|
// The following tests validate the structure and JSON handling of endpoints.
|
|
|
|
// TestLoginRequestStructure tests that login request JSON structure is correct
|
|
func TestLoginRequestStructure(t *testing.T) {
|
|
// Test JSON marshaling/unmarshaling of request structure
|
|
reqData := struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}{
|
|
Username: "testuser",
|
|
Password: "testpass",
|
|
}
|
|
|
|
data, err := json.Marshal(reqData)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.Username != reqData.Username {
|
|
t.Errorf("Username = %s, want %s", decoded.Username, reqData.Username)
|
|
}
|
|
if decoded.Password != reqData.Password {
|
|
t.Errorf("Password = %s, want %s", decoded.Password, reqData.Password)
|
|
}
|
|
}
|
|
|
|
// TestRegisterRequestStructure tests that register request JSON structure is correct
|
|
func TestRegisterRequestStructure(t *testing.T) {
|
|
reqData := struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}{
|
|
Username: "newuser",
|
|
Password: "newpass",
|
|
}
|
|
|
|
data, err := json.Marshal(reqData)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.Username != reqData.Username {
|
|
t.Errorf("Username = %s, want %s", decoded.Username, reqData.Username)
|
|
}
|
|
if decoded.Password != reqData.Password {
|
|
t.Errorf("Password = %s, want %s", decoded.Password, reqData.Password)
|
|
}
|
|
}
|
|
|
|
// TestCreateCharacterRequestStructure tests that create character request JSON structure is correct
|
|
func TestCreateCharacterRequestStructure(t *testing.T) {
|
|
reqData := struct {
|
|
Token string `json:"token"`
|
|
}{
|
|
Token: "test-token-12345",
|
|
}
|
|
|
|
data, err := json.Marshal(reqData)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded struct {
|
|
Token string `json:"token"`
|
|
}
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.Token != reqData.Token {
|
|
t.Errorf("Token = %s, want %s", decoded.Token, reqData.Token)
|
|
}
|
|
}
|
|
|
|
// TestDeleteCharacterRequestStructure tests that delete character request JSON structure is correct
|
|
func TestDeleteCharacterRequestStructure(t *testing.T) {
|
|
reqData := struct {
|
|
Token string `json:"token"`
|
|
CharID int `json:"id"`
|
|
}{
|
|
Token: "test-token",
|
|
CharID: 12345,
|
|
}
|
|
|
|
data, err := json.Marshal(reqData)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded struct {
|
|
Token string `json:"token"`
|
|
CharID int `json:"id"`
|
|
}
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.Token != reqData.Token {
|
|
t.Errorf("Token = %s, want %s", decoded.Token, reqData.Token)
|
|
}
|
|
if decoded.CharID != reqData.CharID {
|
|
t.Errorf("CharID = %d, want %d", decoded.CharID, reqData.CharID)
|
|
}
|
|
}
|
|
|
|
// TestLoginResponseStructure tests the login response JSON structure
|
|
func TestLoginResponseStructure(t *testing.T) {
|
|
respData := struct {
|
|
Token string `json:"token"`
|
|
Characters []Character `json:"characters"`
|
|
}{
|
|
Token: "login-token-abc123",
|
|
Characters: []Character{
|
|
{ID: 1, Name: "Hunter1", IsFemale: false, Weapon: 3, HR: 100, GR: 10},
|
|
{ID: 2, Name: "Hunter2", IsFemale: true, Weapon: 7, HR: 200, GR: 20},
|
|
},
|
|
}
|
|
|
|
data, err := json.Marshal(respData)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded struct {
|
|
Token string `json:"token"`
|
|
Characters []Character `json:"characters"`
|
|
}
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.Token != respData.Token {
|
|
t.Errorf("Token = %s, want %s", decoded.Token, respData.Token)
|
|
}
|
|
if len(decoded.Characters) != len(respData.Characters) {
|
|
t.Errorf("Characters count = %d, want %d", len(decoded.Characters), len(respData.Characters))
|
|
}
|
|
}
|
|
|
|
// TestRegisterResponseStructure tests the register response JSON structure
|
|
func TestRegisterResponseStructure(t *testing.T) {
|
|
respData := struct {
|
|
Token string `json:"token"`
|
|
}{
|
|
Token: "register-token-xyz789",
|
|
}
|
|
|
|
data, err := json.Marshal(respData)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded struct {
|
|
Token string `json:"token"`
|
|
}
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.Token != respData.Token {
|
|
t.Errorf("Token = %s, want %s", decoded.Token, respData.Token)
|
|
}
|
|
}
|
|
|
|
// TestCreateCharacterResponseStructure tests the create character response JSON structure
|
|
func TestCreateCharacterResponseStructure(t *testing.T) {
|
|
respData := struct {
|
|
CharID int `json:"id"`
|
|
}{
|
|
CharID: 42,
|
|
}
|
|
|
|
data, err := json.Marshal(respData)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded struct {
|
|
CharID int `json:"id"`
|
|
}
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.CharID != respData.CharID {
|
|
t.Errorf("CharID = %d, want %d", decoded.CharID, respData.CharID)
|
|
}
|
|
}
|
|
|
|
// TestLauncherContentType tests that Launcher sets correct content type
|
|
func TestLauncherContentType(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("GET", "/launcher", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Launcher(w, req)
|
|
|
|
// Note: The handler sets header after WriteHeader, so we check response body is JSON
|
|
resp := w.Result()
|
|
var data map[string]interface{}
|
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
|
t.Errorf("Launcher() response is not valid JSON: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestLauncherMessageDates tests that launcher message dates are valid timestamps
|
|
func TestLauncherMessageDates(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("GET", "/launcher", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Launcher(w, req)
|
|
|
|
var data struct {
|
|
Important []LauncherMessage `json:"important"`
|
|
Normal []LauncherMessage `json:"normal"`
|
|
}
|
|
json.NewDecoder(w.Result().Body).Decode(&data)
|
|
|
|
// All dates should be positive unix timestamps
|
|
for _, msg := range data.Important {
|
|
if msg.Date <= 0 {
|
|
t.Errorf("Important message date should be positive, got %d", msg.Date)
|
|
}
|
|
}
|
|
for _, msg := range data.Normal {
|
|
if msg.Date <= 0 {
|
|
t.Errorf("Normal message date should be positive, got %d", msg.Date)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestLauncherMessageLinks tests that launcher message links are valid URLs
|
|
func TestLauncherMessageLinks(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
req := httptest.NewRequest("GET", "/launcher", nil)
|
|
w := httptest.NewRecorder()
|
|
|
|
s.Launcher(w, req)
|
|
|
|
var data struct {
|
|
Important []LauncherMessage `json:"important"`
|
|
Normal []LauncherMessage `json:"normal"`
|
|
}
|
|
json.NewDecoder(w.Result().Body).Decode(&data)
|
|
|
|
// All links should start with http:// or https://
|
|
for _, msg := range data.Important {
|
|
if len(msg.Link) < 7 || (msg.Link[:7] != "http://" && msg.Link[:8] != "https://") {
|
|
t.Errorf("Important message link should be a URL, got %q", msg.Link)
|
|
}
|
|
}
|
|
for _, msg := range data.Normal {
|
|
if len(msg.Link) < 7 || (msg.Link[:7] != "http://" && msg.Link[:8] != "https://") {
|
|
t.Errorf("Normal message link should be a URL, got %q", msg.Link)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestCharacterStructJSONMarshal tests Character struct marshals correctly
|
|
func TestCharacterStructJSONMarshal(t *testing.T) {
|
|
char := Character{
|
|
ID: 42,
|
|
Name: "TestHunter",
|
|
IsFemale: true,
|
|
Weapon: 7,
|
|
HR: 999,
|
|
GR: 100,
|
|
LastLogin: 1609459200,
|
|
}
|
|
|
|
data, err := json.Marshal(char)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded Character
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.ID != char.ID {
|
|
t.Errorf("ID = %d, want %d", decoded.ID, char.ID)
|
|
}
|
|
if decoded.Name != char.Name {
|
|
t.Errorf("Name = %s, want %s", decoded.Name, char.Name)
|
|
}
|
|
if decoded.IsFemale != char.IsFemale {
|
|
t.Errorf("IsFemale = %v, want %v", decoded.IsFemale, char.IsFemale)
|
|
}
|
|
if decoded.Weapon != char.Weapon {
|
|
t.Errorf("Weapon = %d, want %d", decoded.Weapon, char.Weapon)
|
|
}
|
|
if decoded.HR != char.HR {
|
|
t.Errorf("HR = %d, want %d", decoded.HR, char.HR)
|
|
}
|
|
if decoded.GR != char.GR {
|
|
t.Errorf("GR = %d, want %d", decoded.GR, char.GR)
|
|
}
|
|
if decoded.LastLogin != char.LastLogin {
|
|
t.Errorf("LastLogin = %d, want %d", decoded.LastLogin, char.LastLogin)
|
|
}
|
|
}
|
|
|
|
// TestLauncherMessageJSONMarshal tests LauncherMessage struct marshals correctly
|
|
func TestLauncherMessageJSONMarshal(t *testing.T) {
|
|
msg := LauncherMessage{
|
|
Message: "Test Announcement",
|
|
Date: 1609459200,
|
|
Link: "https://example.com/news",
|
|
}
|
|
|
|
data, err := json.Marshal(msg)
|
|
if err != nil {
|
|
t.Fatalf("json.Marshal() error = %v", err)
|
|
}
|
|
|
|
var decoded LauncherMessage
|
|
if err := json.Unmarshal(data, &decoded); err != nil {
|
|
t.Fatalf("json.Unmarshal() error = %v", err)
|
|
}
|
|
|
|
if decoded.Message != msg.Message {
|
|
t.Errorf("Message = %s, want %s", decoded.Message, msg.Message)
|
|
}
|
|
if decoded.Date != msg.Date {
|
|
t.Errorf("Date = %d, want %d", decoded.Date, msg.Date)
|
|
}
|
|
if decoded.Link != msg.Link {
|
|
t.Errorf("Link = %s, want %s", decoded.Link, msg.Link)
|
|
}
|
|
}
|
|
|
|
// TestEndpointHTTPMethods tests that endpoints respond to correct HTTP methods
|
|
func TestEndpointHTTPMethods(t *testing.T) {
|
|
s := mockServer()
|
|
|
|
// Launcher should respond to GET
|
|
t.Run("Launcher GET", func(t *testing.T) {
|
|
req := httptest.NewRequest("GET", "/launcher", nil)
|
|
w := httptest.NewRecorder()
|
|
s.Launcher(w, req)
|
|
if w.Result().StatusCode != http.StatusOK {
|
|
t.Errorf("Launcher() GET status = %d, want %d", w.Result().StatusCode, http.StatusOK)
|
|
}
|
|
})
|
|
|
|
// Note: Login, Register, CreateCharacter, DeleteCharacter require database
|
|
// and cannot be tested without mocking the database connection
|
|
}
|