tahamajs/IE / Projects /cli /main_test.go
tahamajs's picture
download
raw
5.2 kB
package main
import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
)
// TestParseArgs verifies that value-flag-aware parser correctly separates
// boolean flags, value flags, and positional arguments.
func TestParseArgs(t *testing.T) {
// Case 1: Deploy with value flag and boolean flags
args := []string{"deploy", "--file", "tool.html", "--private", "--pro"}
parsed := parseArgs(args)
cmd := ""
if len(parsed.Positional) > 0 {
cmd = parsed.Positional[0]
}
if cmd != "deploy" {
t.Errorf("Expected command 'deploy', got '%s'", cmd)
}
if parsed.Get("--file", "-f") != "tool.html" {
t.Errorf("Expected --file value 'tool.html', got '%s'", parsed.Get("--file", "-f"))
}
if !parsed.Has("--private", "") {
t.Errorf("Expected --private boolean flag to be true")
}
if !parsed.Has("--pro", "") {
t.Errorf("Expected --pro boolean flag to be true")
}
// Case 2: Positional arguments shouldn't be consumed as values for boolean flags
args2 := []string{"deploy", "--public", "some-extra-arg.html"}
parsed2 := parseArgs(args2)
if !parsed2.Has("--public", "") {
t.Errorf("Expected --public to be present")
}
// 'some-extra-arg.html' should be treated as a positional arg, not the value of --public
foundPositional := false
for _, p := range parsed2.Positional {
if p == "some-extra-arg.html" {
foundPositional = true
}
}
if !foundPositional {
t.Errorf("Expected 'some-extra-arg.html' to be a positional argument, but was ignored or consumed")
}
}
// TestTruncateOrPad verifies rune padding and length limits
func TestTruncateOrPad(t *testing.T) {
s1 := truncateOrPad("hello", 10)
if len(s1) != 10 {
t.Errorf("Expected padded string length 10, got %d", len(s1))
}
s2 := truncateOrPad("this is a very long string", 5)
if s2 != "this…" {
t.Errorf("Expected truncated string 'this…', got '%s'", s2)
}
// Rune-aware checks (non-ASCII characters)
s3 := truncateOrPad("سلام", 6)
// سلام has 4 runes, should be padded with 2 spaces
if len(s3) != 10 { // length of runes/bytes might differ, let's verify character count
runes := []rune(s3)
if len(runes) != 6 {
t.Errorf("Expected 6 runes, got %d in '%s'", len(runes), s3)
}
}
}
// TestFormatDate verifies ISO timezone formatting
func TestFormatDate(t *testing.T) {
res1 := formatDate("2026-07-11T11:15:00Z")
if res1 == "—" {
t.Errorf("Expected formatted date, got default empty sign")
}
res2 := formatDate(12345) // invalid format
if res2 != "—" {
t.Errorf("Expected '—' for invalid timestamp types, got '%s'", res2)
}
}
// TestConfigStore verifies loadConfig and saveConfig file permissions (0600)
func TestConfigStore(t *testing.T) {
tempDir, err := os.MkdirTemp("", "ie-cli-test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
// Mock getConfigPath to write to tempDir
originalHome := os.Getenv("HOME")
os.Setenv("HOME", tempDir)
defer os.Setenv("HOME", originalHome)
cfg := &Config{
Token: "test-jwt-token-xyz",
Username: "tahamajs",
Host: "http://localhost:9092",
}
err = saveConfig(cfg)
if err != nil {
t.Fatalf("Failed to save config: %v", err)
}
// Verify file permission is 0600
cfgPath := filepath.Join(tempDir, ".ie-research-cli.json")
info, err := os.Stat(cfgPath)
if err != nil {
t.Fatalf("Failed to stat config file: %v", err)
}
mode := info.Mode().Perm()
if mode != 0600 {
t.Errorf("Expected config file permission 0600, got %o", mode)
}
// Load and verify fields
loaded, err := loadConfig()
if err != nil {
t.Fatalf("Failed to load config: %v", err)
}
if loaded.Username != "tahamajs" || loaded.Token != "test-jwt-token-xyz" {
t.Errorf("Loaded config values mismatch: username=%s, token=%s", loaded.Username, loaded.Token)
}
}
// TestFetchAPI verifies integration with REST APIs
func TestFetchAPI(t *testing.T) {
// Create mock HTTP server simulating Spring Boot REST endpoints
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Verify method and headers
if r.Method != "POST" {
t.Errorf("Expected POST request, got %s", r.Method)
}
if auth := r.Header.Get("Authorization"); auth != "Bearer dummy-token" {
t.Errorf("Expected Bearer Authorization header, got '%s'", auth)
}
// Read and verify body
bodyBytes, _ := io.ReadAll(r.Body)
var payload map[string]interface{}
json.Unmarshal(bodyBytes, &payload)
if payload["name"] != "Bibtex Converter" {
t.Errorf("Expected tool name 'Bibtex Converter', got '%v'", payload["name"])
}
// Return success response
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"success":true,"toolId":42,"message":"Deployed successfully"}`))
}))
defer server.Close()
payload := map[string]interface{}{
"name": "Bibtex Converter",
"version": "1.0.0",
}
resp, err := fetchAPI("POST", server.URL, payload, "dummy-token")
if err != nil {
t.Fatalf("fetchAPI failed: %v", err)
}
if resp["success"] != true || resp["toolId"].(float64) != 42 {
t.Errorf("Expected response toolId=42 and success=true, got: %v", resp)
}
}

Xet Storage Details

Size:
5.2 kB
·
Xet hash:
2a0080dc11bd99ebe495f860e297ea120b1b9fc62a2268835cbc162a466b3192

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.