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  }