@@ -17,33 +17,106 @@ package githubfile
1717import (
1818 "context"
1919 "fmt"
20+ "math/rand"
21+ "net/http"
22+ "net/http/httptest"
23+ "net/url"
24+ "os"
2025 "testing"
2126
27+ "github.com/form3tech-oss/go-github-utils/pkg/branch"
2228 ghfileutils "github.com/form3tech-oss/go-github-utils/pkg/file"
29+ "github.com/google/go-github/v54/github"
2330 "github.com/hashicorp/terraform-plugin-sdk/helper/resource"
31+ "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
2432 "github.com/hashicorp/terraform-plugin-sdk/terraform"
33+ "golang.org/x/oauth2"
2534)
2635
2736const (
28- testAccFileCreate = `
37+ testRepoOwner = "form3tech-oss"
38+ testRepoName = "terraform-provider-githubfile"
39+ )
40+
41+ var testBranchName string
42+
43+ func newGitHubClient () * github.Client {
44+ token := os .Getenv ("GITHUB_TOKEN" )
45+ ts := oauth2 .StaticTokenSource (& oauth2.Token {AccessToken : token })
46+ tc := oauth2 .NewClient (context .Background (), ts )
47+ return github .NewClient (tc )
48+ }
49+
50+ func TestMain (m * testing.M ) {
51+ testBranchName = fmt .Sprintf ("acc-test-%d" , rand .Int63 ())
52+
53+ code := m .Run ()
54+
55+ // Cleanup: delete the test branch if it was created
56+ if os .Getenv ("GITHUB_TOKEN" ) != "" {
57+ cleanupTestBranch ()
58+ }
59+
60+ os .Exit (code )
61+ }
62+
63+ func cleanupTestBranch () {
64+ client := newGitHubClient ()
65+ ref := fmt .Sprintf ("refs/heads/%s" , testBranchName )
66+ _ , err := client .Git .DeleteRef (context .Background (), testRepoOwner , testRepoName , ref )
67+ if err != nil {
68+ fmt .Fprintf (os .Stderr , "failed to delete test branch %s: %v\n " , testBranchName , err )
69+ }
70+ }
71+
72+ func createTestBranch (t * testing.T ) {
73+ t .Helper ()
74+
75+ client := newGitHubClient ()
76+ ctx := context .Background ()
77+
78+ // Get the SHA for the default branch (master)
79+ sha , err := branch .GetSHAForBranch (ctx , client , testRepoOwner , testRepoName , "master" )
80+ if err != nil {
81+ t .Fatalf ("failed to get SHA for master branch: %v" , err )
82+ }
83+
84+ // Create the test branch
85+ ref := & github.Reference {
86+ Ref : github .String (fmt .Sprintf ("refs/heads/%s" , testBranchName )),
87+ Object : & github.GitObject {
88+ SHA : github .String (sha ),
89+ },
90+ }
91+ _ , _ , err = client .Git .CreateRef (ctx , testRepoOwner , testRepoName , ref )
92+ if err != nil {
93+ t .Fatalf ("failed to create test branch %s: %v" , testBranchName , err )
94+ }
95+ }
96+
97+ func testAccFileCreateConfig () string {
98+ return fmt .Sprintf (`
2999resource "githubfile_file" "foo" {
30- repository_owner = "form3tech-oss"
31- repository_name = "terraform-provider-githubfile-test"
32- branch = "master"
33- path = "foo/bar/baz/README.md"
34- contents = "foo\nbar\nbaz"
100+ repository_owner = "%s"
101+ repository_name = "%s"
102+ branch = "%s"
103+ path = "foo/bar/baz/README.md"
104+ contents = "foo\nbar\nbaz"
105+ }
106+ ` , testRepoOwner , testRepoName , testBranchName )
35107}
36- `
37- testAccFileUpdate = `
108+
109+ func testAccFileUpdateConfig () string {
110+ return fmt .Sprintf (`
38111resource "githubfile_file" "foo" {
39- repository_owner = "form3tech-oss"
40- repository_name = "terraform-provider-githubfile-test"
41- branch = "master"
42- path = "foo/bar/baz/README.md"
43- contents = "foo\nbar\nqux"
112+ repository_owner = "%s"
113+ repository_name = "%s"
114+ branch = "%s"
115+ path = "foo/bar/baz/README.md"
116+ contents = "foo\nbar\nqux"
117+ }
118+ ` , testRepoOwner , testRepoName , testBranchName )
44119}
45- `
46- )
47120
48121func TestAccResourceFile_basic (t * testing.T ) {
49122 var (
@@ -55,18 +128,19 @@ func TestAccResourceFile_basic(t *testing.T) {
55128 resource .Test (t , resource.TestCase {
56129 PreCheck : func () {
57130 testAccPreCheck (t )
131+ createTestBranch (t )
58132 },
59133 IDRefreshName : resourceName ,
60134 Providers : testAccProviders ,
61135 CheckDestroy : testAccCheckFileDestroy ,
62136 Steps : []resource.TestStep {
63137 {
64- Config : testAccFileCreate ,
138+ Config : testAccFileCreateConfig () ,
65139 Check : resource .ComposeAggregateTestCheckFunc (
66140 testAccCheckFileExists (resourceName , & before ),
67- resource .TestCheckResourceAttr (resourceName , repositoryNameAttributeName , "terraform-provider-githubfile-test" ),
68- resource .TestCheckResourceAttr (resourceName , repositoryOwnerAttributeName , "form3tech-oss" ),
69- resource .TestCheckResourceAttr (resourceName , branchAttributeName , "master" ),
141+ resource .TestCheckResourceAttr (resourceName , repositoryNameAttributeName , testRepoName ),
142+ resource .TestCheckResourceAttr (resourceName , repositoryOwnerAttributeName , testRepoOwner ),
143+ resource .TestCheckResourceAttr (resourceName , branchAttributeName , testBranchName ),
70144 resource .TestCheckResourceAttr (resourceName , pathAttributeName , "foo/bar/baz/README.md" ),
71145 resource .TestCheckResourceAttr (resourceName , contentsAttributeName , "foo\n bar\n baz" ),
72146 ),
@@ -77,12 +151,12 @@ func TestAccResourceFile_basic(t *testing.T) {
77151 ImportStateVerify : true ,
78152 },
79153 {
80- Config : testAccFileUpdate ,
154+ Config : testAccFileUpdateConfig () ,
81155 Check : resource .ComposeAggregateTestCheckFunc (
82156 testAccCheckFileExists (resourceName , & before ),
83- resource .TestCheckResourceAttr (resourceName , repositoryNameAttributeName , "terraform-provider-githubfile-test" ),
84- resource .TestCheckResourceAttr (resourceName , repositoryOwnerAttributeName , "form3tech-oss" ),
85- resource .TestCheckResourceAttr (resourceName , branchAttributeName , "master" ),
157+ resource .TestCheckResourceAttr (resourceName , repositoryNameAttributeName , testRepoName ),
158+ resource .TestCheckResourceAttr (resourceName , repositoryOwnerAttributeName , testRepoOwner ),
159+ resource .TestCheckResourceAttr (resourceName , branchAttributeName , testBranchName ),
86160 resource .TestCheckResourceAttr (resourceName , pathAttributeName , "foo/bar/baz/README.md" ),
87161 resource .TestCheckResourceAttr (resourceName , contentsAttributeName , "foo\n bar\n qux" ),
88162 ),
@@ -137,3 +211,82 @@ func testAccCheckFileDestroy(s *terraform.State) error {
137211 }
138212 return nil
139213}
214+
215+ // newTestResourceData creates a schema.ResourceData with the file resource schema
216+ // populated from the given raw values, suitable for unit testing.
217+ func newTestResourceData (t * testing.T , values map [string ]interface {}) * schema.ResourceData {
218+ t .Helper ()
219+ return schema .TestResourceDataRaw (t , resourceFile ().Schema , values )
220+ }
221+
222+ // newMockGitHubClient creates a github.Client pointing at the given httptest.Server.
223+ func newMockGitHubClient (server * httptest.Server ) * github.Client {
224+ client := github .NewClient (server .Client ())
225+ serverURL , _ := url .Parse (server .URL + "/" )
226+ client .BaseURL = serverURL
227+ return client
228+ }
229+
230+ func TestResourceFileDelete_ArchivedRepo (t * testing.T ) {
231+ // Set up a mock HTTP server that returns an archived repository
232+ mux := http .NewServeMux ()
233+ mux .HandleFunc ("/repos/test-owner/test-repo" , func (w http.ResponseWriter , r * http.Request ) {
234+ w .Header ().Set ("Content-Type" , "application/json" )
235+ fmt .Fprint (w , `{"id":1,"name":"test-repo","full_name":"test-owner/test-repo","archived":true}` )
236+ })
237+ server := httptest .NewServer (mux )
238+ defer server .Close ()
239+
240+ config := & providerConfiguration {
241+ githubClient : newMockGitHubClient (server ),
242+ }
243+
244+ d := newTestResourceData (t , map [string ]interface {}{
245+ repositoryOwnerAttributeName : "test-owner" ,
246+ repositoryNameAttributeName : "test-repo" ,
247+ branchAttributeName : "main" ,
248+ pathAttributeName : "some/file.txt" ,
249+ contentsAttributeName : "some content" ,
250+ })
251+ d .SetId ("test-owner/test-repo:main:some/file.txt" )
252+
253+ // Delete should succeed without error — archived repo skips deletion
254+ err := resourceFileDelete (d , config )
255+ if err != nil {
256+ t .Fatalf ("expected no error for archived repo deletion, got: %v" , err )
257+ }
258+ }
259+
260+ func TestResourceFileDelete_NonArchivedRepo_FileNotFound (t * testing.T ) {
261+ // Set up a mock HTTP server that returns a non-archived repository
262+ // and a 404 for the file content (file doesn't exist)
263+ mux := http .NewServeMux ()
264+ mux .HandleFunc ("/repos/test-owner/test-repo" , func (w http.ResponseWriter , r * http.Request ) {
265+ w .Header ().Set ("Content-Type" , "application/json" )
266+ fmt .Fprint (w , `{"id":1,"name":"test-repo","full_name":"test-owner/test-repo","archived":false}` )
267+ })
268+ mux .HandleFunc ("/repos/test-owner/test-repo/contents/some/file.txt" , func (w http.ResponseWriter , r * http.Request ) {
269+ w .WriteHeader (http .StatusNotFound )
270+ })
271+ server := httptest .NewServer (mux )
272+ defer server .Close ()
273+
274+ config := & providerConfiguration {
275+ githubClient : newMockGitHubClient (server ),
276+ }
277+
278+ d := newTestResourceData (t , map [string ]interface {}{
279+ repositoryOwnerAttributeName : "test-owner" ,
280+ repositoryNameAttributeName : "test-repo" ,
281+ branchAttributeName : "main" ,
282+ pathAttributeName : "some/file.txt" ,
283+ contentsAttributeName : "some content" ,
284+ })
285+ d .SetId ("test-owner/test-repo:main:some/file.txt" )
286+
287+ // Delete should succeed — file not found is treated as already deleted
288+ err := resourceFileDelete (d , config )
289+ if err != nil {
290+ t .Fatalf ("expected no error when file not found on non-archived repo, got: %v" , err )
291+ }
292+ }
0 commit comments