github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/pkg/misc/closure/jstest/jstest.go (about) 1 /* 2 Copyright 2014 The Camlistore Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package jstest uses the Go testing package to test JavaScript code using Node and Mocha. 18 package jstest 19 20 import ( 21 "fmt" 22 "io/ioutil" 23 "net/http" 24 "os" 25 "os/exec" 26 "path/filepath" 27 "strings" 28 "testing" 29 30 "camlistore.org/pkg/misc/closure" 31 ) 32 33 // checkSystemRequirements checks whether system dependencies such as node and npm are present. 34 func checkSystemRequirements() error { 35 binaries := []string{"mocha", "node", "npm"} 36 for _, b := range binaries { 37 if _, err := exec.LookPath(b); err != nil { 38 return fmt.Errorf("Required dependency %q not present", b) 39 } 40 } 41 42 c := exec.Command("npm", "list", "--depth=0") 43 b, _ := c.Output() 44 s := string(b) 45 modules := []string{"mocha", "assert"} 46 for _, m := range modules { 47 if !strings.Contains(s, fmt.Sprintf(" %s@", m)) { 48 return fmt.Errorf("Required npm module %v not present", m) 49 } 50 } 51 return nil 52 } 53 54 func getRepoRoot(target string) (string, error) { 55 dir, err := filepath.Abs(filepath.Dir(target)) 56 if err != nil { 57 return "", fmt.Errorf("Could not get working directory: %v", err) 58 } 59 for ; dir != "" && filepath.Base(dir) != "camlistore.org"; dir = filepath.Dir(dir) { 60 } 61 if dir == "" { 62 return "", fmt.Errorf("Could not find Camlistore repo in ancestors of %q", target) 63 } 64 return dir, nil 65 } 66 67 // writeDeps runs closure.GenDeps() on targetDir and writes the resulting dependencies to a temporary file which will be used during the test run. The entries in the deps files are generated with paths relative to baseJS, which should be Closure's base.js file. 68 func writeDeps(baseJS, targetDir string) (string, error) { 69 closureBaseDir := filepath.Dir(baseJS) 70 depPrefix, err := filepath.Rel(closureBaseDir, targetDir) 71 if err != nil { 72 return "", fmt.Errorf("Could not compute relative path from %q to %q: %v", baseJS, targetDir, err) 73 } 74 75 depPrefix += string(os.PathSeparator) 76 b, err := closure.GenDepsWithPath(depPrefix, http.Dir(targetDir)) 77 if err != nil { 78 return "", fmt.Errorf("GenDepsWithPath failed: %v", err) 79 } 80 depsFile, err := ioutil.TempFile("", "camlistore_closure_test_runner") 81 if err != nil { 82 return "", fmt.Errorf("Could not create temp js deps file: %v", err) 83 } 84 err = ioutil.WriteFile(depsFile.Name(), b, 0644) 85 if err != nil { 86 return "", fmt.Errorf("Could not write js deps file: %v", err) 87 } 88 return depsFile.Name(), nil 89 } 90 91 // TestCwd runs all the tests in the current working directory. 92 func TestCwd(t *testing.T) { 93 err := checkSystemRequirements() 94 if err != nil { 95 t.Logf("WARNING: JavaScript unit tests could not be run due to a missing system dependency: %v.\nIf you are doing something that might affect JavaScript, you might want to fix this.", err) 96 t.Log(err) 97 t.Skip() 98 } 99 100 path, err := os.Getwd() 101 if err != nil { 102 t.Fatalf("Could not determine current directory: %v.", err) 103 } 104 105 repoRoot, err := getRepoRoot(path) 106 if err != nil { 107 t.Fatalf("Could not find repository root: %v", err) 108 } 109 baseJS := filepath.Join(repoRoot, "third_party", "closure", "lib", "closure", "goog", "base.js") 110 bootstrap := filepath.Join(filepath.Dir(baseJS), "bootstrap", "nodejs.js") 111 depsFile, err := writeDeps(baseJS, path) 112 if err != nil { 113 t.Fatal(err) 114 } 115 116 c := exec.Command("mocha", "-r", bootstrap, "-r", depsFile, filepath.Join(path, "*test.js")) 117 b, err := c.CombinedOutput() 118 if err != nil { 119 t.Fatalf(string(b)) 120 } 121 }