internal/control/querylang_test.go

v1.40.0
gitbay/internal/control/querylang_test.go history · blame · raw

112 lines · 4034 bytes

  1package control
  2
  3import (
  4	"errors"
  5	"reflect"
  6	"testing"
  7
  8	"gitbay.org/gitbay/internal/store"
  9)
 10
 11func TestParseItemQuery(t *testing.T) {
 12	for _, tc := range []struct {
 13		in   []string
 14		want ItemQuery
 15		text string // canonical form
 16	}{
 17		{[]string{"repo:krz/gitbay"}, ItemQuery{Scopes: []store.RepoScope{{Owner: "krz", Name: "gitbay"}}}, "repo:krz/gitbay"},
 18		{[]string{"repo:krz/git* owner:cmc"}, ItemQuery{Scopes: []store.RepoScope{{Owner: "krz", Name: "git*"}, {Owner: "cmc"}}}, "repo:krz/git* owner:cmc"},
 19		{[]string{"repo:*", "is:open"}, ItemQuery{AnyRepo: true, State: "open"}, "repo:* is:open"},
 20		{[]string{"is:merged"}, ItemQuery{State: "merged"}, "is:merged"},
 21		{[]string{"is:open is:issue"}, ItemQuery{Kind: "issue", State: "open"}, "is:issue is:open"},
 22		{[]string{"label:bug", "label:ui", "label:bug"}, ItemQuery{Labels: []string{"bug", "ui"}}, "label:bug label:ui"},
 23		{[]string{`label:"needs review"`}, ItemQuery{Labels: []string{"needs review"}}, `label:"needs review"`},
 24		{[]string{"label:needs review"}, ItemQuery{Labels: []string{"needs"}, Text: []string{"review"}}, "label:needs review"},
 25		{[]string{"no:label no:milestone"}, ItemQuery{NoLabel: true, NoMilestone: true}, "no:label no:milestone"},
 26		{[]string{"milestone:v2"}, ItemQuery{Milestone: "v2"}, "milestone:v2"},
 27		{[]string{"assignee:@me author:cmc"}, ItemQuery{Assignee: "@me", Author: "cmc"}, "assignee:@me author:cmc"},
 28		{[]string{"crash", `"on start"`, "is:open"}, ItemQuery{State: "open", Text: []string{"crash", "on start"}}, `is:open crash "on start"`},
 29		{[]string{`"a:b"`}, ItemQuery{Text: []string{"a:b"}}, `"a:b"`},
 30	} {
 31		got, err := ParseItemQuery(tc.in...)
 32		if err != nil {
 33			t.Errorf("%q: %v", tc.in, err)
 34			continue
 35		}
 36		if !reflect.DeepEqual(got, tc.want) {
 37			t.Errorf("%q = %+v, want %+v", tc.in, got, tc.want)
 38		}
 39		if s := got.String(); s != tc.text {
 40			t.Errorf("%q canonical = %q, want %q", tc.in, s, tc.text)
 41		}
 42		again, err := ParseItemQuery(got.String())
 43		if err != nil || !reflect.DeepEqual(again, got) {
 44			t.Errorf("%q does not survive its canonical form: %+v, %v", tc.in, again, err)
 45		}
 46	}
 47}
 48
 49func TestParseItemQueryRefuses(t *testing.T) {
 50	for _, tc := range []struct {
 51		in, token string
 52	}{
 53		{"", ""},
 54		{"foo:bar", "foo:bar"},
 55		{"is:open is:bogus", "is:bogus"},
 56		{"is:open is:closed", "is:closed"},
 57		{"is:issue is:mr", "is:mr"},
 58		{"is:issue is:merged", "is:merged"},
 59		{"is:mr assignee:cmc", "assignee:cmc"},
 60		{"assignee:cmc is:mr", "is:mr"},
 61		{"assignee:cmc assignee:bob", "assignee:bob"},
 62		{"is:merged assignee:cmc", "assignee:cmc"},
 63		{"assignee:@me is:merged", "is:merged"},
 64		{"author:Not_A_User", "author:Not_A_User"},
 65		{"repo:krz", "repo:krz"},
 66		{"repo:*/gitbay", "repo:*/gitbay"},
 67		{"repo:krz/[ab]", "repo:krz/[ab]"},
 68		{"owner:krz/x", "owner:krz/x"},
 69		{"label:bug no:label", "no:label"},
 70		{"no:milestone milestone:v1", "milestone:v1"},
 71		{"no:author", "no:author"},
 72		{"label:", "label:"},
 73		{`label:"open`, `label:"open`},
 74		{"x", "x"}, // text too short
 75	} {
 76		_, err := ParseItemQuery(tc.in)
 77		var qe *QueryError
 78		if !errors.As(err, &qe) {
 79			t.Errorf("%q: err %v, want a QueryError", tc.in, err)
 80			continue
 81		}
 82		if qe.Token != tc.token {
 83			t.Errorf("%q: token %q, want %q (%v)", tc.in, qe.Token, tc.token, err)
 84		}
 85	}
 86}
 87
 88func TestItemQuerySelects(t *testing.T) {
 89	for _, tc := range []struct {
 90		in          string
 91		issues, mrs bool
 92	}{
 93		{"is:open", true, true},
 94		{"is:issue", true, false},
 95		{"is:mr", false, true},
 96		{"is:merged", false, true},
 97		{"assignee:cmc", true, false},
 98	} {
 99		q, err := ParseItemQuery(tc.in)
100		if err != nil {
101			t.Fatal(err)
102		}
103		if i, m := q.Selects(); i != tc.issues || m != tc.mrs {
104			t.Errorf("%q selects issues=%v mrs=%v, want %v %v", tc.in, i, m, tc.issues, tc.mrs)
105		}
106	}
107	q, _ := ParseItemQuery("repo:* repo:krz/x assignee:@me author:@me")
108	f := q.Filter("alice", true, true)
109	if f.Scopes != nil || f.Assignee != "alice" || f.Author != "alice" {
110		t.Errorf("Filter = %+v: repo:* widens to every repository, @me is the caller", f)
111	}
112}