From b1fdb363ffc8f3a132979c73fcc6de149b8783f1 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 18 Sep 2025 05:28:48 +0200 Subject: [PATCH 01/12] feat(gist): add `RawURL` and `Truncated` fields to `GistFile` * Added `RawURL` to store the raw URL of the gist file. * Added `Truncated` to indicate if the content is truncated. --- pkg/cmd/gist/shared/shared.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/gist/shared/shared.go b/pkg/cmd/gist/shared/shared.go index 99a5524ee..3f849f71d 100644 --- a/pkg/cmd/gist/shared/shared.go +++ b/pkg/cmd/gist/shared/shared.go @@ -19,10 +19,12 @@ import ( ) type GistFile struct { - Filename string `json:"filename,omitempty"` - Type string `json:"type,omitempty"` - Language string `json:"language,omitempty"` - Content string `json:"content"` + Filename string `json:"filename,omitempty"` + Type string `json:"type,omitempty"` + Language string `json:"language,omitempty"` + Content string `json:"content"` + RawURL string `json:"raw_url,omitempty"` + Truncated bool `json:"truncated,omitempty"` } type GistOwner struct { From 62ea0605900c16940a6580ba0d316c9eb5a8ed7d Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 18 Sep 2025 06:35:16 +0200 Subject: [PATCH 02/12] feat(gist): add `GetRawGistFile` function to retrieve raw gist content * Implements a new function to fetch the raw content of a gist using its `rawURL`. * Handles HTTP requests and responses, including error management for non-200 status codes. --- pkg/cmd/gist/shared/shared.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/pkg/cmd/gist/shared/shared.go b/pkg/cmd/gist/shared/shared.go index 3f849f71d..305e2f642 100644 --- a/pkg/cmd/gist/shared/shared.go +++ b/pkg/cmd/gist/shared/shared.go @@ -3,6 +3,7 @@ package shared import ( "errors" "fmt" + "io" "net/http" "net/url" "regexp" @@ -246,3 +247,29 @@ func PromptGists(prompter prompter.Prompter, client *http.Client, host string, c return &gists[result], nil } + +func GetRawGistFile(httpClient *http.Client, rawURL string) (string, error) { + req, err := http.NewRequest("GET", rawURL, nil) + if err != nil { + return "", err + } + + resp, err := httpClient.Do(req) + if err != nil { + return "", err + } + + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", api.HandleHTTPError(resp) + } + + body, err := io.ReadAll(resp.Body) + + if err != nil { + return "", err + } + + return string(body), nil +} From 704bb4164c84e23cb6fd32b4c1a14899df74bc0c Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 18 Sep 2025 06:35:31 +0200 Subject: [PATCH 03/12] feat(gist): retrieve full content for truncated gist files * Added logic to fetch the full content of a gist file if it is marked as truncated. * Utilizes the `GetRawGistFile` function to obtain the complete content from the provided `RawURL`. --- pkg/cmd/gist/view/view.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/cmd/gist/view/view.go b/pkg/cmd/gist/view/view.go index f789c5b04..9eb906cde 100644 --- a/pkg/cmd/gist/view/view.go +++ b/pkg/cmd/gist/view/view.go @@ -136,6 +136,16 @@ func viewRun(opts *ViewOptions) error { defer opts.IO.StopPager() render := func(gf *shared.GistFile) error { + if gf.Truncated { + fullContent, err := shared.GetRawGistFile(client, gf.RawURL) + + if err != nil { + return err + } + + gf.Content = fullContent + } + if shared.IsBinaryContents([]byte(gf.Content)) { if len(gist.Files) == 1 || opts.Filename != "" { return fmt.Errorf("error: file is binary") From bf272305ff2bd76b84fca08ea22c9d69aafaf7aa Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 18 Sep 2025 06:35:35 +0200 Subject: [PATCH 04/12] feat(gist): retrieve full content for truncated gist files * Added logic to fetch full content for truncated files when updating a gist. * Utilizes `shared.GetRawGistFile` to retrieve the complete content based on the `RawURL`. --- pkg/cmd/gist/edit/edit.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/cmd/gist/edit/edit.go b/pkg/cmd/gist/edit/edit.go index 9e74adf62..377bb24d8 100644 --- a/pkg/cmd/gist/edit/edit.go +++ b/pkg/cmd/gist/edit/edit.go @@ -155,6 +155,15 @@ func editRun(opts *EditOptions) error { // Transform our gist into the schema that the update endpoint expects filesToupdate := make(map[string]*gistFileToUpdate, len(gist.Files)) for filename, file := range gist.Files { + if file.Truncated { + fullContent, err := shared.GetRawGistFile(client, file.RawURL) + if err != nil { + return err + } + + file.Content = fullContent + } + filesToupdate[filename] = &gistFileToUpdate{ Content: file.Content, NewFilename: file.Filename, From e3afc4dae496ea312fff8ccba110e7ff9faa2240 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 19 Sep 2025 05:01:16 +0200 Subject: [PATCH 05/12] test(gist): add tests for `GetRawGistFile` function - Implemented unit tests for various scenarios in `GetRawGistFile`. - Covered cases including successful requests, error handling, and different content types. - Ensured proper verification of HTTP responses and error messages. --- pkg/cmd/gist/shared/shared_test.go | 95 ++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/pkg/cmd/gist/shared/shared_test.go b/pkg/cmd/gist/shared/shared_test.go index 0bc1e1f11..d75ebc2b7 100644 --- a/pkg/cmd/gist/shared/shared_test.go +++ b/pkg/cmd/gist/shared/shared_test.go @@ -219,3 +219,98 @@ func TestPromptGists(t *testing.T) { }) } } + +func TestGetRawGistFile(t *testing.T) { + tests := []struct { + name string + response string + statusCode int + want string + wantErr bool + errContains string + }{ + { + name: "successful request", + response: "Hello, World!", + statusCode: http.StatusOK, + want: "Hello, World!", + wantErr: false, + }, + { + name: "empty response", + response: "", + statusCode: http.StatusOK, + want: "", + wantErr: false, + }, + { + name: "not found error", + response: "Not Found", + statusCode: http.StatusNotFound, + want: "", + wantErr: true, + errContains: "HTTP 404", + }, + { + name: "server error", + response: "Internal Server Error", + statusCode: http.StatusInternalServerError, + want: "", + wantErr: true, + errContains: "HTTP 500", + }, + { + name: "large content", + response: "This is a very large file content with multiple lines\nLine 2\nLine 3\nAnd more content...", + statusCode: http.StatusOK, + want: "This is a very large file content with multiple lines\nLine 2\nLine 3\nAnd more content...", + wantErr: false, + }, + { + name: "special characters", + response: "Special chars: àáâãäåæçèéêë 中文 🎉 \"quotes\" 'single'", + statusCode: http.StatusOK, + want: "Special chars: àáâãäåæçèéêë 中文 🎉 \"quotes\" 'single'", + wantErr: false, + }, + { + name: "JSON content", + response: `{"name": "test", "version": "1.0.0", "dependencies": {"lodash": "^4.17.21"}}`, + statusCode: http.StatusOK, + want: `{"name": "test", "version": "1.0.0", "dependencies": {"lodash": "^4.17.21"}}`, + wantErr: false, + }, + { + name: "HTML content", + response: "Test

Hello

", + statusCode: http.StatusOK, + want: "Test

Hello

", + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + reg := &httpmock.Registry{} + reg.Register( + httpmock.REST("GET", "raw-url"), + httpmock.StatusStringResponse(tt.statusCode, tt.response), + ) + + client := &http.Client{Transport: reg} + result, err := GetRawGistFile(client, "https://gist.githubusercontent.com/raw-url") + + if tt.wantErr { + assert.Error(t, err) + if tt.errContains != "" { + assert.Contains(t, err.Error(), tt.errContains) + } + } else { + assert.NoError(t, err) + assert.Equal(t, tt.want, result) + } + + reg.Verify(t) + }) + } +} From b9b265421983abf9b0ed1bc18d82bbb550bd0d95 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sat, 20 Sep 2025 06:55:10 +0200 Subject: [PATCH 06/12] test(gist): add tests for editing truncated gist files * Implement tests for editing gists that contain truncated files. * Ensure that both single and multiple truncated files are handled correctly. * Mock responses for retrieving full content from raw URLs for truncated files. --- pkg/cmd/gist/edit/edit_test.go | 90 ++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/pkg/cmd/gist/edit/edit_test.go b/pkg/cmd/gist/edit/edit_test.go index 12cdf8169..ea368be45 100644 --- a/pkg/cmd/gist/edit/edit_test.go +++ b/pkg/cmd/gist/edit/edit_test.go @@ -581,6 +581,82 @@ func Test_editRun(t *testing.T) { }, wantErr: "no file in the gist", }, + { + name: "edit gist with truncated file", + opts: &EditOptions{ + Selector: "1234", + }, + mockGist: &shared.Gist{ + ID: "1234", + Files: map[string]*shared.GistFile{ + "large.txt": { + Filename: "large.txt", + Content: "This is truncated content...", + Type: "text/plain", + Truncated: true, + RawURL: "https://gist.githubusercontent.com/user/1234/raw/large.txt", + }, + }, + Owner: &shared.GistOwner{Login: "octocat"}, + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("POST", "gists/1234"), + httpmock.StatusStringResponse(201, "{}")) + }, + wantLastRequestParameters: map[string]interface{}{ + "description": "", + "files": map[string]interface{}{ + "large.txt": map[string]interface{}{ + "content": "new file content", + "filename": "large.txt", + }, + }, + }, + }, + { + name: "edit specific truncated file in gist with multiple truncated files", + opts: &EditOptions{ + Selector: "1234", + EditFilename: "large.txt", + }, + mockGist: &shared.Gist{ + ID: "1234", + Files: map[string]*shared.GistFile{ + "large.txt": { + Filename: "large.txt", + Content: "This is truncated content...", + Type: "text/plain", + Truncated: true, + RawURL: "https://gist.githubusercontent.com/user/1234/raw/large.txt", + }, + "also-truncated.txt": { + Filename: "also-truncated.txt", + Content: "", // Empty because GitHub truncates subsequent files + Type: "text/plain", + Truncated: true, // Subsequent files are also marked as truncated + RawURL: "https://gist.githubusercontent.com/user/1234/raw/also-truncated.txt", + }, + }, + Owner: &shared.GistOwner{Login: "octocat"}, + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("POST", "gists/1234"), + httpmock.StatusStringResponse(201, "{}")) + }, + wantLastRequestParameters: map[string]interface{}{ + "description": "", + "files": map[string]interface{}{ + "large.txt": map[string]interface{}{ + "content": "new file content", + "filename": "large.txt", + }, + "also-truncated.txt": map[string]interface{}{ + "content": "This is the full content of the also-truncated file retrieved from raw URL", + "filename": "also-truncated.txt", + }, + }, + }, + }, } for _, tt := range tests { @@ -603,6 +679,20 @@ func Test_editRun(t *testing.T) { httpmock.JSONResponse(tt.mockGist)) reg.Register(httpmock.GraphQL(`query UserCurrent\b`), httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`)) + + // Register raw URL mocks for truncated files + for filename, file := range tt.mockGist.Files { + if file.Truncated && file.RawURL != "" { + // Mock the raw URL response for GetRawGistFile calls + if filename == "large.txt" { + reg.Register(httpmock.REST("GET", "user/1234/raw/large.txt"), + httpmock.StringResponse("This is the full content of the large file retrieved from raw URL")) + } else if filename == "also-truncated.txt" { + reg.Register(httpmock.REST("GET", "user/1234/raw/also-truncated.txt"), + httpmock.StringResponse("This is the full content of the also-truncated file retrieved from raw URL")) + } + } + } } } From 26f1d48fa423ed2108da3238f12ca6b54a91b1d7 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sat, 20 Sep 2025 06:55:38 +0200 Subject: [PATCH 07/12] test(gist): add tests for handling truncated files in view command * Added test cases for viewing truncated files with and without the raw flag. * Included scenarios for multiple files with truncation behavior. * Ensured correct output is returned for truncated files when accessed via raw URLs. --- pkg/cmd/gist/view/view_test.go | 102 +++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/pkg/cmd/gist/view/view_test.go b/pkg/cmd/gist/view/view_test.go index 706b85f10..85c2b7ad8 100644 --- a/pkg/cmd/gist/view/view_test.go +++ b/pkg/cmd/gist/view/view_test.go @@ -344,6 +344,96 @@ func Test_viewRun(t *testing.T) { }, wantOut: "cicada.txt\nfoo.md\n", }, + { + name: "truncated file with raw and filename", + isTTY: true, + opts: &ViewOptions{ + Selector: "1234", + Raw: true, + Filename: "large.txt", + }, + mockGist: &shared.Gist{ + Files: map[string]*shared.GistFile{ + "large.txt": { + Content: "This is truncated content...", + Type: "text/plain", + Truncated: true, + RawURL: "https://gist.githubusercontent.com/user/1234/raw/large.txt", + }, + }, + }, + wantOut: "This is the full content of the large file retrieved from raw URL\n", + }, + { + name: "truncated file without raw flag", + isTTY: true, + opts: &ViewOptions{ + Selector: "1234", + Raw: false, + Filename: "large.txt", + }, + mockGist: &shared.Gist{ + Files: map[string]*shared.GistFile{ + "large.txt": { + Content: "This is truncated content...", + Type: "text/plain", + Truncated: true, + RawURL: "https://gist.githubusercontent.com/user/1234/raw/large.txt", + }, + }, + }, + wantOut: "This is the full content of the large file retrieved from raw URL\n", + }, + { + name: "multiple files with one truncated", + isTTY: true, + opts: &ViewOptions{ + Selector: "1234", + Raw: true, + }, + mockGist: &shared.Gist{ + Description: "Mixed files", + Files: map[string]*shared.GistFile{ + "normal.txt": { + Content: "normal content", + Type: "text/plain", + }, + "large.txt": { + Content: "This is truncated content...", + Type: "text/plain", + Truncated: true, + RawURL: "https://gist.githubusercontent.com/user/1234/raw/large.txt", + }, + }, + }, + wantOut: "Mixed files\n\nlarge.txt\n\nThis is the full content of the large file retrieved from raw URL\n\nnormal.txt\n\nnormal content\n", + }, + { + name: "multiple files with subsequent files truncated as empty", + isTTY: true, + opts: &ViewOptions{ + Selector: "1234", + Raw: true, + }, + mockGist: &shared.Gist{ + Description: "Large gist with multiple files", + Files: map[string]*shared.GistFile{ + "large.txt": { + Content: "This is truncated content...", + Type: "text/plain", + Truncated: true, + RawURL: "https://gist.githubusercontent.com/user/1234/raw/large.txt", + }, + "also-truncated.txt": { + Type: "text/plain", + Content: "", // Empty because GitHub truncates subsequent files + Truncated: true, // Subsequent files are also marked as truncated + RawURL: "https://gist.githubusercontent.com/user/1234/raw/also-truncated.txt", + }, + }, + }, + wantOut: "Large gist with multiple files\n\nalso-truncated.txt\n\nThis is the full content of the also-truncated file retrieved from raw URL\n\nlarge.txt\n\nThis is the full content of the large file retrieved from raw URL\n", + }, } for _, tt := range tests { @@ -354,6 +444,18 @@ func Test_viewRun(t *testing.T) { } else { reg.Register(httpmock.REST("GET", "gists/1234"), httpmock.JSONResponse(tt.mockGist)) + + for filename, file := range tt.mockGist.Files { + if file.Truncated && file.RawURL != "" { + if filename == "large.txt" { + reg.Register(httpmock.REST("GET", "user/1234/raw/large.txt"), + httpmock.StringResponse("This is the full content of the large file retrieved from raw URL")) + } else if filename == "also-truncated.txt" { + reg.Register(httpmock.REST("GET", "user/1234/raw/also-truncated.txt"), + httpmock.StringResponse("This is the full content of the also-truncated file retrieved from raw URL")) + } + } + } } if tt.opts == nil { From f8651f5e44a91e219eb510fc8d556c32050f1da6 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 30 Oct 2025 05:48:34 +0100 Subject: [PATCH 08/12] fix(gist): fetch full content for truncated files during editing This change makes it only fetch the raw content, when we wanna edit the specific file. --- pkg/cmd/gist/edit/edit.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pkg/cmd/gist/edit/edit.go b/pkg/cmd/gist/edit/edit.go index 377bb24d8..a480e837a 100644 --- a/pkg/cmd/gist/edit/edit.go +++ b/pkg/cmd/gist/edit/edit.go @@ -155,15 +155,6 @@ func editRun(opts *EditOptions) error { // Transform our gist into the schema that the update endpoint expects filesToupdate := make(map[string]*gistFileToUpdate, len(gist.Files)) for filename, file := range gist.Files { - if file.Truncated { - fullContent, err := shared.GetRawGistFile(client, file.RawURL) - if err != nil { - return err - } - - file.Content = fullContent - } - filesToupdate[filename] = &gistFileToUpdate{ Content: file.Content, NewFilename: file.Filename, @@ -267,6 +258,17 @@ func editRun(opts *EditOptions) error { return fmt.Errorf("editing binary files not supported") } + // If the file is truncated, fetch the full content + file := gist.Files[filename] + if file.Truncated { + fullContent, err := shared.GetRawGistFile(client, file.RawURL) + if err != nil { + return err + } + + gistFile.Content = fullContent + } + var text string if src := opts.SourceFile; src != "" { if src == "-" { From c98c435800bebab55bfa55b92f335510b9923790 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 30 Oct 2025 05:49:52 +0100 Subject: [PATCH 09/12] fix(gist): only include files that have changed in request There was some issues when sending the full list of files, some of them would be truncated. --- pkg/cmd/gist/edit/edit.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/gist/edit/edit.go b/pkg/cmd/gist/edit/edit.go index a480e837a..80d686069 100644 --- a/pkg/cmd/gist/edit/edit.go +++ b/pkg/cmd/gist/edit/edit.go @@ -214,11 +214,12 @@ func editRun(opts *EditOptions) error { // Remove a file from the gist if opts.RemoveFilename != "" { - err := removeFile(gistToUpdate, opts.RemoveFilename) + files, err := getFilesToRemove(gistToUpdate, opts.RemoveFilename) if err != nil { return err } + gistToUpdate.Files = files return updateGist(apiClient, host, gistToUpdate) } @@ -339,6 +340,12 @@ func editRun(opts *EditOptions) error { return nil } + updatedFiles := make(map[string]*gistFileToUpdate, len(filesToUpdate)) + for filename := range filesToUpdate { + updatedFiles[filename] = gistToUpdate.Files[filename] + } + gistToUpdate.Files = updatedFiles + return updateGist(apiClient, host, gistToUpdate) } @@ -396,11 +403,13 @@ func getFilesToAdd(file string, content []byte) (map[string]*gistFileToUpdate, e }, nil } -func removeFile(gist gistToUpdate, filename string) error { +func getFilesToRemove(gist gistToUpdate, filename string) (map[string]*gistFileToUpdate, error) { if _, found := gist.Files[filename]; !found { - return fmt.Errorf("gist has no file %q", filename) + return nil, fmt.Errorf("gist has no file %q", filename) } gist.Files[filename] = nil - return nil + return map[string]*gistFileToUpdate{ + filename: nil, + }, nil } From 42238dc365c9d268f9636d1b3ab495f62d8526a6 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 30 Oct 2025 05:55:53 +0100 Subject: [PATCH 10/12] fix(gist): prevent fetching full content for already edited files --- pkg/cmd/gist/edit/edit.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/gist/edit/edit.go b/pkg/cmd/gist/edit/edit.go index 80d686069..1773a8f83 100644 --- a/pkg/cmd/gist/edit/edit.go +++ b/pkg/cmd/gist/edit/edit.go @@ -260,14 +260,17 @@ func editRun(opts *EditOptions) error { } // If the file is truncated, fetch the full content + // but only if it hasn't already been edited in this session file := gist.Files[filename] if file.Truncated { - fullContent, err := shared.GetRawGistFile(client, file.RawURL) - if err != nil { - return err - } + if _, alreadyEdited := filesToUpdate[filename]; !alreadyEdited { + fullContent, err := shared.GetRawGistFile(client, file.RawURL) + if err != nil { + return err + } - gistFile.Content = fullContent + gistFile.Content = fullContent + } } var text string From 6c497e74df60b9b035452ee22b3293cd8c81d5c2 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 30 Oct 2025 06:12:15 +0100 Subject: [PATCH 11/12] test(gist): fix failing tests --- pkg/cmd/gist/edit/edit_test.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/pkg/cmd/gist/edit/edit_test.go b/pkg/cmd/gist/edit/edit_test.go index ea368be45..296ae3261 100644 --- a/pkg/cmd/gist/edit/edit_test.go +++ b/pkg/cmd/gist/edit/edit_test.go @@ -230,10 +230,6 @@ func Test_editRun(t *testing.T) { wantLastRequestParameters: map[string]interface{}{ "description": "catbug", "files": map[string]interface{}{ - "cicada.txt": map[string]interface{}{ - "content": "bwhiizzzbwhuiiizzzz", - "filename": "cicada.txt", - }, "unix.md": map[string]interface{}{ "content": "new file content", "filename": "unix.md", @@ -478,10 +474,6 @@ func Test_editRun(t *testing.T) { wantLastRequestParameters: map[string]interface{}{ "description": "", "files": map[string]interface{}{ - "sample.txt": map[string]interface{}{ - "filename": "sample.txt", - "content": "bwhiizzzbwhuiiizzzz", - }, "sample2.txt": nil, }, }, @@ -650,10 +642,6 @@ func Test_editRun(t *testing.T) { "content": "new file content", "filename": "large.txt", }, - "also-truncated.txt": map[string]interface{}{ - "content": "This is the full content of the also-truncated file retrieved from raw URL", - "filename": "also-truncated.txt", - }, }, }, }, @@ -687,9 +675,6 @@ func Test_editRun(t *testing.T) { if filename == "large.txt" { reg.Register(httpmock.REST("GET", "user/1234/raw/large.txt"), httpmock.StringResponse("This is the full content of the large file retrieved from raw URL")) - } else if filename == "also-truncated.txt" { - reg.Register(httpmock.REST("GET", "user/1234/raw/also-truncated.txt"), - httpmock.StringResponse("This is the full content of the also-truncated file retrieved from raw URL")) } } } From 7db532aca0b391d290e25ea2014e4364dee296b9 Mon Sep 17 00:00:00 2001 From: Lucas Date: Thu, 30 Oct 2025 18:50:49 +0100 Subject: [PATCH 12/12] test(gist/edit): add tests for single file edit and interactive multi-file selection Co-authored-by: Kynan Ware <47394200+BagToad@users.noreply.github.com> --- pkg/cmd/gist/edit/edit_test.go | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/pkg/cmd/gist/edit/edit_test.go b/pkg/cmd/gist/edit/edit_test.go index 296ae3261..ac1555f5c 100644 --- a/pkg/cmd/gist/edit/edit_test.go +++ b/pkg/cmd/gist/edit/edit_test.go @@ -237,6 +237,33 @@ func Test_editRun(t *testing.T) { }, }, }, + { + name: "single file edit flag sends only edited file", + opts: &EditOptions{ + Selector: "1234", + EditFilename: "unix.md", + }, + mockGist: &shared.Gist{ + ID: "1234", + Files: map[string]*shared.GistFile{ + "cicada.txt": {Filename: "cicada.txt", Content: "bwhiizzzbwhuiiizzzz", Type: "text/plain"}, + "unix.md": {Filename: "unix.md", Content: "meow", Type: "text/markdown"}, + }, + Owner: &shared.GistOwner{Login: "octocat"}, + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("POST", "gists/1234"), httpmock.StatusStringResponse(201, "{}")) + }, + wantLastRequestParameters: map[string]interface{}{ + "description": "", + "files": map[string]interface{}{ + "unix.md": map[string]interface{}{ + "content": "new file content", + "filename": "unix.md", + }, + }, + }, + }, { name: "multiple files, cancel, with TTY", isTTY: true, @@ -645,6 +672,48 @@ func Test_editRun(t *testing.T) { }, }, }, + { + name: "interactive truncated multi-file gist fetches only selected file raw content the first time", + isTTY: true, + opts: &EditOptions{Selector: "1234"}, + prompterStubs: func(pm *prompter.MockPrompter) { + pm.RegisterSelect("Edit which file?", []string{"also-truncated.txt", "large.txt"}, func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "large.txt") + }) + pm.RegisterSelect("What next?", editNextOptions, func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "Edit another file") + }) + // Editing large.txt twice to ensure that fetch for the raw URL happens only once + pm.RegisterSelect("Edit which file?", []string{"also-truncated.txt", "large.txt"}, func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "large.txt") + }) + pm.RegisterSelect("What next?", editNextOptions, func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "Submit") + }) + }, + mockGist: &shared.Gist{ + ID: "1234", + Files: map[string]*shared.GistFile{ + "large.txt": {Filename: "large.txt", Content: "This is truncated content...", Type: "text/plain", Truncated: true, RawURL: "https://gist.githubusercontent.com/user/1234/raw/large.txt"}, + "also-truncated.txt": {Filename: "also-truncated.txt", Content: "stuff...", Type: "text/plain", Truncated: true, RawURL: "https://gist.githubusercontent.com/user/1234/raw/also-truncated.txt"}, + }, + Owner: &shared.GistOwner{Login: "octocat"}, + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register(httpmock.REST("POST", "gists/1234"), httpmock.StatusStringResponse(201, "{}")) + // Explicity exclude also-truncated.txt raw URL to ensure it is not fetched since we did not select it. + reg.Exclude(t, httpmock.REST("GET", "user/1234/raw/also-truncated.txt")) + }, + wantLastRequestParameters: map[string]interface{}{ + "description": "", + "files": map[string]interface{}{ + "large.txt": map[string]interface{}{ + "content": "new file content", + "filename": "large.txt", + }, + }, + }, + }, } for _, tt := range tests {