github.com/jimmyfrasche/autoreadme@v0.0.0-20240504231658-aacd7e11c8ba/autoreadme_test.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"io/fs"
     6  	"os"
     7  	"path/filepath"
     8  	"testing"
     9  
    10  	"golang.org/x/tools/txtar"
    11  )
    12  
    13  var join = filepath.Join
    14  
    15  func mkdirp(t *testing.T, path ...string) {
    16  	t.Helper()
    17  	if err := os.MkdirAll(join(path...), 0777); err != nil {
    18  		t.Fatal(err)
    19  	}
    20  }
    21  
    22  func writeFile(t *testing.T, data []byte, path ...string) {
    23  	t.Helper()
    24  	if err := os.WriteFile(join(path...), data, 0666); err != nil {
    25  		t.Fatal(err)
    26  	}
    27  }
    28  
    29  func cd(t *testing.T, path ...string) {
    30  	t.Helper()
    31  	if err := os.Chdir(join(path...)); err != nil {
    32  		t.Fatalf("failed to cd: %s", err)
    33  	}
    34  }
    35  
    36  // See testdata/README.md for instructions on how to add additional test cases.
    37  func TestAutoreadme(t *testing.T) {
    38  	// cd back to the original directory when we're done
    39  	originalDir, err := os.Getwd()
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	t.Cleanup(func() {
    44  		os.Chdir(originalDir)
    45  	})
    46  
    47  	// switch out the default template for one specialized for testing
    48  	src, err := readFile(join("testdata", "test.template"))
    49  	if err != nil {
    50  		t.Fatalf("reading testdata/test.template: %s", err)
    51  	}
    52  	originalSrc := defaultTemplateSrc
    53  	defaultTemplateSrc = string(src)
    54  	t.Cleanup(func() {
    55  		defaultTemplateSrc = originalSrc
    56  	})
    57  
    58  	// use testdata/*.txtar files to build out scenarios for us to test
    59  	cases, err := filepath.Glob(join("testdata", "*.txtar"))
    60  	if err != nil {
    61  		t.Fatalf("getting testdata/*.txtar files: %s", err)
    62  	}
    63  	for _, c := range cases {
    64  		name := filepath.Base(c)
    65  		name = name[:len(name)-len(".txtar")]
    66  
    67  		t.Run(name, func(t *testing.T) {
    68  			cd(t, originalDir)
    69  
    70  			arc, err := txtar.ParseFile(c)
    71  			if err != nil {
    72  				t.Fatal(err)
    73  			}
    74  
    75  			tmp := t.TempDir()
    76  			cd(t, tmp)
    77  
    78  			// always create a .git/ directory at the root
    79  			// to avoid having to specify it in every single test case
    80  			mkdirp(t, ".git")
    81  
    82  			// write out the archive in tmp
    83  			for _, file := range arc.Files {
    84  				name := filepath.FromSlash(file.Name)
    85  				dir := filepath.Dir(name)
    86  				if dir != "" {
    87  					mkdirp(t, dir)
    88  				}
    89  				writeFile(t, file.Data, name)
    90  			}
    91  
    92  			// do the thing
    93  			if err = Main(context.Background()); err != nil {
    94  				t.Fatalf("running autoreadme: %s", err)
    95  			}
    96  
    97  			// collect all generated README.md and README.md.expect contents, keyed by location
    98  			expect := map[string]string{}
    99  			got := map[string]string{}
   100  			err = filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error {
   101  				if err != nil {
   102  					return err
   103  				}
   104  				if d.IsDir() {
   105  					return nil
   106  				}
   107  				name := d.Name()
   108  				switch name {
   109  				default:
   110  					return nil
   111  				case "README.md", "README.md.expect":
   112  				}
   113  				bs, err := readFile(path)
   114  				if err != nil {
   115  					return err
   116  				}
   117  				contents := string(bs)
   118  				path = filepath.Dir(path)
   119  				if name == "README.md.expect" {
   120  					expect[path] = contents
   121  				} else {
   122  					got[path] = contents
   123  				}
   124  				return nil
   125  			})
   126  			if err != nil {
   127  				t.Fatal(err)
   128  			}
   129  
   130  			for k, v := range expect {
   131  				if _, ok := got[k]; !ok {
   132  					t.Errorf("README.md.expect with no README.md at %s\n %s", k, v)
   133  				}
   134  			}
   135  			for k, v := range got {
   136  				v2, ok := expect[k]
   137  				if !ok {
   138  					t.Errorf("README.md without README.md.expect at %s:\n%s", k, v)
   139  				} else if v != v2 {
   140  					t.Errorf("README.md difference at %s:\nGOT:\n%s\nEXPECTED:\n%s", k, v, v2)
   141  				}
   142  			}
   143  		})
   144  	}
   145  }