diff --git a/api/export_pr.go b/api/export_pr.go index bb3310811..8c17ea510 100644 --- a/api/export_pr.go +++ b/api/export_pr.go @@ -23,7 +23,7 @@ func (issue *Issue) ExportData(fields []string) map[string]interface{} { items := make([]map[string]interface{}, 0, len(issue.ProjectItems.Nodes)) for _, n := range issue.ProjectItems.Nodes { items = append(items, map[string]interface{}{ - "status": n.Status, + "status": n.Status.StatusFragment, "title": n.Project.Title, }) } @@ -109,7 +109,7 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} { items := make([]map[string]interface{}, 0, len(pr.ProjectItems.Nodes)) for _, n := range pr.ProjectItems.Nodes { items = append(items, map[string]interface{}{ - "status": n.Status, + "status": n.Status.StatusFragment, "title": n.Project.Title, }) } diff --git a/api/export_pr_test.go b/api/export_pr_test.go index b7f4dcddb..50e346dee 100644 --- a/api/export_pr_test.go +++ b/api/export_pr_test.go @@ -75,38 +75,6 @@ func TestIssue_ExportData(t *testing.T) { } `), }, - { - name: "project items", - fields: []string{"projectItems"}, - inputJSON: heredoc.Doc(` - { "projectItems": { "nodes": [ - { - "id": "PVTI_id", - "project": { - "id": "PVT_id", - "title": "Some Project" - }, - "status": { - "name": "Todo", - "optionId": "abc123" - } - } - ] } } - `), - outputJSON: heredoc.Doc(` - { - "projectItems": [ - { - "status": { - "optionId": "abc123", - "name": "Todo" - }, - "title": "Some Project" - } - ] - } - `), - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -213,38 +181,6 @@ func TestPullRequest_ExportData(t *testing.T) { } `), }, - { - name: "project items", - fields: []string{"projectItems"}, - inputJSON: heredoc.Doc(` - { "projectItems": { "nodes": [ - { - "id": "PVTPR_id", - "project": { - "id": "PVT_id", - "title": "Some Project" - }, - "status": { - "name": "Todo", - "optionId": "abc123" - } - } - ] } } - `), - outputJSON: heredoc.Doc(` - { - "projectItems": [ - { - "status": { - "optionId": "abc123", - "name": "Todo" - }, - "title": "Some Project" - } - ] - } - `), - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -269,3 +205,108 @@ func TestPullRequest_ExportData(t *testing.T) { }) } } + +// The following tests exist separately from the table driven tests +// above because in the implementation code, the GraphQL request is +// performed by shurcool, and it handles the JSON decoding into the +// response struct, which is slightly different than the stdlib JSON +// decoder used by the rest of the requests when Finding an Issue or PR. +func TestIssueExportProjectItems(t *testing.T) { + issue := Issue{ + ProjectItems: ProjectItems{ + Nodes: []*ProjectV2Item{ + { + ID: "PVTI_lADOB-vozM4AVk16zgK6U50", + Project: struct { + ID string `json:"id"` + Title string `json:"title"` + }{ + ID: "PVT_kwDOB-vozM4AVk16", + Title: "Test Project", + }, + Status: Status{ + StatusFragment: struct { + OptionID string `json:"optionId"` + Name string `json:"name"` + }{ + OptionID: "47fc9ee4", + Name: "In Progress", + }, + }, + }, + }, + }, + } + + expectedExportedJSON := heredoc.Doc(` + { + "projectItems": [ + { + "status": { + "optionId": "47fc9ee4", + "name": "In Progress" + }, + "title": "Test Project" + } + ] + } + `) + + exported := issue.ExportData([]string{"projectItems"}) + + buf := bytes.Buffer{} + enc := json.NewEncoder(&buf) + enc.SetIndent("", "\t") + require.NoError(t, enc.Encode(exported)) + require.Equal(t, expectedExportedJSON, buf.String()) +} + +func TestPRExportProjectItems(t *testing.T) { + pr := PullRequest{ + ProjectItems: ProjectItems{ + Nodes: []*ProjectV2Item{ + { + ID: "PVTI_lADOB-vozM4AVk16zgK6U50", + Project: struct { + ID string `json:"id"` + Title string `json:"title"` + }{ + ID: "PVT_kwDOB-vozM4AVk16", + Title: "Test Project", + }, + Status: Status{ + StatusFragment: struct { + OptionID string `json:"optionId"` + Name string `json:"name"` + }{ + OptionID: "47fc9ee4", + Name: "In Progress", + }, + }, + }, + }, + }, + } + + expectedExportedJSON := heredoc.Doc(` + { + "projectItems": [ + { + "status": { + "optionId": "47fc9ee4", + "name": "In Progress" + }, + "title": "Test Project" + } + ] + } + `) + + exported := pr.ExportData([]string{"projectItems"}) + + buf := bytes.Buffer{} + enc := json.NewEncoder(&buf) + enc.SetIndent("", "\t") + require.NoError(t, enc.Encode(exported)) + require.Equal(t, expectedExportedJSON, buf.String()) +} diff --git a/api/queries_issue.go b/api/queries_issue.go index fdef7783f..1871294e7 100644 --- a/api/queries_issue.go +++ b/api/queries_issue.go @@ -106,10 +106,14 @@ type ProjectV2Item struct { ID string `json:"id"` Title string `json:"title"` } - Status struct { - OptionID string `json:"optionId" graphql:"... on ProjectV2ItemFieldSingleSelectValue{optionId}"` - Name string `json:"name" graphql:"... on ProjectV2ItemFieldSingleSelectValue{name}"` - } `graphql:"status:fieldValueByName(name: \"Status\")"` + Status Status `graphql:"status:fieldValueByName(name: \"Status\")"` +} + +type Status struct { + StatusFragment struct { + OptionID string `json:"optionId"` + Name string `json:"name"` + } `graphql:"... on ProjectV2ItemFieldSingleSelectValue"` } func (p ProjectCards) ProjectNames() []string { diff --git a/api/queries_projects_v2_test.go b/api/queries_projects_v2_test.go index 30d782bef..8cacad921 100644 --- a/api/queries_projects_v2_test.go +++ b/api/queries_projects_v2_test.go @@ -236,12 +236,14 @@ func TestProjectsV2ItemsForPullRequest(t *testing.T) { ID: "PVT_kwDOB-vozM4AVk16", Title: "Test Project", }, - Status: struct { - OptionID string `json:"optionId" graphql:"... on ProjectV2ItemFieldSingleSelectValue{optionId}"` - Name string `json:"name" graphql:"... on ProjectV2ItemFieldSingleSelectValue{name}"` - }{ - OptionID: "47fc9ee4", - Name: "In Progress", + Status: Status{ + StatusFragment: struct { + OptionID string `json:"optionId"` + Name string `json:"name"` + }{ + OptionID: "47fc9ee4", + Name: "In Progress", + }, }, }, },