Merge pull request #313 from reagent-project/new-test-runner

New test runner
This commit is contained in:
Juho Teperi 2017-10-20 10:20:11 +03:00 committed by GitHub
commit c63fe944fd
84 changed files with 5646 additions and 2151 deletions

10
.gitignore vendored
View File

@ -4,18 +4,14 @@ pom.xml
pom.xml.asc
.nrepl-port
demo/empty.cljs
outsite/public/index.html
outsite/public/js
outsite/public/news
outsite/public/css
out
tmp
figwheel_server.log
reagent.iml
.idea
.lein-failures
outsite/bundle.js
outsite/bundle.min.js
node_modules
pre-render
test-environments/*/junit

145
Makefile
View File

@ -1,145 +0,0 @@
PROF =
PORT = 3449
SITEDIR = outsite/public
OUTPUTDIR = $(SITEDIR)/js/out
# convenience shortcuts for continous building
##############################################
# development build with auto-reloading
run: figwheel
# development build with auto-reloading and site generation
runsite:
@$(MAKE) run PROF=+site,$(PROF)
# development build with auto-reloading and webpacked source
runpack: target/webpack/bundle.js
@$(MAKE) run PROF=+webpack,$(PROF)
# development build with figwheel, but no tests
runnotest:
@$(MAKE) run PROF=dev-notest,$(PROF)
# production build with auto-rebuild
runprod: clean
@$(MAKE) serve-site PROF=prod,$(PROF)
# production build with auto-rebuild and webpacked source
runprodpack: clean target/webpack/bundle.js
@$(MAKE) serve-site PROF=prod,webpack,$(PROF)
# production build with auto-rebuild and testing
runprodtest: clean
@$(MAKE) serve-site PROF=prod-test,$(PROF)
clean:
lein clean
## Subtargets
figwheel: trigger-build
@echo "Will start figwheel server at: http://127.0.0.1:$(PORT)\n"
lein with-profile $(PROF), figwheel
serve-site: trigger-build
@echo "Starting site at: http://127.0.0.1:$(PORT)/public\n"
( trap "kill 0" SIGINT SIGTERM EXIT; \
( cd $(SITEDIR)/.. && python -m SimpleHTTPServer $(PORT) & ); \
lein with-profile $(PROF), cljsbuild auto )
trigger-build:
# always trigger build to make sure page-generation works
@echo "(ns empty.generated.ns)" > demo/empty.cljs
@(echo "/* Generated, do not modify */\n\n" && \
cat examples/todomvc/todos.css examples/simple/example.css) \
> site/public/css/examples.css
## gh-pages support
###################
# build site and push upstream to the gh-pages branch
push-gh-pages: build-gh-pages
git push origin gh-pages:gh-pages
# build site and push to reagent-project's doc site
push-project-docs: gen-site gen-docs
# sanity check
test -f $(SITEDIR)/index.html
test ! -e $(OUTPUTDIR)
rm -fr tmp
git clone git@github.com:reagent-project/reagent-project.github.io.git tmp
rm -fr tmp/*
cp -r $(SITEDIR)/* tmp/
mkdir -p tmp/docs/master/
cp -r target/doc/* tmp/docs/master/
cd tmp && \
git add . && git commit -m "Updated" && \
git push
rm -rf tmp
# build site into a gh-pages branch
build-gh-pages: gen-site gh-pages-add
gen-site: clean
lein with-profile prod cljsbuild once
lein with-profile prerender cljsbuild once
gen-docs: clean
lein codox
# copy contents of $(SITEDIR) to branch gh-pages
gh-pages-add:
# sanity check
test -f $(SITEDIR)/index.html
test ! -e $(OUTPUTDIR)
# make sure gh-pages branch exists
git show-branch gh-pages || true | git mktree | \
xargs git commit-tree | xargs git branch gh-pages
# clone gh-pages branch, and commit site to that
cd $(SITEDIR) && \
rm -rf .git tmp && \
git clone ../.. -lnb gh-pages tmp && \
mv tmp/.git . && \
git add . && git commit -m "Updated" && \
git push && rm -rf .git tmp
## Webpack
##########
target/webpack/bundle.js: node_modules lib/modules.js package.json Makefile
npm run bundle
node_modules:
npm install
## Misc utilities
#################
show-outdated:
lein ancient :all
VERSION := `sed -n -e '/(defproject reagent/ s/.*"\(.*\)"/\1/p' project.clj`
setversion:
version=$(VERSION); \
find . -name project.clj -o -name README.md | \
xargs -n1 sed -i "" -e 's,\(reagent "\)\([^"]*\)",\1'"$$version"'"',g
tag: setversion
if git rev-parse v$(VERSION) 2>/dev/null; then \
echo "Tag already exists"; \
exit 1; \
else \
git commit --allow-empty -a -v -e -m"Version "$(VERSION) && \
git tag v$(VERSION); \
fi

View File

@ -14,7 +14,7 @@ Reagent provides a way to write efficient React components using (almost) nothin
### Prerequisites
* [JDK](http://www.azul.com/downloads/zulu/)
* Java JDK
* [Leiningen](http://leiningen.org/)
### Usage
@ -36,7 +36,7 @@ To use Reagent in an existing project you add this to your dependencies in `proj
This is all you need to do if you want the standard version of React. If you want the version of React with addons, you'd use something like this instead:
[reagent "0.6.0" :exclusions [cljsjs/react]]
[reagent "0.7.0" :exclusions [cljsjs/react]]
[cljsjs/react-with-addons "15.4.2-2"]
If you want to use your own build of React (or React from a CDN), you have to use `:exclusions` variant of the dependency, and also provide a file named "cljsjs/react.cljs", containing just `(ns cljsjs.react)`, in your project.

View File

@ -1,42 +0,0 @@
var fs = require("fs");
var vm = require("vm");
var path = require("path");
var run = function (src) {
global.require = require;
vm.runInThisContext(fs.readFileSync(src), src);
}
var imported = {};
var loadSrc = function (mainFile, outputDir, devFile) {
var googDir = path.join(outputDir, "goog");
var optNone = false;
if (outputDir) {
optNone = fs.existsSync(path.join(googDir, "deps.js"));
}
if (optNone) {
var cwd = process.cwd();
if (!global.goog) {
global.goog = {};
}
global.CLOSURE_IMPORT_SCRIPT = function (src) {
var s = path.resolve(path.resolve(cwd, path.join(googDir, src)));
if (!(s in imported)) {
imported[s] = true;
run(s);
return true;
}
};
run(path.join(googDir, "base.js"));
run(path.join(outputDir, "cljs_deps.js"));
run(path.join(outputDir, devFile));
} else {
run(mainFile);
}
return optNone;
};
exports.load = loadSrc;

View File

@ -1,40 +0,0 @@
var cljsLoad = require("./cljs-load");
var srcFile = "pre-render/main.js";
var outputDirectory = "outsite/public/js/out";
var devFile = "reagenttest/runtests.js";
var beep = "\u0007";
if (typeof location === "undefined") {
// figwheel wants js/location to exist, even if it doesn't run,
// for some reason
global.location = {};
}
var gensite = function () {
console.log("Pre-rendering or testing...");
var optNone = cljsLoad.load(srcFile, outputDirectory, devFile);
sitetools.server.genpages({"opt-none": optNone});
}
var compileFail = function () {
var msg = process.argv[process.argv.length - 1];
if (msg && msg.match(/failed/)) {
console.log("Compilation failed" + beep);
return true;
}
};
process.env.NODE_ENV = "production";
if (!compileFail()) {
try {
gensite();
} catch (e) {
console.log(e + beep);
console.error(e.stack);
process.exit(1);
}
}
process.exit(0);

39
build-example-site.sh Executable file
View File

@ -0,0 +1,39 @@
#!/bin/bash
set -ex
SHA=$(git rev-parse HEAD)
# sanity check
rm -fr tmp
git clone git@github.com:reagent-project/reagent-project.github.io.git tmp
rm -fr tmp/*
# Prerendering seems to work best on React 16
cd test-environments/browser-node-react-16
lein do clean, cljsbuild once prod
cp -r target/cljsbuild/prod/public/* ../../tmp/
lein cljsbuild once prerender
node target/cljsbuild/prerender/main.js
cp -r target/prerender/public/* ../../tmp/
cd ../..
test -f tmp/index.html
test -f tmp/js/main.js
test ! -e tmp/js/out
lein codox
mkdir -p tmp/docs/master/
cp -r target/doc/* tmp/docs/master/
cd tmp
git checkout -- README.md
git add .
git commit -m "Built site from $SHA"
git push
rm -rf tmp

View File

@ -1,17 +1,21 @@
machine:
node:
version: v8.2.0
environment:
JVM_OPTS: "-Xms512m -Xmx1024m"
dependencies:
override:
- lein deps
- npm install -g karma-cli
- ./prepare-tests.sh
cache_directories:
- test-environments/browser-node/node_modules
- test-environments/browser-node-react-16/node_modules
test:
override:
# Run tests against Cljsjs
- mv node_modules node_modules_disabled
- lein with-profile dev do clean, cljsbuild once
- node bin/gen-site.js
- test -f outsite/public/js/out/cljsjs/react/development/react.inc.js
- lein with-profile prod-test do clean, cljsbuild once
# Run tests against Node Modules
- mv node_modules_disabled
- lein clean
- lein with-profile dev do clean, cljsbuild once
- node bin/gen-site.js
- test -f outsite/public/js/out/node_modules/react/react.js
- ./run-tests.sh
deployment:
master:
branch: master
commands:
- ./build-example-site.sh

View File

@ -7,8 +7,6 @@
[reagentdemo.news :as news]
[reagent.debug :refer-macros [dbg println]]))
(def test-results (r/atom nil))
(def github {:href "https://github.com/reagent-project/reagent"})
(defn github-badge []
@ -23,8 +21,7 @@
(tools/register-page index-page [#'intro/main] title)
(defn demo []
(defn demo [& [test-component]]
[:div
[:div.nav>ul.nav
[:li.brand [link {:href index-page} "Reagent:"]]
@ -32,14 +29,12 @@
[:li [link {:href news/url} "News"]]
[:li>a github "GitHub"]
[:li [:a {:href "http://reagent-project.github.io/docs/master/"} "API"]]]
[:div @test-results]
[:div test-component]
[tools/main-content]
[github-badge]])
(defn init! []
(tools/start! {:body [#'demo]
(defn init! [& [test-component]]
(tools/start! {:body [#'demo test-component]
:title-prefix "Reagent: "
:css-infiles ["site/public/css/examples.css"
"site/public/css/main.css"]}))
(init!)

View File

@ -0,0 +1,9 @@
(ns reagentdemo.dev
"Initializes the demo app, and runs the tests."
(:require [reagentdemo.core :as core]
[reagenttest.runtests :as tests]))
(defn init! []
(core/init! (tests/init!)))
(init!)

View File

@ -1,4 +0,0 @@
(ns reagentdemo.server
"Used to pre-render HTML files."
(:require [reagentdemo.core]
[sitetools.server]))

View File

@ -16,7 +16,7 @@
(defonce config (r/atom {:body [#'main-content]
:pages {"/index.html" {:content [:div]
:title ""}}
:site-dir "outsite/public"
:site-dir "target/prerender/public/"
:css-infiles ["site/public/css/main.css"]
:css-file "css/built.css"
:js-file "js/main.js"

View File

@ -0,0 +1,20 @@
(ns sitetools.prerender
(:require [reagent.debug :refer-macros [log]]
[sitetools.core :as tools]
[sitetools.server :as server]
[reagentdemo.core :as demo]))
(defn -main [& args]
(log "Generating site")
(demo/init!)
(let [conf @tools/config
conf (assoc conf :timestamp (str "?" (js/Date.now)))
{:keys [site-dir pages]} conf]
(doseq [f (keys pages)]
(server/write-file (->> f tools/to-relative (server/path-join site-dir))
(server/gen-page f conf)))
(server/write-resources site-dir conf))
(log "Wrote site")
(js/process.exit 0))
(set! *main-cli-fn* -main)

View File

@ -57,6 +57,7 @@
($ (fs) mkdirSync d))))
(defn write-file [f content]
(log "Write" f)
(mkdirs ($ (path) dirname f))
($ (fs) writeFileSync f content))
@ -68,16 +69,3 @@
(->> css-infiles
(map #($ (fs) readFileSync %))
(string/join "\n"))))
;;; Main entry points
(defn ^:export genpages [opts]
(log "Generating site")
(let [conf (swap! tools/config merge (js->clj opts :keywordize-keys true))
conf (assoc conf :timestamp (str "?" (js/Date.now)))
{:keys [site-dir pages]} conf]
(doseq [f (keys pages)]
(write-file (->> f tools/to-relative (path-join site-dir))
(gen-page f conf)))
(write-resources site-dir conf))
(log "Wrote site"))

31
docs/development.md Normal file
View File

@ -0,0 +1,31 @@
# Reagent development
## Running tests
To prepare different environments for tests run:
```bash
./prepare-test.sh
```
After this, you can run the full test set:
```bash
./run-tests.sh
```
Running all the tests can take a while, so while developing Reagent,
you might want to focus on one test environment, and use Figwheel to
run tests on your browser:
```
cd test-environments/browser-umd-react-16
# If build requires e.g. Lein profiles or such,
# the folder contains figwheel.sh script:
./figwheel.sh
# Else, just run figwheel normally:
lein figwheel
# Open http://0.0.0.0:3449 on a browser
# Check console for test output
```

2530
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,9 @@
{
"dependencies": {
"@cljs-oss/module-deps": "1.1.1",
"create-react-class": "^15.6.2",
"react": "^15.6.1",
"react-dom": "^15.6.1"
},
"scripts": {
"bundle": "webpack && NODE_ENV=production webpack -p"
},
"private": true,
"devDependencies": {
"babel-core": "^5.8.25",
"webpack": "^1.12.2"
"karma": "^1.7.1",
"karma-chrome-launcher": "^2.2.0",
"karma-cljs-test": "^0.1.0",
"karma-junit-reporter": "^1.2.0"
}
}

23
prepare-tests.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
npm install
echo
# Symlinked node_modules, package.json and package-lock.json
# are used to share node_modules between environments that
# use the same packages.
for env in test-environments/*; do
name=$(basename "$env")
(
cd "$env"
if [[ ! -L node_modules ]]; then
echo "Install $name packages"
npm install
else
echo "$name uses $(readlink node_modules)"
fi
)
echo
done

View File

@ -4,7 +4,7 @@
:description "A simple ClojureScript interface to React"
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.908"]
[org.clojure/clojurescript "1.9.946"]
;; If :npm-deps enabled, these are used only for externs.
;; Without direct react dependency, other packages,
;; like react-leaflet might have closer dependency to a other version.
@ -14,7 +14,9 @@
[cljsjs/create-react-class "15.6.2-0"]]
:plugins [[lein-cljsbuild "1.1.7"]
[lein-codox "0.10.3"]]
[lein-doo "0.1.8"]
[lein-codox "0.10.3"]
[lein-figwheel "0.5.14"]]
:source-paths ["src"]
@ -22,89 +24,86 @@
:exclude clojure.string
:source-paths ["src"]}
:profiles {:test {:cljsbuild
{:builds {:client {:source-paths ["test"]
:notify-command ["node" "bin/gen-site.js"]
:compiler
{:main "reagenttest.runtests"}}}}}
:profiles {:react-16 {:dependencies [[cljsjs/react "16.0.0-0"]
[cljsjs/react-dom "16.0.0-0"]
[cljsjs/react-dom-server "16.0.0-0"]]}
:fig [{:dependencies [[figwheel "0.5.13"]]
:plugins [[lein-figwheel "0.5.13"]]
:source-paths ["demo"] ;; for lighttable
:resource-paths ["site" "outsite"]
:figwheel {:css-dirs ["site/public/css"]}
:cljsbuild
{:builds
{:client
{:figwheel true
:compiler {:source-map true
:optimizations :none
;; :recompile-dependents false
:output-dir "outsite/public/js/out"
:asset-path "js/out"}}}}}]
:dev {:dependencies [[figwheel "0.5.14"]
[doo "0.1.8"]]
:source-paths ["demo" "examples/todomvc/src" "examples/simple/src" "examples/geometry/src"]
:resource-paths ["site" "target/cljsbuild/client"]}}
:site {:resource-paths ^:replace ["outsite"]
:figwheel {:css-dirs ^:replace ["outsite/public/css"]}}
:prod [:site
{:cljsbuild
{:builds {:client
{:compiler {:optimizations :advanced
:elide-asserts true
:pretty-print false
;; :pseudo-names true
:output-dir "target/client"}}}}}]
:prerender [:prod
{:cljsbuild
{:builds {:client
{:compiler {:main "reagentdemo.server"
:output-to "pre-render/main.js"
:output-dir "pre-render/out"}
:notify-command ["node" "bin/gen-site.js"] }}}}]
:webpack {:cljsbuild
{:builds {:client
{:compiler
{:foreign-libs
[{:file "target/webpack/bundle.js"
:file-min "target/webpack/bundle.min.js"
:provides ["cljsjs.react.dom"
"cljsjs.react.dom.server"
"cljsjs.react"]
:requires []}]}}}}}
:prod-test [:prod :test]
:dev [:fig :test]
:dev-notest [:fig]}
:clean-targets ^{:protect false} [:target-path :compile-path
"outsite/public/js"
"outsite/public/site"
"outsite/public/news"
"outsite/public/css"
"outsite/public/index.html"
"out"
"pre-render"]
:cljsbuild {:builds {:client
{:source-paths ["src"
"demo"
"examples/todomvc/src"
"examples/simple/src"
"examples/geometry/src"]
:compiler {:parallel-build true
:main "reagentdemo.core"
:output-to "outsite/public/js/main.js"
:language-in :ecmascript6
:language-out :ecmascript3
;; Add process.env.NODE_ENV preload
:process-shim true
:npm-deps {:react "15.6.1"
:react-dom "15.6.1"
:create-react-class "15.6.2"}}}}}
:clean-targets ^{:protect false} [:target-path :compile-path "out"]
:figwheel {:http-server-root "public" ;; assumes "resources"
:repl false})
:css-dirs ["site/public/css"]
:repl false}
;; No profiles and merging - just manual configuration for each build type
:cljsbuild
{:builds
{:client
{:source-paths ["demo" "test"]
:figwheel true
:compiler {:parallel-build true
:source-map true
:optimizations :none
; :main "reagentdemo.core"
:main "reagentdemo.dev"
:output-dir "target/cljsbuild/client/public/js/out"
:output-to "target/cljsbuild/client/public/js/main.js"
:asset-path "js/out"
;; add process.env.node_env preload
:process-shim true}}
:test
{:source-paths ["test"]
:compiler {:parallel-build true
:source-map true
:optimizations :none
:main "reagenttest.runtests"
:asset-path "js/out"
:output-dir "target/cljsbuild/test/out"
:output-to "target/cljsbuild/test/main.js"
;; add process.env.node_env preload
:process-shim true}}
:prerender
{:source-paths ["demo"]
:compiler {:main "sitetools.prerender"
:target :nodejs
:process-shim false
:output-dir "target/cljsbuild/prerender/out"
:output-to "target/cljsbuild/prerender/main.js"}}
:node-test
{:source-paths ["test"]
:compiler {:main "reagenttest.runtests"
:target :nodejs
:parallel-build true
:source-map true
:optimizations :none
:output-dir "target/cljsbuild/node-test/out"
:output-to "target/cljsbuild/node-test/main.js"}}
:prod
{:source-paths ["demo"]
:compiler {:main "reagentdemo.core"
:optimizations :advanced
:elide-asserts true
:pretty-print false
;; :pseudo-names true
:output-to "target/cljsbuild/prod/public/js/main.js"
:output-dir "target/cljsbuild/prod/out" ;; Outside of public, not published
:closure-warnings {:global-this :off}}}
:prod-test
{:source-paths ["demo"]
:compiler {:main "reagenttest.runtests"
:optimizations :advanced
:elide-asserts true
:pretty-print false
;; :pseudo-names true
:output-to "target/cljsbuild/prod-test/main.js"
:output-dir "target/cljsbuild/prod-test/out"
:closure-warnings {:global-this :off}}}}})

39
run-tests.sh Executable file
View File

@ -0,0 +1,39 @@
#!/bin/bash
# Kill all subshells with ctrl-c
trap "kill 0" SIGINT
reset='\033[0m'
red='\033[0;31m'
green='\033[0;32m'
blue='\033[0;34m'
EXIT=0
SUMMARY="$blue##\n## SUMMARY\n##$reset\n\n"
for env in test-environments/*; do
name=$(basename "$env")
(
cd "$env"
echo -e "$blue##"
echo -e "## TESTING $name"
echo -e "##$reset"
echo
./test.sh
)
if [[ $? != "0" ]]; then
echo
echo -e "${red}FAIL $name$reset"
SUMMARY="$SUMMARY${red}FAIL $name$reset\n"
EXIT=1
else
SUMMARY="$SUMMARY${green}OK $name$reset\n"
fi
echo
echo
done
echo -e "$SUMMARY"
exit $EXIT

View File

@ -199,6 +199,10 @@
(when-not (nil? f)
(.call f c c))))
:componentDidCatch
(fn componentDidCatch [error info]
(this-as c (.call f c c error info)))
nil))
(defn get-wrapper [key f name]
@ -267,20 +271,35 @@
cljsify
create-react-class))
(defn component-path [c]
(let [elem (some-> (or (some-> c ($ :_reactInternalInstance))
c)
($ :_currentElement))
name (some-> elem
(defn fiber-component-path [fiber]
(let [name (some-> fiber
($ :type)
($ :displayName))
path (some-> elem
($ :_owner)
component-path
parent (some-> fiber
($ :return))
path (some-> parent
fiber-component-path
(str " > "))
res (str path name)]
(when-not (empty? res) res)))
(defn component-path [c]
;; Alternative branch for React 16
(if-let [fiber (some-> c ($ :_reactInternalFiber))]
(fiber-component-path fiber)
(let [elem (or (some-> (or (some-> c ($ :_reactInternalInstance))
c)
($ :_currentElement)))
name (some-> elem
($ :type)
($ :displayName))
path (some-> elem
($ :_owner)
component-path
(str " > "))
res (str path name)]
(when-not (empty? res) res))))
(defn comp-name []
(if (dev?)
(let [c *current-component*

View File

@ -0,0 +1 @@
../../demo

View File

@ -0,0 +1 @@
../../examples

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
{
"dependencies": {
"@cljs-oss/module-deps": "1.1.1",
"create-react-class": "^15.6.2",
"react": "^16.0.0",
"react-dom": "^16.0.0"
},
"devDependencies": {
"karma": "^1.7.1",
"karma-chrome-launcher": "^2.2.0",
"karma-cljs-test": "^0.1.0",
"karma-junit-reporter": "^1.2.0"
}
}

View File

@ -0,0 +1 @@
../../project.clj

View File

@ -0,0 +1 @@
../../site

View File

@ -0,0 +1 @@
../../src

View File

@ -0,0 +1 @@
../../test

View File

@ -0,0 +1,4 @@
#!/bin/bash
set -ex
lein do clean, doo chrome-headless test once
test -f target/cljsbuild/test/out/node_modules/react/index.js

View File

@ -0,0 +1 @@
../../demo

View File

@ -0,0 +1 @@
../../examples

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
{
"dependencies": {
"@cljs-oss/module-deps": "1.1.1",
"create-react-class": "^15.6.2",
"react": "^15.6.2",
"react-dom": "^15.6.2"
},
"devDependencies": {
"karma": "^1.7.1",
"karma-chrome-launcher": "^2.2.0",
"karma-cljs-test": "^0.1.0",
"karma-junit-reporter": "^1.2.0"
}
}

View File

@ -0,0 +1 @@
../../project.clj

View File

@ -0,0 +1 @@
../../site

View File

@ -0,0 +1 @@
../../src

View File

@ -0,0 +1 @@
../../test

View File

@ -0,0 +1,4 @@
#!/bin/bash
set -ex
lein do clean, doo chrome-headless test once
test -f target/cljsbuild/test/out/node_modules/react/react.js

View File

@ -0,0 +1 @@
../../demo

View File

@ -0,0 +1 @@
../../examples

View File

@ -0,0 +1 @@
../browser-umd/node_modules

View File

@ -0,0 +1 @@
../browser-umd/package-lock.json

View File

@ -0,0 +1 @@
../browser-umd/package.json

View File

@ -0,0 +1 @@
../../project.clj

View File

@ -0,0 +1 @@
../../site

View File

@ -0,0 +1 @@
../../src

View File

@ -0,0 +1 @@
../../test

View File

@ -0,0 +1,4 @@
#!/bin/bash
set -x
lein do clean, doo chrome-headless prod-test once
test -f target/cljsbuild/prod-test/main.js

View File

@ -0,0 +1 @@
../../demo

View File

@ -0,0 +1 @@
../../examples

View File

@ -0,0 +1,3 @@
#!/bin/bash
set -x
lein with-profile react-16 figwheel

View File

@ -0,0 +1 @@
../browser-umd/node_modules

View File

@ -0,0 +1 @@
../browser-umd/package-lock.json

View File

@ -0,0 +1 @@
../browser-umd/package.json

View File

@ -0,0 +1 @@
../../project.clj

View File

@ -0,0 +1 @@
../../site

View File

@ -0,0 +1 @@
../../src

View File

@ -0,0 +1 @@
../../test

View File

@ -0,0 +1,4 @@
#!/bin/bash
set -ex
lein with-profile dev,react-16 do clean, doo chrome-headless test once
test -f target/cljsbuild/test/out/cljsjs/react/development/react.inc.js

View File

@ -0,0 +1 @@
../../demo

View File

@ -0,0 +1 @@
../../examples

View File

@ -0,0 +1 @@
../../node_modules

View File

@ -0,0 +1 @@
../../package-lock.json

View File

@ -0,0 +1 @@
../../package.json

View File

@ -0,0 +1 @@
../../project.clj

View File

@ -0,0 +1 @@
../../site

View File

@ -0,0 +1 @@
../../src

View File

@ -0,0 +1 @@
../../test

View File

@ -0,0 +1,4 @@
#!/bin/bash
set -ex
lein do clean, doo chrome-headless test once
test -f target/cljsbuild/test/out/cljsjs/react/development/react.inc.js

1
test-environments/node/demo Symbolic link
View File

@ -0,0 +1 @@
../../demo

View File

@ -0,0 +1 @@
../../examples

View File

@ -0,0 +1 @@
../browser-node/node_modules

1
test-environments/node/package-lock.json generated Symbolic link
View File

@ -0,0 +1 @@
../browser-node/package-lock.json

View File

@ -0,0 +1 @@
../browser-node/package.json

View File

@ -0,0 +1 @@
../../project.clj

1
test-environments/node/site Symbolic link
View File

@ -0,0 +1 @@
../../site

1
test-environments/node/src Symbolic link
View File

@ -0,0 +1 @@
../../src

1
test-environments/node/test Symbolic link
View File

@ -0,0 +1 @@
../../test

5
test-environments/node/test.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
set -ex
lein do clean, doo node node-test once
test ! -f target/cljsbuild/node-test/out/node_modules/react/index.js
grep "reagent.impl.template.node\$module\$react = require('react')" target/cljsbuild/node-test/out/reagent/impl/template.js

View File

@ -8,9 +8,9 @@
[reagenttest.testwithlet]
[reagenttest.testwrap]
[cljs.test :as test :include-macros true]
[doo.runner :as doo :refer-macros [doo-tests]]
[reagent.core :as r]
[reagent.debug :refer-macros [dbg log]]
[reagentdemo.core :as demo]
[sitetools.server]))
(enable-console-print!)
@ -50,9 +50,18 @@
"testing")]))
(defn init! []
;; This function is only used when running tests from the demo app.
;; Which is why exit-point is set manually.
(when (some? (test/deftest empty-test))
;; Only run with :load-tests true
(reset! demo/test-results [#'test-output-mini])
(run-tests)))
(doo/set-exit-point! (fn [success?] nil))
(run-tests)
[#'test-output-mini]))
(init!)
(doo-tests 'reagenttest.testreagent
'reagenttest.testcursor
'reagenttest.testinterop
'reagenttest.testratom
'reagenttest.testratomasync
'reagenttest.testtrack
'reagenttest.testwithlet
'reagenttest.testwrap)

View File

@ -1,5 +1,6 @@
(ns reagenttest.testreagent
(:require [cljs.test :as t :refer-macros [is deftest testing]]
[react :as react]
[create-react-class :as create-react-class]
[reagent.ratom :as rv :refer-macros [reaction]]
[reagent.debug :as debug :refer-macros [dbg println log dev?]]
@ -23,21 +24,15 @@
(def rflush r/flush)
(defn add-test-div [name]
(let [doc js/document
body (.-body js/document)
div (.createElement doc "div")]
(.appendChild body div)
div))
(defn with-mounted-component [comp f]
(when isClient
(let [div (add-test-div "_testreagent")]
(let [c (r/render comp div)]
(f c div)
(r/unmount-component-at-node div)
(r/flush)
(.removeChild (.-body js/document) div)))))
(let [div (.createElement js/document "div")]
(try
(let [c (r/render comp div)]
(f c div))
(finally
(r/unmount-component-at-node div)
(r/flush))))))
(defn found-in [re div]
(let [res (.-innerHTML div)]
@ -282,16 +277,18 @@
(deftest data-aria-test []
(is (re-find #"data-foo"
(as-string [:div {:data-foo "x"}])))
(is (re-find #"aria-foo"
(as-string [:div {:aria-foo "x"}])))
(is (re-find #"aria-labelledby"
(as-string [:div {:aria-labelledby "x"}])))
;; Skip test: produces warning in new React
;; (is (not (re-find #"enctype"
;; (as-string [:div {"enc-type" "x"}])))
;; "Strings are passed through to React.")
(is (re-find #"enctype"
;; FIXME: For some reason UMD module returns everything in
;; lowercase, and CommonJS with upper T
(is (re-find #"enc[tT]ype"
(as-string [:div {"encType" "x"}]))
"Strings are passed through to React, and have to be camelcase.")
(is (re-find #"enctype"
(is (re-find #"enc[tT]ype"
(as-string [:div {:enc-type "x"}]))
"Strings are passed through to React, and have to be camelcase."))
@ -906,6 +903,29 @@
(defn foo []
[:div])
(defn log-error [& f]
(debug/error (apply str f)))
(defn wrap-capture-window-error [f]
(fn []
(let [org js/console.onerror]
(set! js/window.onerror (fn [e]
(log-error e)
true))
(try
(f)
(finally
(set! js/window.onerror org))))))
(defn wrap-capture-console-error [f]
(fn []
(let [org js/console.error]
(set! js/console.error log-error)
(try
(f)
(finally
(set! js/console.error org))))))
(deftest test-err-messages
(when (dev?)
(is (thrown-with-msg?
@ -939,24 +959,27 @@
pkg "reagenttest.testreagent."
stack1 (str "in " pkg "comp1")
stack2 (str "in " pkg "comp2 > " pkg "comp1")
lstr (fn [& s] (list (apply str s)))
re (fn [& s]
(re-pattern (apply str s)))
rend (fn [x]
(with-mounted-component x identity))]
(let [e (debug/track-warnings
#(is (thrown-with-msg?
:default (re "Invalid tag: 'div.' \\(" stack2 "\\)")
(rend [comp2 [:div. "foo"]]))))]
(is (= e
{:error (lstr "Error rendering component (" stack2 ")")})))
(wrap-capture-window-error
(wrap-capture-console-error
#(is (thrown-with-msg?
:default (re "Invalid tag: 'div.' \\(" stack2 "\\)")
(rend [comp2 [:div. "foo"]]))))))]
(is (= (last (:error e))
(str "Error rendering component (" stack2 ")"))))
(let [e (debug/track-warnings
#(is (thrown-with-msg?
:default (re "Invalid tag: 'div.' \\(" stack1 "\\)")
(rend [comp1 [:div. "foo"]]))))]
(is (= e
{:error (lstr "Error rendering component (" stack1 ")")})))
(wrap-capture-window-error
(wrap-capture-console-error
#(is (thrown-with-msg?
:default (re "Invalid tag: 'div.' \\(" stack1 "\\)")
(rend [comp1 [:div. "foo"]]))))))]
(is (= (last (:error e))
(str "Error rendering component (" stack1 ")"))))
(let [e (debug/track-warnings #(r/as-element [nat]))]
(is (re-find #"Using native React classes directly"
@ -972,6 +995,29 @@
(is (re-find #"Every element in a seq should have a unique :key"
(-> e :warn first))))))))
(deftest test-error-boundary
(when (>= (js/parseInt react/version) 16)
(let [error (r/atom nil)
error-boundary (fn error-boundary [comp]
(r/create-class
{:component-did-catch (fn [this e info]
(reset! error e))
:reagent-render (fn [comp]
(if @error
[:div "Something went wrong."]
comp))}))
comp1 (fn comp1 []
($ nil :foo)
[:div "foo"])]
(debug/track-warnings
(wrap-capture-window-error
(wrap-capture-console-error
#(with-mounted-component [error-boundary [comp1]]
(fn [c div]
(r/flush)
(is (= "Cannot read property 'foo' of null" (.-message @error)))
(is (found-in #"Something went wrong\." div))))))))))
(deftest test-dom-node
(let [node (atom nil)
ref (atom nil)
@ -1032,6 +1078,6 @@
(is (= @node nil))))
(deftest style-property-names-are-camel-cased
(is (= "<div style=\"text-align:center;\">foo</div>"
(server/render-to-static-markup
[:div {:style {:text-align "center"}} "foo"]))))
(is (re-find #"<div style=\"text-align:center(;?)\">foo</div>"
(server/render-to-static-markup
[:div {:style {:text-align "center"}} "foo"]))))

View File

@ -3,20 +3,32 @@
[reagent.debug :refer-macros [dbg println log]]
[reagent.core :as r]))
(defn add-test-div [name]
(let [doc js/document
body (.-body js/document)
div (.createElement doc "div")]
(.appendChild body div)
div))
(defn with-mounted-component [comp f]
(when r/is-client
(let [div (add-test-div "_testreagent")]
(let [comp (r/render comp div #(f comp div))]
(r/unmount-component-at-node div)
(r/flush)
(.removeChild (.-body js/document) div)))))
(let [div (.createElement js/document "div")]
(try
(let [c (r/render comp div)]
(f c div))
(finally
(r/unmount-component-at-node div)
(r/flush))))))
(defn with-mounted-component-async [comp done f]
(when r/is-client
(let [div (.createElement js/document "div")
c (r/render comp div)]
(f c div (fn []
(r/unmount-component-at-node div)
(r/flush)
(done))))))
(defn run-fns-after-render [& fs]
((reduce (fn [cb f]
(fn []
(r/after-render (fn []
(f)
(cb)))))
(reverse fs))))
(defn found-in [re div]
(let [res (.-innerHTML div)]
@ -45,7 +57,7 @@
(is (= @w1 @w2))
(is (not= w1 w2))
(reset! w1 1))
(let [w1 (ws) w2 (ws)]
(is (= @w1 1))
(is (= w1 w2))
@ -129,86 +141,92 @@
parent (fn []
[child (r/wrap (:foo @state)
swap! state assoc :foo)])]
(with-mounted-component [parent]
(fn [c div]
(is (found-in #"value:1:" div))
(is (= @ran 1))
(t/async done
(with-mounted-component-async [parent] done
(fn [c div done]
(run-fns-after-render
(fn []
(is (found-in #"value:1:" div))
(is (= @ran 1))
(reset! @grand-state {:foobar 2})
(is (= @state {:foo {:bar {:foobar 2}}}))
(r/flush)
(is (= @ran 2))
(is (found-in #"value:2:" div))
(reset! @grand-state {:foobar 2}))
(fn []
(is (= @state {:foo {:bar {:foobar 2}}}))
(is (= @ran 2))
(is (found-in #"value:2:" div))
(swap! state update-in [:foo :bar] assoc :foobar 3)
(r/flush)
(is (= @ran 3))
(is (found-in #"value:3:" div))
(swap! state update-in [:foo :bar] assoc :foobar 3))
(fn []
(is (= @ran 3))
(is (found-in #"value:3:" div))
(reset! state {:foo {:bar {:foobar 3}}
:foo1 {}}))
(fn []
(is (= @ran 3))
(reset! @grand-state {:foobar 3}))
(fn []
(is (= @ran 3))
(reset! state {:foo {:bar {:foobar 3}}
:foo1 {}})
(r/flush)
(is (= @ran 3))
(reset! state {:foo {:bar {:foobar 2}}
:foo2 {}}))
(fn []
(is (found-in #"value:2:" div))
(is (= @ran 4))
(reset! @grand-state {:foobar 3})
(r/flush)
(is (= @ran 3))
(reset! @grand-state {:foobar 2}))
(fn []
(is (found-in #"value:2:" div))
(is (= @ran 5))
(reset! state {:foo {:bar {:foobar 2}}
:foo2 {}})
(r/flush)
(is (found-in #"value:2:" div))
(is (= @ran 4))
(reset! state {:foo {:bar {:foobar 4}}})
(reset! @grand-state {:foobar 4}))
(fn []
(is (found-in #"value:4:" div))
(is (= @ran 6))
(reset! @grand-state {:foobar 2})
(r/flush)
(is (found-in #"value:2:" div))
(is (= @ran 5))
(reset! state {:foo {:bar {:foobar 4}}})
(reset! @grand-state {:foobar 4})
(r/flush)
(is (found-in #"value:4:" div))
(is (= @ran 6))
(reset! @grand-state {:foobar 4})
(r/flush)
(is (found-in #"value:4:" div))
(is (= @ran 7)))))))
(reset! @grand-state {:foobar 4}))
(fn []
(is (found-in #"value:4:" div))
(is (= @ran 7)))
done)))))))
(deftest test-cursor
(let [state (r/atom {:a {:v 1}
:b {:v 2}})
a-count (r/atom 0)
b-count (r/atom 0)
derefer (fn derefer [cur count]
(swap! count inc)
[:div "" @cur])
comp (fn test-cursor []
[:div
[derefer (r/cursor state [:a]) a-count]
[derefer (r/cursor state [:b]) b-count]])]
(with-mounted-component [comp]
(fn [c div]
(is (= @a-count 1))
(is (= @b-count 1))
(let [state (r/atom {:a {:v 1}
:b {:v 2}})
a-count (r/atom 0)
b-count (r/atom 0)
derefer (fn derefer [cur count]
(swap! count inc)
[:div "" @cur])
comp (fn test-cursor []
[:div
[derefer (r/cursor state [:a]) a-count]
[derefer (r/cursor state [:b]) b-count]])]
(t/async done
(with-mounted-component-async [comp] done
(fn [c div done]
(run-fns-after-render
(fn []
(is (= @a-count 1))
(is (= @b-count 1))
(swap! state update-in [:a :v] inc)
(is (= @a-count 1))
(r/flush)
(is (= @a-count 2))
(is (= @b-count 1))
(reset! state {:a {:v 2} :b {:v 2}})
(r/flush)
(is (= @a-count 2))
(is (= @b-count 1))
(swap! state update-in [:a :v] inc)
(is (= @a-count 1)))
(fn []
(is (= @a-count 2))
(is (= @b-count 1))
(reset! state {:a {:v 3} :b {:v 2}})
(r/flush)
(is (= @a-count 3))
(is (= @b-count 1))))))
(reset! state {:a {:v 2} :b {:v 2}}))
(fn []
(is (= @a-count 2))
(is (= @b-count 1))
(reset! state {:a {:v 3} :b {:v 2}}))
(fn []
(is (= @a-count 3))
(is (= @b-count 1)))
done))))))
(deftest test-fn-cursor
(let [state (r/atom {:a {:v 1}
@ -233,7 +251,7 @@
(swap! state update-in [:a :v] inc)
(is (= @a-count 1))
(is (= @b-count 1))
(r/flush)
(is (= @a-count 2))
(is (= @b-count 2))

View File

@ -0,0 +1,35 @@
/* jshint strict: false */
/* globals configData */
/*
* Doo reads this file from classpath runners/karma.conf.js
* This sets up junit reporter.
*/
var path = require('path');
// Doo writes this file to /tmp, so can't use relative require directly
var logger = require(process.cwd() + '/node_modules/karma/lib/logger.js');
module.exports = function(config) {
var suite = path.basename(process.cwd());
// Hide two unncessary warnings
logger.create('web-server', 'error');
logger.create('watcher', 'error');
configData.plugins = ['karma-*'];
configData.logLevel = config.LOG_WARN;
configData.reporters = ['dots', 'junit'];
configData.junitReporter = {
outputDir: (process.env.CIRCLE_TEST_REPORTS || 'junit'),
outputFile: suite + '.xml',
suite: suite, // suite will become the package name attribute in xml testsuite element
useBrowserName: false // add browser name to report and classes names
};
config.set(configData);
};

View File

@ -1,23 +0,0 @@
var path = require('path');
var webpack = require('webpack');
var prod = process.env.NODE_ENV === "production";
module.exports = {
entry: './lib/modules.js',
output: {
path: "./target/webpack/",
filename: prod ? 'bundle.min.js' : 'bundle.js'
},
module: {
loaders: [
{ test: /.jsx?$/, loader: 'babel-loader', include: "./lib" }
]
},
plugins: [
new webpack.DefinePlugin(
{'process.env': { 'NODE_ENV': prod ? '"production"' : '"development"'}})
]
}