mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-08-07 01:33:52 +00:00
feat(rubick): rename project and add production release bundle
This commit is contained in:
commit
fab6cf26eb
33 changed files with 11554 additions and 0 deletions
141
tests/go/cli_test.go
Normal file
141
tests/go/cli_test.go
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
package gotests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
repoRootPath string
|
||||
testBinPath string
|
||||
)
|
||||
|
||||
func repoRoot() string {
|
||||
return repoRootPath
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
root, err := filepath.Abs("../..")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "resolve repo root: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
repoRootPath = root
|
||||
|
||||
binDir := filepath.Join(root, ".bin")
|
||||
if err := os.MkdirAll(binDir, 0o755); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "create .bin dir: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testBinPath = filepath.Join(binDir, "rubick-test")
|
||||
build := exec.Command("go", "build", "-o", testBinPath, "./cmd/rubick")
|
||||
build.Dir = root
|
||||
build.Stdout = os.Stdout
|
||||
build.Stderr = os.Stderr
|
||||
if err := build.Run(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "build test binary: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
code := m.Run()
|
||||
_ = os.Remove(testBinPath)
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func runCLI(t *testing.T, args ...string) (int, string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command(testBinPath, args...)
|
||||
cmd.Dir = repoRoot()
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.Stdout = &buf
|
||||
cmd.Stderr = &buf
|
||||
|
||||
err := cmd.Run()
|
||||
if err == nil {
|
||||
return 0, buf.String()
|
||||
}
|
||||
if ee, ok := err.(*exec.ExitError); ok {
|
||||
return ee.ExitCode(), buf.String()
|
||||
}
|
||||
t.Fatalf("failed to run command %v: %v", args, err)
|
||||
return -1, ""
|
||||
}
|
||||
|
||||
func runCLILive(t *testing.T, env map[string]string, args ...string) (int, string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command(testBinPath, args...)
|
||||
cmd.Dir = repoRoot()
|
||||
cmd.Env = os.Environ()
|
||||
for k, v := range env {
|
||||
cmd.Env = append(cmd.Env, k+"="+v)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.Stdout = &buf
|
||||
cmd.Stderr = &buf
|
||||
|
||||
err := cmd.Run()
|
||||
if err == nil {
|
||||
return 0, buf.String()
|
||||
}
|
||||
if ee, ok := err.(*exec.ExitError); ok {
|
||||
return ee.ExitCode(), buf.String()
|
||||
}
|
||||
t.Fatalf("failed to run command %v: %v", args, err)
|
||||
return -1, ""
|
||||
}
|
||||
|
||||
func TestCLIHelpExitCodes(t *testing.T) {
|
||||
cases := [][]string{
|
||||
{"--help"},
|
||||
{"msn", "--help"},
|
||||
{"msn", "screener", "--help"},
|
||||
{"msn", "fetch", "--help"},
|
||||
{"msn", "fetch-all", "--help"},
|
||||
{"msn", "lookup", "--help"},
|
||||
{"news", "--help"},
|
||||
{"export", "--help"},
|
||||
{"extractor", "--help"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
code, out := runCLI(t, c...)
|
||||
if code != 0 {
|
||||
t.Fatalf("expected exit 0 for %v, got %d\n%s", c, code, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCLIErrorExitCodes(t *testing.T) {
|
||||
cases := [][]string{
|
||||
{"unknown"},
|
||||
{"msn"},
|
||||
{"news"},
|
||||
{"export"},
|
||||
{"extractor"},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
code, _ := runCLI(t, c...)
|
||||
if code == 0 {
|
||||
t.Fatalf("expected non-zero exit for %v", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCLILookup(t *testing.T) {
|
||||
code, out := runCLI(t, "msn", "lookup", "BBCA")
|
||||
if code != 0 {
|
||||
t.Fatalf("expected success, got %d\n%s", code, out)
|
||||
}
|
||||
if !strings.Contains(out, "BBCA") {
|
||||
t.Fatalf("expected output to contain BBCA, got:\n%s", out)
|
||||
}
|
||||
}
|
||||
67
tests/go/live_e2e_test.go
Normal file
67
tests/go/live_e2e_test.go
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package gotests
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func isTransientNetworkErr(out string) bool {
|
||||
s := strings.ToLower(out)
|
||||
patterns := []string{
|
||||
"no such host", "timeout", "tempor", "connection reset", "connection refused", "429",
|
||||
}
|
||||
for _, p := range patterns {
|
||||
if strings.Contains(s, p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestLiveMSNScreener(t *testing.T) {
|
||||
if os.Getenv("RUN_LIVE_E2E") != "1" {
|
||||
t.Skip("set RUN_LIVE_E2E=1 to run live tests")
|
||||
}
|
||||
|
||||
outFile := filepath.Join(repoRoot(), "output", "live_test_screener.json")
|
||||
code, out := runCLILive(t, nil,
|
||||
"msn", "screener",
|
||||
"--region", "id",
|
||||
"--filter", "large-cap",
|
||||
"--limit", "1",
|
||||
"--output", outFile,
|
||||
)
|
||||
if code != 0 {
|
||||
if isTransientNetworkErr(out) {
|
||||
t.Skipf("transient/live network issue: %s", out)
|
||||
}
|
||||
t.Fatalf("live screener failed: %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLiveNewsQuery(t *testing.T) {
|
||||
if os.Getenv("RUN_LIVE_E2E") != "1" {
|
||||
t.Skip("set RUN_LIVE_E2E=1 to run live tests")
|
||||
}
|
||||
if os.Getenv("BRAVE_API_KEY") == "" {
|
||||
t.Skip("BRAVE_API_KEY not set")
|
||||
}
|
||||
|
||||
outFile := filepath.Join(repoRoot(), "output", "live_test_news.json")
|
||||
code, out := runCLILive(t, nil,
|
||||
"news", "IHSG",
|
||||
"--from", "2026-03-04",
|
||||
"--to", "2026-03-06",
|
||||
"--count", "1",
|
||||
"--concurrency", "1",
|
||||
"--output", outFile,
|
||||
)
|
||||
if code != 0 {
|
||||
if isTransientNetworkErr(out) {
|
||||
t.Skipf("transient/live network issue: %s", out)
|
||||
}
|
||||
t.Fatalf("live news failed: %s", out)
|
||||
}
|
||||
}
|
||||
49
tests/test_export_simple.py
Normal file
49
tests/test_export_simple.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import json
|
||||
import sqlite3
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from scripts.export_simple import export_csv, export_json, export_xlsx
|
||||
|
||||
|
||||
class ExportSimpleTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp = tempfile.TemporaryDirectory()
|
||||
self.base = Path(self.tmp.name)
|
||||
self.db = self.base / "test.db"
|
||||
conn = sqlite3.connect(self.db)
|
||||
conn.execute("CREATE TABLE stocks (id TEXT, ticker TEXT)")
|
||||
conn.execute("INSERT INTO stocks VALUES ('1','BBCA')")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def tearDown(self):
|
||||
self.tmp.cleanup()
|
||||
|
||||
def test_export_json(self):
|
||||
conn = sqlite3.connect(self.db)
|
||||
out = self.base / "json"
|
||||
export_json(conn, out, ["stocks"])
|
||||
conn.close()
|
||||
data = json.loads((out / "stocks.json").read_text())
|
||||
self.assertEqual(data[0]["ticker"], "BBCA")
|
||||
|
||||
def test_export_csv(self):
|
||||
conn = sqlite3.connect(self.db)
|
||||
out = self.base / "csv"
|
||||
export_csv(conn, out, ["stocks"])
|
||||
conn.close()
|
||||
text = (out / "stocks.csv").read_text()
|
||||
self.assertIn("BBCA", text)
|
||||
|
||||
def test_export_xlsx(self):
|
||||
conn = sqlite3.connect(self.db)
|
||||
out = self.base / "out.xlsx"
|
||||
export_xlsx(conn, out, ["stocks"])
|
||||
conn.close()
|
||||
self.assertTrue(out.exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue