Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 183 additions & 0 deletions internal/app/analytics/analytics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package analytics

import (
"flag"
"os"
"path/filepath"
"testing"

ga "google.golang.org/api/analyticsreporting/v4"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/urfave/cli"
)

func TestFmtDate(t *testing.T) {
t.Parallel()
assert.Equal(t, "2024-01-15", fmtDate("20240115"))
assert.Equal(t, "0001-01-01", fmtDate("invalid"))
}

func TestUcFirst(t *testing.T) {
t.Parallel()

tests := []struct {
input string
expected string
}{
{"sessions", "Sessions"},
{"pageviews", "Pageviews"},
{"users", "Users"},
{"", ""},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
assert.Equal(t, tt.expected, ucFirst(tt.input))
})
}
}

func TestRemoveGAprefix(t *testing.T) {
t.Parallel()
assert.Equal(t, "date", removeGAprefix("ga:date"))
assert.Equal(t, "sessions", removeGAprefix("ga:sessions"))
assert.Equal(t, "noprefix", removeGAprefix("noprefix"))
}

func TestMetricName(t *testing.T) {
t.Parallel()

entry := &ga.MetricHeaderEntry{Name: "ga:sessions"}
assert.Equal(t, "ga:sessions", metricName(entry))
}

func TestProcessReportHeader(t *testing.T) {
t.Parallel()

res := &ga.GetReportsResponse{
Reports: []*ga.Report{{
ColumnHeader: &ga.ColumnHeader{
Dimensions: []string{"ga:date"},
MetricHeader: &ga.MetricHeader{
MetricHeaderEntries: []*ga.MetricHeaderEntry{
{Name: "ga:sessions"},
{Name: "ga:pageviews"},
{Name: "ga:users"},
},
},
},
}},
}
result := processReportHeader(res)
assert.Equal(t, []string{"date", "Sessions", "Pageviews", "Users"}, result)
}

func TestGenerateReportRequest(t *testing.T) {
t.Parallel()

t.Run("with default dates", func(t *testing.T) {
flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
flagSet.String("view-id", "12345", "")
flagSet.String("start-date", "2024-01-01", "")
flagSet.String("end-date", "", "")

app := cli.NewApp()
app.Flags = []cli.Flag{
cli.StringFlag{Name: "view-id"},
cli.StringFlag{Name: "start-date"},
cli.StringFlag{Name: "end-date"},
}

ctx := cli.NewContext(app, flagSet, nil)
req := generateReportRequest(ctx)
assert.Equal(t, "12345", req.ViewId)
assert.Len(t, req.DateRanges, 1)
assert.Equal(t, "2024-01-01", req.DateRanges[0].StartDate)
assert.NotEmpty(t, req.DateRanges[0].EndDate)
})

t.Run("with custom end date", func(t *testing.T) {
flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
flagSet.String("view-id", "12345", "")
flagSet.String("start-date", "2024-01-01", "")
flagSet.String("end-date", "2024-06-30", "")

app := cli.NewApp()
app.Flags = []cli.Flag{
cli.StringFlag{Name: "view-id"},
cli.StringFlag{Name: "start-date"},
cli.StringFlag{Name: "end-date"},
}

ctx := cli.NewContext(app, flagSet, nil)
req := generateReportRequest(ctx)
assert.Equal(t, "2024-06-30", req.DateRanges[0].EndDate)
})
}

func TestWriteOutput(t *testing.T) {
t.Parallel()

res := &ga.GetReportsResponse{
Reports: []*ga.Report{{
ColumnHeader: &ga.ColumnHeader{
Dimensions: []string{"ga:date"},
MetricHeader: &ga.MetricHeader{
MetricHeaderEntries: []*ga.MetricHeaderEntry{
{Name: "ga:sessions"},
},
},
},
Data: &ga.ReportData{
Rows: []*ga.ReportRow{
{
Dimensions: []string{"20240101"},
Metrics: []*ga.DateRangeValues{{Values: []string{"100"}}},
},
{
Dimensions: []string{"20240102"},
Metrics: []*ga.DateRangeValues{{Values: []string{"200"}}},
},
},
},
}},
}

t.Run("write to file", func(t *testing.T) {
tmpDir := t.TempDir()
outFile := filepath.Join(tmpDir, "output.csv")

flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
flagSet.String("output", outFile, "")

app := cli.NewApp()
app.Flags = []cli.Flag{cli.StringFlag{Name: "output"}}

ctx := cli.NewContext(app, flagSet, nil)
err := writeOutput(ctx, res)
require.NoError(t, err)

data, err := os.ReadFile(outFile)
require.NoError(t, err)
assert.Contains(t, string(data), "date,Sessions")
assert.Contains(t, string(data), "2024-01-01,100")
assert.Contains(t, string(data), "2024-01-02,200")
})

t.Run("write to tmp file", func(t *testing.T) {
tmpDir := t.TempDir()
outFile := filepath.Join(tmpDir, "report.csv")

flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
flagSet.String("output", outFile, "")

app := cli.NewApp()
app.Flags = []cli.Flag{cli.StringFlag{Name: "output"}}

ctx := cli.NewContext(app, flagSet, nil)
err := writeOutput(ctx, res)
require.NoError(t, err)
assert.FileExists(t, outFile)
})
}
193 changes: 193 additions & 0 deletions internal/app/comment/ontology_extra_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package comment

import (
"flag"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/urfave/cli"
)

func TestReadHTMLContent(t *testing.T) {
t.Parallel()

t.Run("existing file", func(t *testing.T) {
tmpDir := t.TempDir()
htmlFile := filepath.Join(tmpDir, "report.html")
content := "<html><body>test</body></html>"
require.NoError(t, os.WriteFile(htmlFile, []byte(content), 0o600))

result, err := readHTMLContent(htmlFile)
require.NoError(t, err)
assert.Equal(t, content, result)
})

t.Run("nonexistent file", func(t *testing.T) {
result, err := readHTMLContent("/nonexistent/file.html")
require.NoError(t, err)
assert.Empty(t, result)
})

t.Run("directory instead of file", func(t *testing.T) {
tmpDir := t.TempDir()
_, err := readHTMLContent(tmpDir)
assert.Error(t, err)
})
}

func TestReportStatusError(t *testing.T) {
t.Parallel()

t.Run("with failures", func(t *testing.T) {
data := map[string][]*reportContent{
"fail": {{Name: "dicty_pheno.obo"}},
}
err := reportStatusError(data)
assert.Error(t, err)
})

t.Run("no failures", func(t *testing.T) {
data := map[string][]*reportContent{
"pass": {{Name: "dicty_assay.obo"}},
}
err := reportStatusError(data)
assert.NoError(t, err)
})

t.Run("empty", func(t *testing.T) {
data := map[string][]*reportContent{}
err := reportStatusError(data)
assert.NoError(t, err)
})
}

func TestBaseNoSuffix(t *testing.T) {
t.Parallel()

tests := []struct {
name string
input string
expected string
}{
{
name: "obo file",
input: "/onto/dicty_assay.obo",
expected: "dicty_assay",
},
{
name: "simple filename",
input: "dicty_flower.obo",
expected: "dicty_flower",
},
{
name: "multiple dots",
input: "/path/to/dicty_pheno.v1.obo",
expected: "dicty_pheno",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expected, baseNoSuffix(tt.input))
})
}
}

func TestOntoReport(t *testing.T) {
t.Parallel()

t.Run("with fail and pass", func(t *testing.T) {
reportDir := t.TempDir()

failJSON := `[{"level": "ERROR", "violations": [{"missing_title": [{"subject": "test"}]}]}]`
require.NoError(t,
os.WriteFile(
filepath.Join(reportDir, "dicty_pheno.json"),
[]byte(failJSON),
0o600,
),
)
require.NoError(t,
os.WriteFile(
filepath.Join(reportDir, "dicty_pheno.html"),
[]byte("<html>fail</html>"),
0o600,
),
)

passJSON := `[{"level": "WARN", "violations": [{"missing_label": [{"subject": "test"}]}]}]` //nolint:gosec
require.NoError(t,
os.WriteFile(
filepath.Join(reportDir, "dicty_assay.json"),
[]byte(passJSON),
0o600,
),
)

flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
flagSet.String("report-dir", reportDir, "")

app := cli.NewApp()
app.Flags = []cli.Flag{cli.StringFlag{Name: "report-dir"}}

ctx := cli.NewContext(app, flagSet, nil)
result, err := ontoReport(ctx, []string{"dicty_pheno", "dicty_assay"})
require.NoError(t, err)
assert.Contains(t, result, "fail")
assert.Contains(t, result, "pass")
assert.Len(t, result["fail"], 1)
assert.Len(t, result["pass"], 1)
assert.Equal(t, "dicty_pheno.obo", result["fail"][0].Name)
assert.Equal(t, "dicty_assay.obo", result["pass"][0].Name)
})

t.Run("with only failures", func(t *testing.T) {
reportDir := t.TempDir()

failJSON := `[{"level": "ERROR", "violations": [{"missing_title": [{"subject": "test"}]}]}]`
require.NoError(t,
os.WriteFile(
filepath.Join(reportDir, "dicty_env.json"),
[]byte(failJSON),
0o600,
),
)

flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
flagSet.String("report-dir", reportDir, "")

app := cli.NewApp()
app.Flags = []cli.Flag{cli.StringFlag{Name: "report-dir"}}

ctx := cli.NewContext(app, flagSet, nil)
result, err := ontoReport(ctx, []string{"dicty_env"})
require.NoError(t, err)
assert.Contains(t, result, "fail")
assert.NotContains(t, result, "pass")
assert.Len(t, result["fail"], 1)
})

t.Run("with bad json returns error", func(t *testing.T) {
reportDir := t.TempDir()

require.NoError(t,
os.WriteFile(
filepath.Join(reportDir, "dicty_bad.json"),
[]byte("not-json"),
0o600,
),
)

flagSet := flag.NewFlagSet("test", flag.ContinueOnError)
flagSet.String("report-dir", reportDir, "")

app := cli.NewApp()
app.Flags = []cli.Flag{cli.StringFlag{Name: "report-dir"}}

ctx := cli.NewContext(app, flagSet, nil)
_, err := ontoReport(ctx, []string{"dicty_bad"})
assert.Error(t, err)
})
}
Loading
Loading