diff --git a/pkg/cmd/ruleset/list/list_test.go b/pkg/cmd/ruleset/list/list_test.go index 8d1f0bb99..d075e46d6 100644 --- a/pkg/cmd/ruleset/list/list_test.go +++ b/pkg/cmd/ruleset/list/list_test.go @@ -140,6 +140,7 @@ func Test_listRun(t *testing.T) { name string isTTY bool opts ListOptions + httpStubs func(*httpmock.Registry) wantErr string wantStdout string wantStderr string @@ -157,6 +158,12 @@ func Test_listRun(t *testing.T) { 42 asdf OWNER/REPO (repo) active 2 77 foobar Org-Name (org) disabled 4 `), + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query RepoRulesetList\b`), + httpmock.FileResponse("./fixtures/rulesetList.json"), + ) + }, wantStderr: "", wantBrowse: "", }, @@ -175,6 +182,12 @@ func Test_listRun(t *testing.T) { 42 asdf OWNER/REPO (repo) active 2 77 foobar Org-Name (org) disabled 4 `), + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query OrgRulesetList\b`), + httpmock.FileResponse("./fixtures/rulesetList.json"), + ) + }, wantStderr: "", wantBrowse: "", }, @@ -186,6 +199,12 @@ func Test_listRun(t *testing.T) { 42 asdf OWNER/REPO (repo) active 2 77 foobar Org-Name (org) disabled 4 `), + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.GraphQL(`query RepoRulesetList\b`), + httpmock.FileResponse("./fixtures/rulesetList.json"), + ) + }, wantStderr: "", wantBrowse: "", }, @@ -240,12 +259,15 @@ func Test_listRun(t *testing.T) { ios.SetStdinTTY(tt.isTTY) ios.SetStderrTTY(tt.isTTY) - fakeHTTP := &httpmock.Registry{} - fakeHTTP.Register(httpmock.GraphQL(`query RulesetList\b`), httpmock.FileResponse("./fixtures/rulesetList.json")) + reg := &httpmock.Registry{} + defer reg.Verify(t) + if tt.httpStubs != nil { + tt.httpStubs(reg) + } tt.opts.IO = ios tt.opts.HttpClient = func() (*http.Client, error) { - return &http.Client{Transport: fakeHTTP}, nil + return &http.Client{Transport: reg}, nil } tt.opts.BaseRepo = func() (ghrepo.Interface, error) { return ghrepo.FromFullName("OWNER/REPO") diff --git a/pkg/cmd/ruleset/shared/http.go b/pkg/cmd/ruleset/shared/http.go index b9114aa85..59480dadf 100644 --- a/pkg/cmd/ruleset/shared/http.go +++ b/pkg/cmd/ruleset/shared/http.go @@ -100,12 +100,12 @@ func rulesetsQuery(org bool) string { } const repoGraphQLHeader = ` -query RulesetList($limit: Int!, $endCursor: String, $includeParents: Boolean, $owner: String!, $repo: String!) { +query RepoRulesetList($limit: Int!, $endCursor: String, $includeParents: Boolean, $owner: String!, $repo: String!) { level: repository(owner: $owner, name: $repo) { ` const orgGraphQLHeader = ` -query RulesetList($limit: Int!, $endCursor: String, $includeParents: Boolean, $login: String!) { +query OrgRulesetList($limit: Int!, $endCursor: String, $includeParents: Boolean, $login: String!) { level: organization(login: $login) { ` diff --git a/pkg/cmd/ruleset/view/fixtures/rulesetViewOrg.json b/pkg/cmd/ruleset/view/fixtures/rulesetViewOrg.json new file mode 100644 index 000000000..d18509bbf --- /dev/null +++ b/pkg/cmd/ruleset/view/fixtures/rulesetViewOrg.json @@ -0,0 +1,58 @@ +{ + "id": 74, + "name": "My Org Ruleset", + "target": "branch", + "source_type": "Organization", + "source": "my-owner", + "enforcement": "disabled", + "conditions": { + "ref_name": { + "exclude": [], + "include": [ + "~ALL" + ] + }, + "repository_name": { + "exclude": [], + "include": [ + "~ALL" + ], + "protected": true + } + }, + "rules": [ + { + "type": "commit_message_pattern", + "parameters": { + "name": "", + "negate": false, + "pattern": "asdf", + "operator": "contains" + } + }, + { + "type": "commit_author_email_pattern", + "parameters": { + "name": "", + "negate": false, + "pattern": "@example.com", + "operator": "ends_with" + } + }, + { + "type": "creation" + } + ], + "node_id": "RRS_lACqUmVwb3NpdG9yec4dwx_uzSNG", + "_links": { + "self": { + "href": "https://api.github.com/repos/my-owner/repo-name/rulesets/74" + }, + "html": { + "href": "https://github.com/organizations/my-owner/settings/rules/74" + } + }, + "created_at": "2023-05-01T13:53:37.185-04:00", + "updated_at": "2023-06-29T17:38:03.722-04:00", + "bypass_actors": [] +} diff --git a/pkg/cmd/ruleset/view/fixtures/rulesetView.json b/pkg/cmd/ruleset/view/fixtures/rulesetViewRepo.json similarity index 100% rename from pkg/cmd/ruleset/view/fixtures/rulesetView.json rename to pkg/cmd/ruleset/view/fixtures/rulesetViewRepo.json diff --git a/pkg/cmd/ruleset/view/view.go b/pkg/cmd/ruleset/view/view.go index 2b67060df..615abdac5 100644 --- a/pkg/cmd/ruleset/view/view.go +++ b/pkg/cmd/ruleset/view/view.go @@ -182,7 +182,7 @@ func viewRun(opts *ViewOptions) error { fmt.Fprintf(w, "ID: %d\n", rs.Id) fmt.Fprintf(w, "Source: %s (%s)\n", rs.Source, rs.SourceType) - fmt.Fprint(w, "Enforceument: ") + fmt.Fprint(w, "Enforcement: ") switch rs.Enforcement { case "disabled": fmt.Fprintf(w, "%s\n", cs.Red("Disabled")) diff --git a/pkg/cmd/ruleset/view/view_test.go b/pkg/cmd/ruleset/view/view_test.go index 7e184ddc4..78c32d076 100644 --- a/pkg/cmd/ruleset/view/view_test.go +++ b/pkg/cmd/ruleset/view/view_test.go @@ -153,6 +153,7 @@ func Test_viewRun(t *testing.T) { name string isTTY bool opts ViewOptions + httpStubs func(*httpmock.Registry) wantErr string wantStdout string wantStderr string @@ -169,7 +170,7 @@ func Test_viewRun(t *testing.T) { Test Ruleset ID: 42 Source: my-owner/repo-name (Repository) - Enforceument: Active + Enforcement: Active Bypass List - OrganizationAdmin (ID: 1), mode: always @@ -183,31 +184,102 @@ func Test_viewRun(t *testing.T) { - commit_message_pattern: [name: ] [negate: false] [operator: contains] [pattern: asdf] - creation `), + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("GET", "repos/my-owner/repo-name/rulesets/42"), + httpmock.FileResponse("./fixtures/rulesetViewRepo.json"), + ) + }, wantStderr: "", wantBrowse: "", }, { - name: "web mode, TTY", + name: "view org ruleset", + isTTY: true, + opts: ViewOptions{ + ID: "74", + Organization: "my-owner", + }, + wantStdout: heredoc.Doc(` + + My Org Ruleset + ID: 74 + Source: my-owner (Organization) + Enforcement: Disabled + + Bypass List + This ruleset cannot be bypassed + + Conditions + - ref_name: [exclude: []] [include: [~ALL]] + - repository_name: [exclude: []] [include: [~ALL]] [protected: true] + + Rules + - commit_author_email_pattern: [name: ] [negate: false] [operator: ends_with] [pattern: @example.com] + - commit_message_pattern: [name: ] [negate: false] [operator: contains] [pattern: asdf] + - creation + `), + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("GET", "orgs/my-owner/rulesets/74"), + httpmock.FileResponse("./fixtures/rulesetViewOrg.json"), + ) + }, + wantStderr: "", + wantBrowse: "", + }, + { + name: "web mode, TTY, repo", isTTY: true, opts: ViewOptions{ ID: "42", WebMode: true, }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("GET", "repos/my-owner/repo-name/rulesets/42"), + httpmock.FileResponse("./fixtures/rulesetViewRepo.json"), + ) + }, wantStdout: "Opening github.com/my-owner/repo-name/rules/42 in your browser.\n", wantStderr: "", wantBrowse: "https://github.com/my-owner/repo-name/rules/42", }, { - name: "web mode, non-TTY", + name: "web mode, non-TTY, repo", isTTY: false, opts: ViewOptions{ ID: "42", WebMode: true, }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("GET", "repos/my-owner/repo-name/rulesets/42"), + httpmock.FileResponse("./fixtures/rulesetViewRepo.json"), + ) + }, wantStdout: "", wantStderr: "", wantBrowse: "https://github.com/my-owner/repo-name/rules/42", }, + { + name: "web mode, TTY, org", + isTTY: true, + opts: ViewOptions{ + ID: "74", + Organization: "my-owner", + WebMode: true, + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("GET", "orgs/my-owner/rulesets/74"), + httpmock.FileResponse("./fixtures/rulesetViewOrg.json"), + ) + }, + wantStdout: "Opening github.com/organizations/my-owner/settings/rules/74 in your browser.\n", + wantStderr: "", + wantBrowse: "https://github.com/organizations/my-owner/settings/rules/74", + }, } for _, tt := range tests { @@ -217,15 +289,15 @@ func Test_viewRun(t *testing.T) { ios.SetStdinTTY(tt.isTTY) ios.SetStderrTTY(tt.isTTY) - fakeHTTP := &httpmock.Registry{} - fakeHTTP.Register( - httpmock.REST("GET", "repos/my-owner/repo-name/rulesets/42"), - httpmock.FileResponse("./fixtures/rulesetView.json"), - ) + reg := &httpmock.Registry{} + defer reg.Verify(t) + if tt.httpStubs != nil { + tt.httpStubs(reg) + } tt.opts.IO = ios tt.opts.HttpClient = func() (*http.Client, error) { - return &http.Client{Transport: fakeHTTP}, nil + return &http.Client{Transport: reg}, nil } tt.opts.BaseRepo = func() (ghrepo.Interface, error) { return ghrepo.FromFullName("my-owner/repo-name")