diff --git a/test/spec/ci_spec.rb b/test/spec/ci_spec.rb new file mode 100644 index 0000000..9053e15 --- /dev/null +++ b/test/spec/ci_spec.rb @@ -0,0 +1,183 @@ +# frozen_string_literal: true + +require_relative 'spec_helper' + +RSpec.describe 'Clojure buildpack' do + it 'runs tests on Heroku CI' do + new_default_hatchet_runner('lein-2.x-with-uberjar').tap do |app| + app.run_ci do |test_run| + # First CI run should build from scratch + expect(clean_output(test_run.output)).to eq(<<~OUTPUT) + -----> Clojure (Leiningen 2) app detected + -----> Installing Azul Zulu OpenJDK $VERSION + -----> Installing Clojure 1.10.0.411 CLI tools + Downloading and expanding tar + Installing libs into /app/.heroku/clj/lib/clojure + Installing clojure and clj into /app/.heroku/clj/bin + Installing man pages into /app/.heroku/clj/share/man/man1 + Removing download + Use clj -h for help. + -----> Installing Leiningen + Downloading: leiningen-2.9.1-standalone.jar + Writing: lein script + -----> Building with Leiningen + Running: lein deps + Downloading Leiningen to /app/.lein/self-installs/leiningen-2.9.1-standalone.jar now... + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + Retrieving $DEPENDENCY from $REPO + -----> No test-setup command provided. Skipping. + -----> Running Clojure (Leiningen 2) buildpack tests... + Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -XX:MaxRAM=2684354560 -XX:MaxRAMPercentage=80.0 + OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release. + Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -XX:MaxRAM=2684354560 -XX:MaxRAMPercentage=80.0 + Compiling com.heroku.ci.core + $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -XX:MaxRAM=2684354560 -XX:MaxRAMPercentage=80.0 + $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + + lein test com.heroku.ci.core-test + + Ran 2 tests containing 2 assertions. + 0 failures, 0 errors. + -----> Clojure (Leiningen 2) buildpack tests completed successfully + OUTPUT + + test_run.run_again + + # Second CI run should use cached artifacts + expect(clean_output(test_run.output)).to eq(<<~OUTPUT) + -----> Clojure (Leiningen 2) app detected + -----> Installing Azul Zulu OpenJDK $VERSION + -----> Installing Clojure 1.10.0.411 CLI tools + Downloading and expanding tar + Installing libs into /app/.heroku/clj/lib/clojure + Installing clojure and clj into /app/.heroku/clj/bin + Installing man pages into /app/.heroku/clj/share/man/man1 + Removing download + Use clj -h for help. + -----> Using cached Leiningen 2.9.1 + Writing: lein script + -----> Building with Leiningen + Running: lein deps + Downloading Leiningen to /app/.lein/self-installs/leiningen-2.9.1-standalone.jar now... + -----> No test-setup command provided. Skipping. + -----> Running Clojure (Leiningen 2) buildpack tests... + Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -XX:MaxRAM=2684354560 -XX:MaxRAMPercentage=80.0 + OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release. + Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -XX:MaxRAM=2684354560 -XX:MaxRAMPercentage=80.0 + Compiling com.heroku.ci.core + $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8 -XX:MaxRAM=2684354560 -XX:MaxRAMPercentage=80.0 + $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + + lein test com.heroku.ci.core-test + + Ran 2 tests containing 2 assertions. + 0 failures, 0 errors. + -----> Clojure (Leiningen 2) buildpack tests completed successfully + OUTPUT + end + end + end +end diff --git a/test/spec/cljs_spec.rb b/test/spec/cljs_spec.rb deleted file mode 100644 index b787e97..0000000 --- a/test/spec/cljs_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -require_relative 'spec_helper' - -describe 'ClojureScript' do - context "when using jdk-#{DEFAULT_OPENJDK_VERSION}" do - it 'deploys clojurescript-example successfully' do - new_default_hatchet_runner('clojurescript-example').tap do |app| - app.before_deploy do - java_version(DEFAULT_OPENJDK_VERSION) - end - - app.deploy do - expect(app.output).to match(/Installing (Heroku|Azul Zulu) OpenJDK #{DEFAULT_OPENJDK_VERSION}/) - expect(app.output).to match(/Downloading: leiningen-2.[5-9].[0-9]-standalone.jar/) - expect(app.output).to include('Running: lein uberjar') - - expect(http_get(app)).to include('Welcome from ClojureScript') - end - end - end - - it 'deploys cljs-lein-npm-example successfully' do - new_default_hatchet_runner('cljs-lein-npm-example').tap do |app| - app.before_deploy do - java_version(DEFAULT_OPENJDK_VERSION) - end - - app.deploy do - expect(app.output).to match(/Installing (Heroku|Azul Zulu) OpenJDK #{DEFAULT_OPENJDK_VERSION}/) - expect(app.output).to match(/Downloading: leiningen-2.[5-9].[0-9]-standalone.jar/) - expect(app.output).to include('Running: lein with-profile production do deps, compile :all') - - expect(http_get(app)).to include('Jokes') - end - end - end - end -end diff --git a/test/spec/compile_spec.rb b/test/spec/compile_spec.rb index 8142993..08d4024 100644 --- a/test/spec/compile_spec.rb +++ b/test/spec/compile_spec.rb @@ -2,33 +2,382 @@ require_relative 'spec_helper' -describe "Heroku's Clojure Support" do - it 'compiles a project without :min-lein-version with the default JDK version' do - new_default_hatchet_runner('test/spec/fixtures/repos/lein-1-jdk-8').tap do |app| +describe 'Clojure' do + it 'works with lein 2.x uberjar' do + new_default_hatchet_runner('lein-2.x-with-uberjar').tap do |app| app.deploy do - expect(app.output).to include('Installing Azul Zulu OpenJDK 1.8') - expect(app.output).to include('No :min-lein-version found in project.clj; using 1.7.1.') - expect(app.output).to include('To use Leiningen 2.x, add this to project.clj: :min-lein-version "2.0.0"') - expect(app.output).to include('Downloading: leiningen-1.7.1-standalone.jar') + expect(clean_output(app.output)).to eq(<<~OUTPUT) + remote: -----> Clojure (Leiningen 2) app detected + remote: -----> Installing Azul Zulu OpenJDK $VERSION + remote: -----> Installing Clojure 1.10.0.411 CLI tools + remote: Downloading and expanding tar + remote: Installing libs into $BUILD_DIR/.heroku/clj/lib/clojure + remote: Installing clojure and clj into $BUILD_DIR/.heroku/clj/bin + remote: Installing man pages into $BUILD_DIR/.heroku/clj/share/man/man1 + remote: Removing download + remote: Use clj -h for help. + remote: -----> Installing Leiningen + remote: Downloading: leiningen-2.9.1-standalone.jar + remote: Writing: lein script + remote: -----> Building with Leiningen + remote: Running: lein uberjar + remote: Downloading Leiningen to /app/.lein/self-installs/leiningen-2.9.1-standalone.jar now... + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Compiling com.heroku.ci.core + remote: $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + remote: Compiling com.heroku.ci.core + remote: Created $BUILD_DIR/target/heroku-minimal-clojure-0.1.0.jar + remote: Created $BUILD_DIR/target/app-standalone.jar + remote: -----> Discovering process types + remote: Procfile declares types -> (none) + remote: Default types for buildpack -> web + + remote: -----> Compressing... + remote: Done: 115.4M + OUTPUT + + app.commit! + app.push! + + # Second build should use cached artifacts and doesn't recompile previously compiled application files + expect(clean_output(app.output)).to eq(<<~OUTPUT) + remote: -----> Clojure (Leiningen 2) app detected + remote: -----> Installing Azul Zulu OpenJDK $VERSION + remote: -----> Installing Clojure 1.10.0.411 CLI tools + remote: Downloading and expanding tar + remote: Installing libs into $BUILD_DIR/.heroku/clj/lib/clojure + remote: Installing clojure and clj into $BUILD_DIR/.heroku/clj/bin + remote: Installing man pages into $BUILD_DIR/.heroku/clj/share/man/man1 + remote: Removing download + remote: Use clj -h for help. + remote: -----> Using cached Leiningen 2.9.1 + remote: Writing: lein script + remote: -----> Building with Leiningen + remote: Running: lein uberjar + remote: Downloading Leiningen to /app/.lein/self-installs/leiningen-2.9.1-standalone.jar now... + remote: Compiling com.heroku.ci.core + remote: $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + remote: Compiling com.heroku.ci.core + remote: Created $BUILD_DIR/target/heroku-minimal-clojure-0.1.0.jar + remote: Created $BUILD_DIR/target/app-standalone.jar + remote: -----> Discovering process types + remote: Procfile declares types -> (none) + remote: Default types for buildpack -> web + + remote: -----> Compressing... + remote: Done: 115.4M + OUTPUT + end + end + end + + it 'works with lein 2.x without uberjar' do + new_default_hatchet_runner('lein-2.x-no-uberjar').tap do |app| + app.deploy do + expect(clean_output(app.output)).to eq(<<~OUTPUT) + remote: -----> Clojure (Leiningen 2) app detected + remote: -----> Installing Azul Zulu OpenJDK $VERSION + remote: -----> Installing Clojure 1.10.0.411 CLI tools + remote: Downloading and expanding tar + remote: Installing libs into $BUILD_DIR/.heroku/clj/lib/clojure + remote: Installing clojure and clj into $BUILD_DIR/.heroku/clj/bin + remote: Installing man pages into $BUILD_DIR/.heroku/clj/share/man/man1 + remote: Removing download + remote: Use clj -h for help. + remote: -----> Installing Leiningen + remote: Downloading: leiningen-2.9.1-standalone.jar + remote: Writing: lein script + remote: -----> Building with Leiningen + remote: Running: lein with-profile production compile :all + remote: Downloading Leiningen to /app/.lein/self-installs/leiningen-2.9.1-standalone.jar now... + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Compiling com.heroku.ci.core + remote: $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + remote: -----> Discovering process types + remote: Procfile declares types -> (none) + remote: Default types for buildpack -> web + + remote: -----> Compressing... + remote: Done: 125.5M + OUTPUT + + app.commit! + app.push! + + # Second build should use cached artifacts and doesn't recompile previously compiled application files + expect(clean_output(app.output)).to eq(<<~OUTPUT) + remote: -----> Clojure (Leiningen 2) app detected + remote: -----> Installing Azul Zulu OpenJDK $VERSION + remote: -----> Installing Clojure 1.10.0.411 CLI tools + remote: Downloading and expanding tar + remote: Installing libs into $BUILD_DIR/.heroku/clj/lib/clojure + remote: Installing clojure and clj into $BUILD_DIR/.heroku/clj/bin + remote: Installing man pages into $BUILD_DIR/.heroku/clj/share/man/man1 + remote: Removing download + remote: Use clj -h for help. + remote: -----> Using cached Leiningen 2.9.1 + remote: Writing: lein script + remote: -----> Building with Leiningen + remote: Running: lein with-profile production compile :all + remote: Downloading Leiningen to /app/.lein/self-installs/leiningen-2.9.1-standalone.jar now... + remote: Compiling com.heroku.ci.core + remote: $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + remote: -----> Discovering process types + remote: Procfile declares types -> (none) + remote: Default types for buildpack -> web + + remote: -----> Compressing... + remote: Done: 125.5M + OUTPUT + end + end + end + + it 'uses custom bin/build script when present' do + new_default_hatchet_runner('lein-2.x-with-uberjar').tap do |app| + app.before_deploy do + Dir.mkdir('bin') unless Dir.exist?('bin') + File.write('bin/build', <<~SCRIPT) + #!/usr/bin/env bash + echo "Running custom build script" + lein deps + SCRIPT + File.chmod(0755, 'bin/build') + end + + app.deploy do + expect(clean_output(app.output)).to include('Found bin/build; running it instead of default lein invocation.') + expect(clean_output(app.output)).to include('Running: bin/build') + expect(clean_output(app.output)).to include('Running custom build script') end end end - it 'compiles a project with :min-lein-version set to 2.0.0 with the default JDK version' do - new_default_hatchet_runner('test/spec/fixtures/repos/lein-2-jdk-8').tap do |app| + it 'detects and uses vendored leiningen from bin/lein' do + buildpack_root = File.expand_path('../..', __dir__) + new_default_hatchet_runner('lein-2.x-with-uberjar').tap do |app| + app.before_deploy do + Dir.mkdir('bin') unless Dir.exist?('bin') + # Create a working lein script based on opt/lein2 + lein_template_path = File.join(buildpack_root, 'opt/lein2') + lein_content = File.read(lein_template_path) + # Replace the version placeholder with actual version + lein_content.gsub!('##LEIN_VERSION##', '2.9.1') + File.write('bin/lein', lein_content) + File.chmod(0755, 'bin/lein') + end + app.deploy do - expect(app.output).to include('Installing Azul Zulu OpenJDK 1.8') - expect(app.output).to include('Downloading: leiningen-2.9.1-standalone.jar') - expect(app.output).not_to include('WARNING: no :min-lein-version found in project.clj; using 1.7.1.') + expect(clean_output(app.output)).to include('Using vendored Leiningen at bin/lein') end end end - it 'runs `lein uberjar` when the project has a :uberjar-name setting' do - new_default_hatchet_runner('test/spec/fixtures/repos/lein-2-jdk-8-uberjar').tap do |app| + it 'fails the build when lein compilation fails' do + new_default_hatchet_runner('lein-2.x-with-uberjar', allow_failure: true).tap do |app| + app.before_deploy do + File.write('src/com/heroku/ci/core.clj', '(this will not compile') + end + app.deploy do - expect(app.output).to include('Installing Azul Zulu OpenJDK 1.8') - expect(app.output).to include('Running: lein uberjar') + expect(app).not_to be_deployed + expect(app.output).to include('Failed to build.') end end end diff --git a/test/spec/compojure_spec.rb b/test/spec/compojure_spec.rb deleted file mode 100644 index 512cac1..0000000 --- a/test/spec/compojure_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -require_relative 'spec_helper' - -describe 'Compojure' do - context "when using jdk-#{DEFAULT_OPENJDK_VERSION}" do - it 'deploys clojure-minimal successfully' do - new_default_hatchet_runner('clojure-minimal').tap do |app| - app.before_deploy do - java_version(DEFAULT_OPENJDK_VERSION) - end - - app.deploy do - expect(app.output).to match(/Installing (Heroku|Azul Zulu) OpenJDK #{DEFAULT_OPENJDK_VERSION}/) - expect(app.output).to match(/Downloading: leiningen-2.[0-9].[0-9]-standalone.jar/) - expect(app.output).to include('Running: lein uberjar') - expect(http_get(app)).to include('["Hello" :from Heroku]') - end - end - end - end -end diff --git a/test/spec/config_spec.rb b/test/spec/config_spec.rb new file mode 100644 index 0000000..e107435 --- /dev/null +++ b/test/spec/config_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require_relative 'spec_helper' + +RSpec.describe 'Clojure buildpack configuration' do + it 'respects LEIN_BUILD_TASK environment variable override' do + new_default_hatchet_runner('lein-2.x-with-uberjar').tap do |app| + app.before_deploy do + app.set_config('LEIN_BUILD_TASK' => 'deps') + end + + app.deploy do + expect(clean_output(app.output)).to include('Running: lein deps') + expect(clean_output(app.output)).not_to include('Running: lein uberjar') + end + end + end + + it 'respects CLOJURE_CLI_VERSION environment variable' do + new_default_hatchet_runner('lein-2.x-with-uberjar').tap do |app| + app.before_deploy do + app.set_config('CLOJURE_CLI_VERSION' => '1.11.1.1347') + end + + app.deploy do + expect(clean_output(app.output)).to include('Installing Clojure 1.11.1.1347 CLI tools') + end + end + end + + it 'respects BUILD_COMMAND environment variable override' do + new_default_hatchet_runner('lein-2.x-with-uberjar').tap do |app| + app.before_deploy do + app.set_config('BUILD_COMMAND' => 'echo "Custom build command executed" && lein deps') + end + + app.deploy do + expect(clean_output(app.output)).to include('Running: echo "Custom build command executed" && lein deps') + expect(clean_output(app.output)).to include('Custom build command executed') + expect(clean_output(app.output)).not_to include('Running: lein uberjar') + end + end + end +end diff --git a/test/spec/detection_spec.rb b/test/spec/detection_spec.rb new file mode 100644 index 0000000..19fcb30 --- /dev/null +++ b/test/spec/detection_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require_relative 'spec_helper' + +RSpec.describe 'Clojure buildpack detection' do + it 'shows error message when project.clj is missing' do + Hatchet::Runner.new('non-clojure-app', allow_failure: true).tap do |app| + app.deploy do + expect(app).not_to be_deployed + expect(clean_output(app.output)).to eq(<<~OUTPUT) + remote: -----> App not compatible with buildpack: $BUILDPACK_URL + remote: Could not find a 'project.clj' file! Please ensure it exists and is checked into Git. + + remote: More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure + + remote: ! Push failed + OUTPUT + end + end + end +end diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/.gitignore b/test/spec/fixtures/repos/cljs-lein-npm-example/.gitignore deleted file mode 100644 index d845904..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -/target -/classes -/checkouts -pom.xml -pom.xml.asc -*.jar -*.class -*~ -/.lein-* -/.nrepl-port -/resources/public/js/out -/logs -/node_modules -npm-debug.log -main.js -package.json -.idea diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/LICENSE b/test/spec/fixtures/repos/cljs-lein-npm-example/LICENSE deleted file mode 100644 index bf00aa6..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/LICENSE +++ /dev/null @@ -1,215 +0,0 @@ -THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC -LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM -CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - - -1. DEFINITIONS - -"Contribution" means: - -a) in the case of the initial Contributor, the initial code and -documentation distributed under this Agreement, and - -b) in the case of each subsequent Contributor: - -i) changes to the Program, and - -ii) additions to the Program; - -where such changes and/or additions to the Program originate from and are -distributed by that particular Contributor. A Contribution 'originates' from -a Contributor if it was added to the Program by such Contributor itself or -anyone acting on such Contributor's behalf. Contributions do not include -additions to the Program which: (i) are separate modules of software -distributed in conjunction with the Program under their own license -agreement, and (ii) are not derivative works of the Program. - -"Contributor" means any person or entity that distributes the Program. - -"Licensed Patents" mean patent claims licensable by a Contributor which are -necessarily infringed by the use or sale of its Contribution alone or when -combined with the Program. - -"Program" means the Contributions distributed in accordance with this -Agreement. - -"Recipient" means anyone who receives the Program under this Agreement, -including all Contributors. - -2. GRANT OF RIGHTS - -a) Subject to the terms of this Agreement, each Contributor hereby grants -Recipient a non-exclusive, worldwide, royalty-free copyright license to -reproduce, prepare derivative works of, publicly display, publicly perform, -distribute and sublicense the Contribution of such Contributor, if any, and -such derivative works, in source code and object code form. - -b) Subject to the terms of this Agreement, each Contributor hereby grants -Recipient a non-exclusive, worldwide, royalty-free patent license under -Licensed Patents to make, use, sell, offer to sell, import and otherwise -transfer the Contribution of such Contributor, if any, in source code and -object code form. This patent license shall apply to the combination of the -Contribution and the Program if, at the time the Contribution is added by the -Contributor, such addition of the Contribution causes such combination to be -covered by the Licensed Patents. The patent license shall not apply to any -other combinations which include the Contribution. No hardware per se is -licensed hereunder. - -c) Recipient understands that although each Contributor grants the licenses -to its Contributions set forth herein, no assurances are provided by any -Contributor that the Program does not infringe the patent or other -intellectual property rights of any other entity. Each Contributor disclaims -any liability to Recipient for claims brought by any other entity based on -infringement of intellectual property rights or otherwise. As a condition to -exercising the rights and licenses granted hereunder, each Recipient hereby -assumes sole responsibility to secure any other intellectual property rights -needed, if any. For example, if a third party patent license is required to -allow Recipient to distribute the Program, it is Recipient's responsibility -to acquire that license before distributing the Program. - -d) Each Contributor represents that to its knowledge it has sufficient -copyright rights in its Contribution, if any, to grant the copyright license -set forth in this Agreement. - -3. REQUIREMENTS - -A Contributor may choose to distribute the Program in object code form under -its own license agreement, provided that: - -a) it complies with the terms and conditions of this Agreement; and - -b) its license agreement: - -i) effectively disclaims on behalf of all Contributors all warranties and -conditions, express and implied, including warranties or conditions of title -and non-infringement, and implied warranties or conditions of merchantability -and fitness for a particular purpose; - -ii) effectively excludes on behalf of all Contributors all liability for -damages, including direct, indirect, special, incidental and consequential -damages, such as lost profits; - -iii) states that any provisions which differ from this Agreement are offered -by that Contributor alone and not by any other party; and - -iv) states that source code for the Program is available from such -Contributor, and informs licensees how to obtain it in a reasonable manner on -or through a medium customarily used for software exchange. - -When the Program is made available in source code form: - -a) it must be made available under this Agreement; and - -b) a copy of this Agreement must be included with each copy of the Program. - -Contributors may not remove or alter any copyright notices contained within -the Program. - -Each Contributor must identify itself as the originator of its Contribution, -if any, in a manner that reasonably allows subsequent Recipients to identify -the originator of the Contribution. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain responsibilities with -respect to end users, business partners and the like. While this license is -intended to facilitate the commercial use of the Program, the Contributor who -includes the Program in a commercial product offering should do so in a -manner which does not create potential liability for other Contributors. -Therefore, if a Contributor includes the Program in a commercial product -offering, such Contributor ("Commercial Contributor") hereby agrees to defend -and indemnify every other Contributor ("Indemnified Contributor") against any -losses, damages and costs (collectively "Losses") arising from claims, -lawsuits and other legal actions brought by a third party against the -Indemnified Contributor to the extent caused by the acts or omissions of such -Commercial Contributor in connection with its distribution of the Program in -a commercial product offering. The obligations in this section do not apply -to any claims or Losses relating to any actual or alleged intellectual -property infringement. In order to qualify, an Indemnified Contributor must: -a) promptly notify the Commercial Contributor in writing of such claim, and -b) allow the Commercial Contributor tocontrol, and cooperate with the -Commercial Contributor in, the defense and any related settlement -negotiations. The Indemnified Contributor may participate in any such claim -at its own expense. - -For example, a Contributor might include the Program in a commercial product -offering, Product X. That Contributor is then a Commercial Contributor. If -that Commercial Contributor then makes performance claims, or offers -warranties related to Product X, those performance claims and warranties are -such Commercial Contributor's responsibility alone. Under this section, the -Commercial Contributor would have to defend claims against the other -Contributors related to those performance claims and warranties, and if a -court requires any other Contributor to pay any damages as a result, the -Commercial Contributor must pay those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON -AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER -EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR -CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A -PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the -appropriateness of using and distributing the Program and assumes all risks -associated with its exercise of rights under this Agreement , including but -not limited to the risks and costs of program errors, compliance with -applicable laws, damage to or loss of data, programs or equipment, and -unavailability or interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY -CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION -LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE -EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of the -remainder of the terms of this Agreement, and without further action by the -parties hereto, such provision shall be reformed to the minimum extent -necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Program itself -(excluding combinations of the Program with other software or hardware) -infringes such Recipient's patent(s), then such Recipient's rights granted -under Section 2(b) shall terminate as of the date such litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it fails to -comply with any of the material terms or conditions of this Agreement and -does not cure such failure in a reasonable period of time after becoming -aware of such noncompliance. If all Recipient's rights under this Agreement -terminate, Recipient agrees to cease use and distribution of the Program as -soon as reasonably practicable. However, Recipient's obligations under this -Agreement and any licenses granted by Recipient relating to the Program shall -continue and survive. - -Everyone is permitted to copy and distribute copies of this Agreement, but in -order to avoid inconsistency the Agreement is copyrighted and may only be -modified in the following manner. The Agreement Steward reserves the right to -publish new versions (including revisions) of this Agreement from time to -time. No one other than the Agreement Steward has the right to modify this -Agreement. The Eclipse Foundation is the initial Agreement Steward. The -Eclipse Foundation may assign the responsibility to serve as the Agreement -Steward to a suitable separate entity. Each new version of the Agreement will -be given a distinguishing version number. The Program (including -Contributions) may always be distributed subject to the version of the -Agreement under which it was received. In addition, after a new version of -the Agreement is published, Contributor may elect to distribute the Program -(including its Contributions) under the new version. Except as expressly -stated in Sections 2(a) and 2(b) above, Recipient receives no rights or -licenses to the intellectual property of any Contributor under this -Agreement, whether expressly, by implication, estoppel or otherwise. All -rights in the Program not expressly granted under this Agreement are -reserved. - -This Agreement is governed by the laws of the State of Washington and the -intellectual property laws of the United States of America. No party to this -Agreement will bring a legal action under this Agreement more than one year -after the cause of action arose. Each party waives its rights to a jury trial -in any resulting litigation. diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/Procfile b/test/spec/fixtures/repos/cljs-lein-npm-example/Procfile deleted file mode 100644 index 8fbd1b9..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: node main.js diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/app.json b/test/spec/fixtures/repos/cljs-lein-npm-example/app.json deleted file mode 100644 index 305d635..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/app.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Clojure lein-npm Example", - "description": "Sample ClojureScript app that uses lein-npm on Heroku.", - "website": "https://devcenter.heroku.com/articles/using-node-js-with-clojure-and-clojurescript-applications", - "repository": "https://github.com/kissaten/cljs-lein-npm-example", -} diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/project.clj b/test/spec/fixtures/repos/cljs-lein-npm-example/project.clj deleted file mode 100644 index 35a8310..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/project.clj +++ /dev/null @@ -1,87 +0,0 @@ -(defproject cljsnode "0.1.1-SNAPSHOT" - :description "FIXME: write description" - :url "http://example.com/FIXME" - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"} - - :dependencies [[org.clojure/clojure "1.7.0"] - [org.clojure/clojurescript "1.7.48"] - [org.clojure/core.async "0.1.346.0-17112a-alpha"] - [reagent "0.5.1"] - [kioo "0.4.1"]] - - :npm {:dependencies [[express "4.13.3"] - [xmlhttprequest "*"] - [xmldom "0.1.19"] - [source-map-support "*"] - [react "0.13.3"]] - :root :root} - - :plugins [[lein-cljsbuild "1.1.0"] - [lein-npm "0.6.1"]] - - :min-lein-version "2.1.2" - - :hooks [leiningen.cljsbuild] - - :aliases {"start" ["npm" "start"]} - - :main "main.js" - - :source-paths ["src/cljs"] - - :clean-targets ^{:protect false} [[:cljsbuild :builds :server :compiler :output-to] - [:cljsbuild :builds :app :compiler :output-dir] - "node_modules" - :target-path :compile-path] - - :figwheel {:http-server-root "public" - :css-dirs ["resources/public/css"] - :server-logfile "logs/figwheel.log"} - - :cljsbuild {:builds - {:app - {:source-paths ["src/browser" "src/cljs"] - :compiler {:output-to "resources/public/js/out/app.js" - :output-dir "resources/public/js/out" - :asset-path "js/out" - :main app.start - :optimizations :none}} - - :server - {:source-paths ["src/node" "src/cljs"] - :compiler {:target :nodejs - :output-to "main.js" - :output-dir "target" - :main server.core - :optimizations :none} - }}} - - :profiles {:dev - {:plugins - [[lein-figwheel "0.3.9"]] - :cljsbuild - {:builds - {:app - {:compiler {:pretty-print true} - :source-map true - :figwheel true} - :server - {:compiler {:pretty-print true} - :source-map true - :figwheel {:heads-up-display false}}}} - :npm {:dependencies [[ws "*"]]}} - - :prod - {:env {:production true} - :cljsbuild - {:builds - {:server - {:compiler {:optimizations :simple - :foreign-libs [{:file "src/node/polyfill/simple.js" - :provides ["polyfill.simple"]}] - :pretty-print false}} - :app - {:compiler {:output-dir "target/app/out" - :optimizations :advanced - :pretty-print false}}}}}}) diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/resources/css b/test/spec/fixtures/repos/cljs-lein-npm-example/resources/css deleted file mode 120000 index 261ec12..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/resources/css +++ /dev/null @@ -1 +0,0 @@ -public/css \ No newline at end of file diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/resources/public/css/custom.css b/test/spec/fixtures/repos/cljs-lein-npm-example/resources/public/css/custom.css deleted file mode 100644 index fbb2961..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/resources/public/css/custom.css +++ /dev/null @@ -1,33 +0,0 @@ - -#forkme img { - position: absolute; - top: 0; - right: 0; - border: 0; - z-index: 100; - width: 15em; - opacity: 0.6; -} - -#jokes { - font-size: larger; - margin-top: 1em; -} - -#jokes .well { - font-weight: bold; - min-height: 20em; - margin-bottom: 1em; - position: relative; -} - -.joke { - margin: 0.5em; - position: absolute; - top: 50%; - transform: translate(0, -50%); -} - - - - diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/resources/template.html b/test/spec/fixtures/repos/cljs-lein-npm-example/resources/template.html deleted file mode 100644 index d690ed1..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/resources/template.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - Jokes - - - - - - - -
-
-
-
-
- Chuck Norris can unit test entire applications with a single assert. -
-
-
-
-
- -
- - Fork me on GitHub - -
- - - - - diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/src/browser/app/start.cljs b/test/spec/fixtures/repos/cljs-lein-npm-example/src/browser/app/start.cljs deleted file mode 100644 index 41cc047..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/src/browser/app/start.cljs +++ /dev/null @@ -1,7 +0,0 @@ -(ns app.start - (:require [app.core :as app])) - -(defn ^:export main [] - (app/activate)) - -(set! js/main-cljs-fn main) diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/src/cljs/app/core.cljs b/test/spec/fixtures/repos/cljs-lein-npm-example/src/cljs/app/core.cljs deleted file mode 100644 index 10b165f..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/src/cljs/app/core.cljs +++ /dev/null @@ -1,42 +0,0 @@ -(ns app.core - (:require-macros - [cljs.core.async.macros :refer [go go-loop]]) - (:require - [cljs.core.async :as async :refer [chan close! timeout put!]] - [goog.dom :as dom] - [goog.events :as events] - [reagent.core :as reagent :refer [atom]] - [app.jokes :refer [fresh-jokes]] - [app.views :refer [jokes-view jokes-page html5]])) - -(def scripts [{:src "/js/out/app.js"} - "main_cljs_fn()"]) - -(def jokes-chan - (memoize #(fresh-jokes 12 2))) - -(defn static-page [] - (let [out (chan 1)] - (go - (put! out - (-> ( e .-target .getResponseJson js->clj cb)))) diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/src/cljs/app/views.cljs b/test/spec/fixtures/repos/cljs-lein-npm-example/src/cljs/app/views.cljs deleted file mode 100644 index fe0f0fe..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/src/cljs/app/views.cljs +++ /dev/null @@ -1,49 +0,0 @@ -(ns app.views - (:require - [kioo.reagent :refer [html-content content append after set-attr do-> - substitute listen unwrap]] - [kioo.core :refer [handle-wrapper]] - [reagent.core :as reagent :refer [atom]] - [goog.string :as gstring]) - (:require-macros - [kioo.reagent :refer [defsnippet deftemplate snippet]])) - -;; Showcasing combining different ways to generate the markup for the page: -;; 1. Hiccup-style templating with elements as inline clojure vectors; -;; 2. Kioo (enlive style) injecting transformations into external template; -;; The template file is in the resources directory. - -(defn jokes-view-1 [jokes] - [:div.row - (for [joke jokes] - ^{:key (gstring/hashCode joke)} - [:div.joke-card.col-xs-12.col-sm-6.col-md-4.col-lg-3 - [:div.well - [:div.joke joke]]])]) - -(defsnippet joke-card "template.html" [:main :.joke-card] - [joke] - {[:.joke] (content joke) }) - -(defsnippet jokes-view-2 "template.html" [:main :.row] - [jokes] - {[:.joke-card] (substitute (map joke-card jokes)) }) - -;; Use either of the jokes-view-* templates from above: - -(def jokes-view jokes-view-2) - -;; Template for the html page: - -(defsnippet jokes-page "template.html" [:html] - [jokes & {:keys [scripts]}] - {[:main] (content [jokes-view jokes]) - [:body] (append [:div (for [src scripts] - ^{:key (gstring/hashCode (pr-str src))} - [:script src])]) }) - -(defn html5 [content] - (str "\n" content)) - -(defn test-views [] - (html5 (jokes-page ["Chuck Norris eats parentheses for breakfast"]))) diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/boot-node.js b/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/boot-node.js deleted file mode 100644 index 1b046f4..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/boot-node.js +++ /dev/null @@ -1,20 +0,0 @@ -// Ensures the polyfill is loaded before any modules that may fail without. -// Author: Terje Norderhaug -// Date: August 2015 -// -// Note: Will be compiled into target-dir not classpath subdirectory -// Hack emulating early parts of target-file in effect injecting a dependency - -// Not currently used... - -// :foreign-libs [{:file "src/node/server/boot.js" -// :provides ["server.boot"] ;; use to also inject dependencies -// :requires ["goog"]}] ;; not really required so remove? - -var path = require("path"); -require(path.join(path.resolve("."),"server/lib","goog","bootstrap","nodejs.js")); -// require("./server/lib/goog/bootstrap/nodejs.js"); -goog.addDependency("../domina/support.js", ["domina.support"], ["server.compat"]); -goog.provide("server.boot"); -require(path.join(path.resolve("."),"server", "main.js")); -// require("./server/main.js"); diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/boot.cljs b/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/boot.cljs deleted file mode 100644 index 5912519..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/boot.cljs +++ /dev/null @@ -1,26 +0,0 @@ -;; Entry point for node apps that needs the polyfill to be loaded -;; before modules are loaded. Require from elsewhere to ensure -;; boot.js is included in the build. -;; -;; Can be avoided by careful dependence management to ensure that polyfill is -;; loaded before modules that needs it. See the generated cljs_deps.js -;; Polyfill should ideally be at the beginning of the dependency list of main: -;; goog.addDependency("../server/core.js", ['server.core'], ['polyfill... -;; * Place polyfill early on the require list. -;; * Require this module [polyfill.boot] to ensure it is built and included. -;; * May only work when :optimization is :none due to the paths. - -(when false ;; doesn't seem to be needed anymore - (js/require "../goog/bootstrap/nodejs.js") ; dependency support - -;; (These could possibly be resolved by adding a dependency to a core cljs module) - (.addDependency js/goog "../domina/support.js" #js ["domina.support"] #js ["polyfill.compat"]) - (.addDependency js/goog "../hickory/core.js" #js ["hickory.core"] #js ["polyfill.compat"]) - -;; require(path.join(path.resolve("."),"..","main.js")); -;; (.require (.join js/path (.resolve js/path ".") ".." "main.js")) - (js/require "../main.js") -) - -;; ns is deliberately last to avoid requiring cljs.core: -(ns polyfill.boot) diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/compat.cljs b/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/compat.cljs deleted file mode 100644 index ac78df7..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/compat.cljs +++ /dev/null @@ -1,347 +0,0 @@ -(ns polyfill.compat - (:require - [cljs.nodejs :as nodejs] - [polyfill.simple])) - -" -Load before any module that depends on basic browser context. -You may have to use (.require js/goog) before the ns delcaration as -the cljs compiler results in arbitrary order of required modules. -goog.require is supposed to be synchronous when used under node, -(https://github.com/google/closure-library/wiki/Using-Closure-Library-with-node.js) -but that doesn't seem to be the case, which may require additional concerns. -" - -(enable-console-print!) - -;; http://stackoverflow.com/questions/8554745/implementing-an-ajax-call-in-clojurescript -;; http://stackoverflow.com/questions/21839156/node-js-javascript-html-xmlhttprequest-cannot-load - -;; Required for goog.net.XhrIo on node: - -(def xhr (nodejs/require "xmlhttprequest")) -(when xhr - (set! js/XMLHttpRequest (.-XMLHttpRequest xhr))) - -;; Reagent uses js/React: - -(def react (nodejs/require "react")) -(when react - (aset js/global "React" react)) ; work-arounds "constant React assigned a value more than once." - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; DOM - -;; https://github.com/google/closure-library/wiki/Using-Closure-Library-with-node.js -;; "any libraries in Closure Library that use the DOM will not work on NodeJS" -;; https://www.npmjs.com/package/jsdom -;; Taking that as a challenge! - -;; [xmldom "0.1.19"] seems to do the job (mostly): -;; https://www.npmjs.com/package/xmldom - -(def xmldom (nodejs/require "xmldom")) -(def dom-parser (.-DOMParser xmldom)) -(def dom-serializer (.-XMLSerializer xmldom)) -(def xmldom-implementation (.-DOMImplementation xmldom)) - -(def dom (nodejs/require "xmldom/dom")) -(def DOMImplementation (.-DOMImplementation dom)) - -(def sax (nodejs/require "xmldom/sax")) - -(def xhtml - " - - - - untitled - - - - - ") - -; (def doc (.parseFromString (new dom-parser) xhtml "application/xml")) - -(defn default-html-markup [& [title]] - (str "" ; per spec, don't change markup - (if title (str "" title "")) - "")) - -(defn html-from-string [& [html]] - (let [parser (new dom-parser) - markup (or html (default-html-markup)) - frag (.parseFromString parser markup "text/html")] - frag)) - -(def doc (html-from-string (default-html-markup "untitled"))) - -(when-not (aget js/global "document") - ; (set! js/document doc) - (aset js/global "document" doc)) ; avoid compiler reset constant error - -(when-not (try goog.global.document (catch js/Error e false)) - (set! goog.global.document doc)) - -(def dom-implementation (.-implementation doc)) - -;; Can't yet set window before loading react.js as it uses it to test for canUseDom -;; wait until DOM implementaiton is more complete? -;; (set! js/window js/global) - -;; Still element.innerHTML need to be supported: -;; see https://github.com/jindw/xmldom/blob/f053be7ceb9b1ddcff93c4b36c92dadb4d589986/dom.js -;; Challenge like getting past this in Domina: -;; https://github.com/levand/domina/blob/master/src/cljs/domina/support.cljs -;; in particular Element.prototype in xmldom/dom -;; Maybe create an observer on the setter? -;; http://stackoverflow.com/questions/20388229/is-using-javascript-setters-and-getter-properties-to-watch-for-changes-a-bad-ide#20388491 - -; (set! js/Element.prototype. ) - -(defn observe-object [obj observer] - (.observe js/Object obj observer)) - -(defn observer [changes] - (println "CHANGES:" (pr-str changes))) - -;; turns out this is overkill: -;; (observe-object div observer) -;; -;; Instead use __defineGetter__ and __defineSetter__ on the element: -;; or Object.defineProperty ?? - -(defn as-getter [f] - (fn [](this-as this (f this)))) - -(defn defget [obj prop f] - (:pre [(string? prop)]) - (.__defineGetter__ obj prop (as-getter f))) - -(defn as-setter [f] - (fn [val](this-as this (f this val)))) - -(defn defset [obj prop f] - (:pre [(string? prop)]) - (.__defineSetter__ obj prop (as-setter f))) - -(def frag (.parseFromString (new dom-parser) "

abc

def
" "text/html")) - -(defn clear-children! [node] - (while (.hasChildNodes node) - (.removeChild node (.-firstChild node))) - node) - -(defn append-nodes! [node nodes] - {:pre [(not (nil? nodes))]} - (let [n (aget nodes "length")] - (doseq [i (range n)] - (.appendChild node - (if-let [doc (.-ownerDocument node)] - (.importNode doc (.item nodes i) true) - (.cloneNode (.item nodes i) true)))) - node)) - -(defn node-content-string [node] - (let [children (.-childNodes node) - n (aget children "length") - serializer (new dom-serializer)] - (->> - (map #(.serializeToString serializer (.item children %)) (range n)) - (apply str)))) - -(def div (.createElement js/document "div")) - -(defn prototype-of [instance] ; works - (.getPrototypeOf js/Object instance)) - -(defn type-prototype [type] ;; ## rename to type-prototype - (.-prototype type)) - -(defn object-keys [obj] - (.keys js/Object obj)) - -(defn defproperty [prototype prop-name {:as descriptor}] - "deftype on a native level" - (.defineProperty js/Object prototype prop-name (clj->js descriptor))) - -(defn append-html [node html] - (let [frag (html-from-string html) - nodes (.-childNodes frag)] - (append-nodes! node nodes))) - -(defn set-inner-html [node html] - {:pre [(not (nil? node)) (string? html)]} - (clear-children! node) - (append-html node html) - node) - -(defn get-inner-html [node] - ; {:pre [(not (nil? node))]} - (if-not (nil? node) - (node-content-string node))) - -;;;;;;;;;;;;;;; -;; PROTOTYPES - -(def dom-implementation-prototype - (type-prototype (.-DOMImplementation dom))) - -(def element-prototype (prototype-of div)) ; fails on print, but still OK - -; Non-standard and deprecated way of defining property: -; (defget element-prototype "innerHTML" get-inner-html) -; (defset element-prototype "innerHTML" set-inner-html) -;; Standard way: -(defproperty element-prototype "innerHTML" - {:get (as-getter get-inner-html) - :set (as-setter set-inner-html)}) - -;; redo in case node prototypes areB cached: - -(def doc2 (.parseFromString (new dom-parser) xhtml "application/xml")) - -(def node (.createElement js/document "main")) - -;; (get-inner-html node) -;; (set-inner-html node "

hello

"); - -;;(def frag2 (html-from-string "

hello

")) -;;(def nodes2 (.-childNodes frag2)) -;;;; (append-nodes! node nodes) -;;(def doc2 (.-ownerDocument frag2)) -;;(def old (.item nodes2 1)) -;;(def fresh (.importNode doc2 old true)) -;;(.appendChild node fresh) - -(defn proto [obj] ;; likely same as getPrototypeOf - (.-__proto__ obj)) - -(defn prototype-instantiate [p] - (let [inst (fn [])] - (set! (.-prototype inst) p) - (set! (.-__proto__ inst) p) - inst)) - -(defn override-prototype [obj prototype & [type]] - (set! (.-prototype obj) - (merge - (if type (type-prototype type) #{}) - prototype)) - (set! (.-__proto__ obj) - (merge - (if type (proto type) #{}) - prototype)) - obj) - -(defn clone-merge ; rename to mutate-prototype or merge-prototype - ;; ... use clone-merge for one with only create? - "The object merged with the js prototype" - [type prototype] - ;; Object.assign is possibly the better choice but not yet in Node - ;; ## need to validate that this actually mutate shared prototype - ;; ## which may not be the case vs override-prototype - ;; ## need to copy the merge into the original object? - (let [combo (.create js/Object prototype (type-prototype type))] - (override-prototype type (type-prototype combo)))) - -(defn prototype-constructor [p] - (.-constructor p)) - -;; js/Node (used in Hickory) -;; Node.prototype in dom.js of xmldom: - -(def document-prototype - (prototype-of doc)) - -(def node-prototype ; apparently correct so dont change - (-> document-prototype proto)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(deftype Node [] Object) -(override-prototype Node node-prototype (aget js/global "Node")) -(set! js/Node Node) -;(set! js/Node -; (clone-merge (or (aget js/global "Node") Node) -; node-prototype)) - -; for testing - from hickory -(defn extend-type-with-seqable - [t] - (extend-type t - ISeqable - (-seq [array] (array-seq array)))) - -;; (def doc2 (.parseFromString (new dom-parser) xhtml "application/xml")) -;; (extend-type-with-seqable Node) -;; (map identity (Node.)) -;; Now even an existing document should be seqable: -;; (map identity doc2) -;; Yes! Works... - -;; js/NodeList (used in hickory.core) - -(def nodelist-prototype (prototype-of (.-childNodes doc))) - -(deftype NodeList [] Object) -(override-prototype NodeList nodelist-prototype (aget js/global "NodeList")) -(set! js/NodeList NodeList) -;;(set! js/NodeList -;; (clone-merge (if (= js/undefined (aget js/global "NodeList")) -;; NodeList -;; (aget js/global "NodeList")) -;; nodelist-prototype)) - -(extend-type-with-seqable js/NodeList) ; test - -; (set! (.-innerHTML node) "

hello

") - -;; .createHTMLDocument -;; createhtmldocument used in hickory -;; http://www.w3.org/TR/domcore/#dom-domimplementation-createhtmldocument - -(def Document (prototype-constructor document-prototype)) - -(defn create-document [] - (Document.)) - -(defn create-html-document [implementation & [title]] - ;; Per specification - (let [html (default-html-markup title) - doctype (.createDocumentType implementation "html") - doc (.createDocument implementation "" nil)] - (.appendChild doc (.importNode doc doctype)) - (append-html doc html) - (aset doc "hasFeature" (fn [] true)) ; specify instead? - doc)) - -;; consider specify instead -;; (specify (type dom-implementation) -;; createHTMLDocument -(aset (proto dom-implementation) "createHTMLDocument" - #(this-as this (create-html-document this %1))) - -;;; TEST: - -(def test-html "
-a") - -;; (set! (.-innerHTML node) test-html) - - -;; (set! (.-innerHTML div) test-html) - -;;(assert (.-firstChild div)) -;;(assert (.getElementsByTagName div "tbody")) - -;; Still can be a problem that dependenices aren't required in order, -;; as js/document need to be defined before certain modules. - -;; may have to run goog.nodeGlobalRequire per the goog bootstrap.js - -; Soon we should be able to use jsdom instead for more comprehensive browser dom emulation: -; (def jsdom (nodejs/require "jsdom")) -; (set! js/document (jsdom/jsdom "

" #js {})) diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/simple.js b/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/simple.js deleted file mode 100644 index 88b5d6e..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/polyfill/simple.js +++ /dev/null @@ -1,42 +0,0 @@ -// goog.provide("polyfill.simple"); - -// When using :simple optimization some polyfill needs to be loaded -// before modules that would fail without. -// -// Force early injection into executable -// by loading this as :foreign-libs in the project file, e.g.: -// -// :optimizations :simple -// :foreign-libs [{:file "src/node/polyfill/simple.js" -// :provides ["polyfill.simple"]}] -// -// Don't use :libs as it unfortunately injects late in :simple executables. -// Same holds for using :require from clojurescript. - -if (typeof React == 'undefined') { - // React = require("react"); // maybe compat can set js/React instead? - global["React"] = require("react"); // avoid compiler err redefine constant -} - -// Stand-ins redefined elsewhere... for hickory.core.cljs -function Node() {}; -Node.ELEMENT_NODE = 1; -Node.ATTRIBUTE_NODE = 2; -Node.TEXT_NODE = 3; -Node.CDATA_SECTION_NODE = 4; -Node.ENTITY_REFERENCE_NODE = 5; -Node.ENTITY_NODE = 6; -Node.PROCESSING_INSTRUCTION_NODE = 7; -Node.COMMENT_NODE = 8; -Node.DOCUMENT_NODE = 9; -Node.DOCUMENT_TYPE_NODE = 10; -Node.DOCUMENT_FRAGMENT_NODE = 11; -Node.NOTATION_NODE = 12; - -function NodeList() {}; -NodeList.prototype = { - length:0, - item: function (index) { - return this[index] || null; - } -} diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/server/core.cljs b/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/server/core.cljs deleted file mode 100644 index d32f461..0000000 --- a/test/spec/fixtures/repos/cljs-lein-npm-example/src/node/server/core.cljs +++ /dev/null @@ -1,31 +0,0 @@ -(ns server.core - (:require-macros - [cljs.core.async.macros :as m :refer [go go-loop alt!]]) - (:require - [polyfill.compat] - [cljs.nodejs :as nodejs] - [cljs.core.async :as async :refer [chan close! timeout put!]] - [reagent.core :as reagent :refer [atom]] - [app.core :refer [static-page]])) - -(enable-console-print!) - -(def express (nodejs/require "express")) - -(defn handler [req res] - (go - (.set res "Content-Type" "text/html") - (.send res (Hello from ClojureScript and Express

")))) - -(defn server [port success] - (doto (express) - (.get "/" handler) - (.listen port success))) - -(defn -main [& mess] - (let [port (or (.-PORT (.-env js/process)) 1337)] - (server port - #(println (str "Server running at http://127.0.0.1:" port "/"))))) - -(set! *main-cli-fn* -main) diff --git a/test/spec/fixtures/repos/cljs-nodejs-example/system.properties b/test/spec/fixtures/repos/cljs-nodejs-example/system.properties deleted file mode 100644 index 221ae01..0000000 --- a/test/spec/fixtures/repos/cljs-nodejs-example/system.properties +++ /dev/null @@ -1 +0,0 @@ -java.runtime.version=8 diff --git a/test/spec/fixtures/repos/cljs-nodejs-example/test/myexample/core_test.cljs b/test/spec/fixtures/repos/cljs-nodejs-example/test/myexample/core_test.cljs deleted file mode 100644 index 4e67ad6..0000000 --- a/test/spec/fixtures/repos/cljs-nodejs-example/test/myexample/core_test.cljs +++ /dev/null @@ -1,7 +0,0 @@ -(ns myexample.core-test - (:require [clojure.test :refer :all] - [myexample.core :refer :all])) - -(deftest a-test - (testing "FIXME, I fail." - (is (= 0 1)))) diff --git a/test/spec/fixtures/repos/clojure-minimal/.gitignore b/test/spec/fixtures/repos/clojure-minimal/.gitignore deleted file mode 100644 index c56d379..0000000 --- a/test/spec/fixtures/repos/clojure-minimal/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -pom.xml -*jar -/classes/ -/.lein-deps-sum -/.lein-failures -/.lein-env -/checkouts -/.env -/target -/.lein-repl-history -/.nrepl-port diff --git a/test/spec/fixtures/repos/clojure-minimal/Procfile b/test/spec/fixtures/repos/clojure-minimal/Procfile deleted file mode 100644 index 8d0a242..0000000 --- a/test/spec/fixtures/repos/clojure-minimal/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: java $JVM_OPTS -cp target/clojure-getting-started-standalone.jar clojure.main -m clojure-getting-started.web diff --git a/test/spec/fixtures/repos/clojure-minimal/project.clj b/test/spec/fixtures/repos/clojure-minimal/project.clj deleted file mode 100644 index 15ef786..0000000 --- a/test/spec/fixtures/repos/clojure-minimal/project.clj +++ /dev/null @@ -1,14 +0,0 @@ -(defproject clojure-getting-started "1.0.0-SNAPSHOT" - :description "Demo Clojure web app" - :url "http://clojure-getting-started.herokuapp.com" - :license {:name "Eclipse Public License v1.0" - :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.10.1"] - [compojure "1.6.2"] - [ring/ring-jetty-adapter "1.8.2"] - [environ "1.2.0"]] - :min-lein-version "2.0.0" - :plugins [[environ/environ.lein "0.2.1"]] - :hooks [environ.leiningen.hooks] - :uberjar-name "clojure-getting-started-standalone.jar" - :profiles {:production {:env {:production true}}}) diff --git a/test/spec/fixtures/repos/clojure-minimal/resources/404.html b/test/spec/fixtures/repos/clojure-minimal/resources/404.html deleted file mode 100644 index 01b164c..0000000 --- a/test/spec/fixtures/repos/clojure-minimal/resources/404.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Page Not Found - - - - -

Page Not Found

-

There's no page at the address you requested. If you entered it - by hand, check for typos. If you followed a link or a bookmark, - it may need to be updated.

- - diff --git a/test/spec/fixtures/repos/clojure-minimal/resources/500.html b/test/spec/fixtures/repos/clojure-minimal/resources/500.html deleted file mode 100644 index cb6474f..0000000 --- a/test/spec/fixtures/repos/clojure-minimal/resources/500.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Error - - - - -

Error

-

Something went wrong. Try again, and if the problem persists - please contact support.

- - diff --git a/test/spec/fixtures/repos/clojure-minimal/src/clojure_getting_started/web.clj b/test/spec/fixtures/repos/clojure-minimal/src/clojure_getting_started/web.clj deleted file mode 100644 index 1f53c5d..0000000 --- a/test/spec/fixtures/repos/clojure-minimal/src/clojure_getting_started/web.clj +++ /dev/null @@ -1,30 +0,0 @@ -(ns clojure-getting-started.web - (:require [compojure.core :refer [defroutes GET PUT POST DELETE ANY]] - [compojure.handler :refer [site]] - [compojure.route :as route] - [clojure.java.io :as io] - [ring.adapter.jetty :as jetty] - [environ.core :refer [env]])) - -(defn splash [] - {:status 200 - :headers {"Content-Type" "text/plain"} - :body (pr-str ["Hello" :from 'Heroku])}) - -(defn request-id-filter [request]) - -(defroutes app - (ANY "*" {:keys [headers params body] :as request} - (println (format "request_id=%s" (get headers "x-request-id")))) - (GET "/" [] - (splash)) - (ANY "*" [] - (route/not-found (slurp (io/resource "404.html"))))) - -(defn -main [& [port]] - (let [port (Integer. (or port (env :port) 5000))] - (jetty/run-jetty (site #'app) {:port port :join? false}))) - -;; For interactive development: -;; (.stop server) -;; (def server (-main)) diff --git a/test/spec/fixtures/repos/clojure-minimal/system.properties b/test/spec/fixtures/repos/clojure-minimal/system.properties deleted file mode 100644 index 221ae01..0000000 --- a/test/spec/fixtures/repos/clojure-minimal/system.properties +++ /dev/null @@ -1 +0,0 @@ -java.runtime.version=8 diff --git a/test/spec/fixtures/repos/clojure-minimal/test/clojure_getting_started/web_test.clj b/test/spec/fixtures/repos/clojure-minimal/test/clojure_getting_started/web_test.clj deleted file mode 100644 index ac12c8d..0000000 --- a/test/spec/fixtures/repos/clojure-minimal/test/clojure_getting_started/web_test.clj +++ /dev/null @@ -1,6 +0,0 @@ -(ns clojure-getting-started.web-test - (:require [clojure.test :refer :all] - [clojure-getting-started.web :refer :all])) - -(deftest first-test - (is false "Tests should be written")) diff --git a/test/spec/fixtures/repos/clojurescript-example/.gitignore b/test/spec/fixtures/repos/clojurescript-example/.gitignore deleted file mode 100644 index 7a153d3..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -/target -/classes -/checkouts -pom.xml -pom.xml.asc -*.jar -*.class -/.lein-* -/.nrepl-port -/resources/public/js -/out -/.repl diff --git a/test/spec/fixtures/repos/clojurescript-example/LICENSE b/test/spec/fixtures/repos/clojurescript-example/LICENSE deleted file mode 100644 index 7689f30..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/LICENSE +++ /dev/null @@ -1,214 +0,0 @@ -THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC -LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM -CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. - -1. DEFINITIONS - -"Contribution" means: - -a) in the case of the initial Contributor, the initial code and -documentation distributed under this Agreement, and - -b) in the case of each subsequent Contributor: - -i) changes to the Program, and - -ii) additions to the Program; - -where such changes and/or additions to the Program originate from and are -distributed by that particular Contributor. A Contribution 'originates' from -a Contributor if it was added to the Program by such Contributor itself or -anyone acting on such Contributor's behalf. Contributions do not include -additions to the Program which: (i) are separate modules of software -distributed in conjunction with the Program under their own license -agreement, and (ii) are not derivative works of the Program. - -"Contributor" means any person or entity that distributes the Program. - -"Licensed Patents" mean patent claims licensable by a Contributor which are -necessarily infringed by the use or sale of its Contribution alone or when -combined with the Program. - -"Program" means the Contributions distributed in accordance with this -Agreement. - -"Recipient" means anyone who receives the Program under this Agreement, -including all Contributors. - -2. GRANT OF RIGHTS - -a) Subject to the terms of this Agreement, each Contributor hereby grants -Recipient a non-exclusive, worldwide, royalty-free copyright license to -reproduce, prepare derivative works of, publicly display, publicly perform, -distribute and sublicense the Contribution of such Contributor, if any, and -such derivative works, in source code and object code form. - -b) Subject to the terms of this Agreement, each Contributor hereby grants -Recipient a non-exclusive, worldwide, royalty-free patent license under -Licensed Patents to make, use, sell, offer to sell, import and otherwise -transfer the Contribution of such Contributor, if any, in source code and -object code form. This patent license shall apply to the combination of the -Contribution and the Program if, at the time the Contribution is added by the -Contributor, such addition of the Contribution causes such combination to be -covered by the Licensed Patents. The patent license shall not apply to any -other combinations which include the Contribution. No hardware per se is -licensed hereunder. - -c) Recipient understands that although each Contributor grants the licenses -to its Contributions set forth herein, no assurances are provided by any -Contributor that the Program does not infringe the patent or other -intellectual property rights of any other entity. Each Contributor disclaims -any liability to Recipient for claims brought by any other entity based on -infringement of intellectual property rights or otherwise. As a condition to -exercising the rights and licenses granted hereunder, each Recipient hereby -assumes sole responsibility to secure any other intellectual property rights -needed, if any. For example, if a third party patent license is required to -allow Recipient to distribute the Program, it is Recipient's responsibility -to acquire that license before distributing the Program. - -d) Each Contributor represents that to its knowledge it has sufficient -copyright rights in its Contribution, if any, to grant the copyright license -set forth in this Agreement. - -3. REQUIREMENTS - -A Contributor may choose to distribute the Program in object code form under -its own license agreement, provided that: - -a) it complies with the terms and conditions of this Agreement; and - -b) its license agreement: - -i) effectively disclaims on behalf of all Contributors all warranties and -conditions, express and implied, including warranties or conditions of title -and non-infringement, and implied warranties or conditions of merchantability -and fitness for a particular purpose; - -ii) effectively excludes on behalf of all Contributors all liability for -damages, including direct, indirect, special, incidental and consequential -damages, such as lost profits; - -iii) states that any provisions which differ from this Agreement are offered -by that Contributor alone and not by any other party; and - -iv) states that source code for the Program is available from such -Contributor, and informs licensees how to obtain it in a reasonable manner on -or through a medium customarily used for software exchange. - -When the Program is made available in source code form: - -a) it must be made available under this Agreement; and - -b) a copy of this Agreement must be included with each copy of the Program. - -Contributors may not remove or alter any copyright notices contained within -the Program. - -Each Contributor must identify itself as the originator of its Contribution, -if any, in a manner that reasonably allows subsequent Recipients to identify -the originator of the Contribution. - -4. COMMERCIAL DISTRIBUTION - -Commercial distributors of software may accept certain responsibilities with -respect to end users, business partners and the like. While this license is -intended to facilitate the commercial use of the Program, the Contributor who -includes the Program in a commercial product offering should do so in a -manner which does not create potential liability for other Contributors. -Therefore, if a Contributor includes the Program in a commercial product -offering, such Contributor ("Commercial Contributor") hereby agrees to defend -and indemnify every other Contributor ("Indemnified Contributor") against any -losses, damages and costs (collectively "Losses") arising from claims, -lawsuits and other legal actions brought by a third party against the -Indemnified Contributor to the extent caused by the acts or omissions of such -Commercial Contributor in connection with its distribution of the Program in -a commercial product offering. The obligations in this section do not apply -to any claims or Losses relating to any actual or alleged intellectual -property infringement. In order to qualify, an Indemnified Contributor must: -a) promptly notify the Commercial Contributor in writing of such claim, and -b) allow the Commercial Contributor tocontrol, and cooperate with the -Commercial Contributor in, the defense and any related settlement -negotiations. The Indemnified Contributor may participate in any such claim -at its own expense. - -For example, a Contributor might include the Program in a commercial product -offering, Product X. That Contributor is then a Commercial Contributor. If -that Commercial Contributor then makes performance claims, or offers -warranties related to Product X, those performance claims and warranties are -such Commercial Contributor's responsibility alone. Under this section, the -Commercial Contributor would have to defend claims against the other -Contributors related to those performance claims and warranties, and if a -court requires any other Contributor to pay any damages as a result, the -Commercial Contributor must pay those damages. - -5. NO WARRANTY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON -AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER -EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR -CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A -PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the -appropriateness of using and distributing the Program and assumes all risks -associated with its exercise of rights under this Agreement , including but -not limited to the risks and costs of program errors, compliance with -applicable laws, damage to or loss of data, programs or equipment, and -unavailability or interruption of operations. - -6. DISCLAIMER OF LIABILITY - -EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY -CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION -LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE -EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGES. - -7. GENERAL - -If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of the -remainder of the terms of this Agreement, and without further action by the -parties hereto, such provision shall be reformed to the minimum extent -necessary to make such provision valid and enforceable. - -If Recipient institutes patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Program itself -(excluding combinations of the Program with other software or hardware) -infringes such Recipient's patent(s), then such Recipient's rights granted -under Section 2(b) shall terminate as of the date such litigation is filed. - -All Recipient's rights under this Agreement shall terminate if it fails to -comply with any of the material terms or conditions of this Agreement and -does not cure such failure in a reasonable period of time after becoming -aware of such noncompliance. If all Recipient's rights under this Agreement -terminate, Recipient agrees to cease use and distribution of the Program as -soon as reasonably practicable. However, Recipient's obligations under this -Agreement and any licenses granted by Recipient relating to the Program shall -continue and survive. - -Everyone is permitted to copy and distribute copies of this Agreement, but in -order to avoid inconsistency the Agreement is copyrighted and may only be -modified in the following manner. The Agreement Steward reserves the right to -publish new versions (including revisions) of this Agreement from time to -time. No one other than the Agreement Steward has the right to modify this -Agreement. The Eclipse Foundation is the initial Agreement Steward. The -Eclipse Foundation may assign the responsibility to serve as the Agreement -Steward to a suitable separate entity. Each new version of the Agreement will -be given a distinguishing version number. The Program (including -Contributions) may always be distributed subject to the version of the -Agreement under which it was received. In addition, after a new version of -the Agreement is published, Contributor may elect to distribute the Program -(including its Contributions) under the new version. Except as expressly -stated in Sections 2(a) and 2(b) above, Recipient receives no rights or -licenses to the intellectual property of any Contributor under this -Agreement, whether expressly, by implication, estoppel or otherwise. All -rights in the Program not expressly granted under this Agreement are -reserved. - -This Agreement is governed by the laws of the State of New York and the -intellectual property laws of the United States of America. No party to this -Agreement will bring a legal action under this Agreement more than one year -after the cause of action arose. Each party waives its rights to a jury trial -in any resulting litigation. diff --git a/test/spec/fixtures/repos/clojurescript-example/Procfile b/test/spec/fixtures/repos/clojurescript-example/Procfile deleted file mode 100644 index 7741d2a..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: java $JVM_OPTS -cp target/my-app.jar clojure.main -m my-app.server diff --git a/test/spec/fixtures/repos/clojurescript-example/code_of_conduct.md b/test/spec/fixtures/repos/clojurescript-example/code_of_conduct.md deleted file mode 100644 index 8108287..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/code_of_conduct.md +++ /dev/null @@ -1,32 +0,0 @@ -# Contributor Code of Conduct - -As contributors and maintainers of this project, we pledge to respect -all people who contribute through reporting issues, posting feature -requests, updating documentation, submitting pull requests or patches, -and other activities. - -We are committed to making participation in this project a -harassment-free experience for everyone, regardless of level of -experience, gender, gender identity and expression, sexual -orientation, disability, personal appearance, body size, race, age, or -religion. - -Examples of unacceptable behavior by participants include the use of -sexual language or imagery, derogatory comments or personal attacks, -trolling, public or private harassment, insults, or other -unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, -or reject comments, commits, code, wiki edits, issues, and other -contributions that are not aligned to this Code of Conduct. Project -maintainers who do not follow the Code of Conduct may be removed from -the project team. - -Instances of abusive, harassing, or otherwise unacceptable behavior -may be reported by opening an issue or contacting one or more of the -project maintainers. - -This Code of Conduct is adapted from the -[Contributor Covenant](http:contributor-covenant.org), version 1.0.0, -available at -[http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) diff --git a/test/spec/fixtures/repos/clojurescript-example/env/dev/clj/my_app/dev.clj b/test/spec/fixtures/repos/clojurescript-example/env/dev/clj/my_app/dev.clj deleted file mode 100644 index c5fcd66..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/env/dev/clj/my_app/dev.clj +++ /dev/null @@ -1,34 +0,0 @@ -(ns my-app.dev - (:require [environ.core :refer [env]] - [net.cgrand.enlive-html :refer [set-attr prepend append html]] - [cemerick.piggieback :as piggieback] - [weasel.repl.websocket :as weasel] - [figwheel-sidecar.auto-builder :as fig-auto] - [figwheel-sidecar.core :as fig] - [clojurescript-build.auto :as auto] - [clojure.java.shell :refer [sh]])) - -(def is-dev? (env :is-dev)) - -(def inject-devmode-html - (comp - (set-attr :class "is-dev") - (prepend (html [:script {:type "text/javascript" :src "/js/out/goog/base.js"}])) - (append (html [:script {:type "text/javascript"} "goog.require('my_app.main')"])))) - -(defn browser-repl [] - (let [repl-env (weasel/repl-env :ip "0.0.0.0" :port 9001)] - (piggieback/cljs-repl :repl-env repl-env))) - -(defn start-figwheel [] - (let [server (fig/start-server { :css-dirs ["resources/public/css"] }) - config {:builds [{:id "dev" - :source-paths ["src/cljs" "env/dev/cljs"] - :compiler {:output-to "resources/public/js/app.js" - :output-dir "resources/public/js/out" - :source-map true - :optimizations :none - :source-map-timestamp true - :preamble ["react/react.min.js"]}}] - :figwheel-server server}] - (fig-auto/autobuild* config))) diff --git a/test/spec/fixtures/repos/clojurescript-example/env/dev/cljs/my_app/main.cljs b/test/spec/fixtures/repos/clojurescript-example/env/dev/cljs/my_app/main.cljs deleted file mode 100644 index b786a6a..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/env/dev/cljs/my_app/main.cljs +++ /dev/null @@ -1,14 +0,0 @@ -(ns my-app.main - (:require [my-app.core :as core] - [figwheel.client :as figwheel :include-macros true] - [cljs.core.async :refer [put!]] - [weasel.repl :as weasel])) - -(figwheel/watch-and-reload - :websocket-url "ws://localhost:3449/figwheel-ws" - :jsload-callback (fn [] - (core/main))) - -(weasel/connect "ws://localhost:9001" :verbose true :print #{:repl :console}) - -(core/main) diff --git a/test/spec/fixtures/repos/clojurescript-example/env/prod/clj/my_app/dev.clj b/test/spec/fixtures/repos/clojurescript-example/env/prod/clj/my_app/dev.clj deleted file mode 100644 index b2cc131..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/env/prod/clj/my_app/dev.clj +++ /dev/null @@ -1,14 +0,0 @@ -(ns my-app.dev - (:require [environ.core :refer [env]])) - -(if (env :is-dev) - (throw (Exception. (str "Production environment code is being loaded while the dev environment is active. " - "You likely have compiled class files lying around from an uberjar build. " - "Remove the target/ directory and try again.")))) - -(def is-dev? false) -(def inject-devmode-html identity) -(defn browser-repl [] - (throw (Exception. "Browser connected REPL is not available in prod mode"))) -(defn start-figwheel [] - (throw (Exception. "Figwheel is not available in prod mode"))) diff --git a/test/spec/fixtures/repos/clojurescript-example/env/prod/cljs/my_app/main.cljs b/test/spec/fixtures/repos/clojurescript-example/env/prod/cljs/my_app/main.cljs deleted file mode 100644 index 8d83a76..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/env/prod/cljs/my_app/main.cljs +++ /dev/null @@ -1,4 +0,0 @@ -(ns my-app.main - (:require [my-app.core :as core])) - -(core/main) diff --git a/test/spec/fixtures/repos/clojurescript-example/env/test/js/polyfill.js b/test/spec/fixtures/repos/clojurescript-example/env/test/js/polyfill.js deleted file mode 100644 index ca8d384..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/env/test/js/polyfill.js +++ /dev/null @@ -1,24 +0,0 @@ -if (!Function.prototype.bind) { - Function.prototype.bind = function(oThis) { - if (typeof this !== 'function') { - // closest thing possible to the ECMAScript 5 - // internal IsCallable function - throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); - } - - var aArgs = Array.prototype.slice.call(arguments, 1), - fToBind = this, - fNOP = function() {}, - fBound = function() { - return fToBind.apply(this instanceof fNOP && oThis - ? this - : oThis, - aArgs.concat(Array.prototype.slice.call(arguments))); - }; - - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - - return fBound; - }; -} diff --git a/test/spec/fixtures/repos/clojurescript-example/env/test/js/unit-test.js b/test/spec/fixtures/repos/clojurescript-example/env/test/js/unit-test.js deleted file mode 100644 index bb56975..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/env/test/js/unit-test.js +++ /dev/null @@ -1,42 +0,0 @@ -var page = require('webpage').create(); -var url; - -if (phantom.args) { - url = phantom.args[0]; -} else { - url = require('system').args[1]; -} - -page.onConsoleMessage = function (message) { - console.log(message); -}; - -function exit(code) { - setTimeout(function(){ phantom.exit(code); }, 0); - phantom.onError = function(){}; -} - -console.log("Loading URL: " + url); - -page.open(url, function (status) { - if (status != "success") { - console.log('Failed to open ' + url); - phantom.exit(1); - } - - console.log("Running test."); - - var result = page.evaluate(function() { - return my_app.test_runner.runner(); - }); - - if (result != 0) { - console.log("*** Test failed! ***"); - exit(1); - } - else { - console.log("Test succeeded."); - exit(0); - } - -}); diff --git a/test/spec/fixtures/repos/clojurescript-example/env/test/unit-test.html b/test/spec/fixtures/repos/clojurescript-example/env/test/unit-test.html deleted file mode 100644 index 4da05bb..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/env/test/unit-test.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/test/spec/fixtures/repos/clojurescript-example/project.clj b/test/spec/fixtures/repos/clojurescript-example/project.clj deleted file mode 100644 index c1f5c2b..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/project.clj +++ /dev/null @@ -1,75 +0,0 @@ -(defproject my-app "0.1.0-SNAPSHOT" - :description "FIXME: write description" - :url "http://example.com/FIXME" - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"} - - :source-paths ["src/clj"] - - :test-paths ["test/clj"] - - :dependencies [[org.clojure/clojure "1.6.0"] - [org.clojure/clojurescript "0.0-3058" :scope "provided"] - [ring "1.3.2"] - [ring/ring-defaults "0.1.4"] - [compojure "1.3.2"] - [enlive "1.1.6"] - [org.omcljs/om "0.8.8"] - [environ "1.0.0"]] - - :plugins [[lein-cljsbuild "1.0.5"] - [lein-environ "1.0.0"]] - - :min-lein-version "2.5.0" - - :uberjar-name "my-app.jar" - - :cljsbuild {:builds {:app {:source-paths ["src/cljs"] - :compiler {:output-to "resources/public/js/app.js" - :output-dir "resources/public/js/out" - :source-map "resources/public/js/out.js.map" - :preamble ["react/react.min.js"] - :optimizations :none - :pretty-print true}}}} - - :profiles {:dev {:source-paths ["env/dev/clj"] - :test-paths ["test/clj"] - - :dependencies [[figwheel "0.2.5"] - [figwheel-sidecar "0.2.5"] - [com.cemerick/piggieback "0.1.5"] - [weasel "0.6.0"]] - - :repl-options {:init-ns my-app.server - :nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]} - - :plugins [[lein-figwheel "0.2.5"]] - - :figwheel {:http-server-root "public" - :server-port 3449 - :css-dirs ["resources/public/css"] - :ring-handler my-app.server/http-handler} - - :env {:is-dev true} - - :cljsbuild {:test-commands { "test" ["phantomjs" "env/test/js/unit-test.js" "env/test/unit-test.html"] } - :builds {:app {:source-paths ["env/dev/cljs"]} - :test {:source-paths ["src/cljs" "test/cljs"] - :compiler {:output-to "resources/public/js/app_test.js" - :output-dir "resources/public/js/test" - :source-map "resources/public/js/test.js.map" - :preamble ["react/react.min.js"] - :optimizations :whitespace - :pretty-print false}}}}} - - :uberjar {:source-paths ["env/prod/clj"] - :hooks [leiningen.cljsbuild] - :env {:production true} - :omit-source true - :aot :all - :main my-app.server - :cljsbuild {:builds {:app - {:source-paths ["env/prod/cljs"] - :compiler - {:optimizations :advanced - :pretty-print false}}}}}}) diff --git a/test/spec/fixtures/repos/clojurescript-example/resources/index.html b/test/spec/fixtures/repos/clojurescript-example/resources/index.html deleted file mode 100644 index a8d1f98..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/resources/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - Welcome from ClojureScript -
- - - diff --git a/test/spec/fixtures/repos/clojurescript-example/resources/public/css/style.css b/test/spec/fixtures/repos/clojurescript-example/resources/public/css/style.css deleted file mode 100644 index b2d3dc0..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/resources/public/css/style.css +++ /dev/null @@ -1,3 +0,0 @@ -h1 { - text-decoration: underline; -} diff --git a/test/spec/fixtures/repos/clojurescript-example/src/clj/my_app/server.clj b/test/spec/fixtures/repos/clojurescript-example/src/clj/my_app/server.clj deleted file mode 100644 index 5b4074e..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/src/clj/my_app/server.clj +++ /dev/null @@ -1,42 +0,0 @@ -(ns my-app.server - (:require [clojure.java.io :as io] - [my-app.dev :refer [is-dev? inject-devmode-html browser-repl start-figwheel]] - [compojure.core :refer [GET defroutes]] - [compojure.route :refer [resources]] - [net.cgrand.enlive-html :refer [deftemplate]] - [net.cgrand.reload :refer [auto-reload]] - [ring.middleware.reload :as reload] - [ring.middleware.defaults :refer [wrap-defaults api-defaults]] - [environ.core :refer [env]] - [ring.adapter.jetty :refer [run-jetty]]) - (:gen-class)) - -(deftemplate page (io/resource "index.html") [] - [:body] (if is-dev? inject-devmode-html identity)) - -(defroutes routes - (resources "/") - (resources "/react" {:root "react"}) - (GET "/*" req (page))) - -(def http-handler - (if is-dev? - (reload/wrap-reload (wrap-defaults #'routes api-defaults)) - (wrap-defaults routes api-defaults))) - -(defn run-web-server [& [port]] - (let [port (Integer. (or port (env :port) 10555))] - (println (format "Starting web server on port %d." port)) - (run-jetty http-handler {:port port :join? false}))) - -(defn run-auto-reload [& [port]] - (auto-reload *ns*) - (start-figwheel)) - -(defn run [& [port]] - (when is-dev? - (run-auto-reload)) - (run-web-server port)) - -(defn -main [& [port]] - (run port)) diff --git a/test/spec/fixtures/repos/clojurescript-example/src/cljs/my_app/core.cljs b/test/spec/fixtures/repos/clojurescript-example/src/cljs/my_app/core.cljs deleted file mode 100644 index 927bc50..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/src/cljs/my_app/core.cljs +++ /dev/null @@ -1,35 +0,0 @@ -(ns my-app.core - (:require [om.core :as om :include-macros true] - [om.dom :as dom :include-macros true])) - -(enable-console-print!) - -(defonce app-state - (atom - {:contacts - [{:first "Ben" :last "Bitdiddle" :email "benb@mit.edu"} - {:first "Lem" :middle-initial "E" :last "Tweakit" :email "morebugs@mit.edu"}]})) - -(defn display-name [{:keys [first last] :as contact}] - (str last ", " first)) - -(defn contact-view [contact owner] - (reify - om/IRender - (render [this] - (dom/li nil (display-name contact))))) - -(defn contacts-view [data owner] - (reify - om/IRender - (render [this] - (dom/div nil - (dom/h2 nil "Contact list") - (apply dom/ul nil - (om/build-all contact-view (:contacts data))))))) - -(defn main [] - (om/root - contacts-view - app-state - {:target (. js/document (getElementById "app"))})) diff --git a/test/spec/fixtures/repos/clojurescript-example/system.properties b/test/spec/fixtures/repos/clojurescript-example/system.properties deleted file mode 100644 index 1863114..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/system.properties +++ /dev/null @@ -1,2 +0,0 @@ - -java.runtime.version=8 diff --git a/test/spec/fixtures/repos/clojurescript-example/test/clj/my_app/example_test.clj b/test/spec/fixtures/repos/clojurescript-example/test/clj/my_app/example_test.clj deleted file mode 100644 index c38bf86..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/test/clj/my_app/example_test.clj +++ /dev/null @@ -1,5 +0,0 @@ -(ns my_app.example-test - (:require [clojure.test :refer :all])) - -(deftest example-passing-test - (is (= 1 1))) diff --git a/test/spec/fixtures/repos/clojurescript-example/test/cljs/my_app/core-test.cljs b/test/spec/fixtures/repos/clojurescript-example/test/cljs/my_app/core-test.cljs deleted file mode 100644 index 73830b6..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/test/cljs/my_app/core-test.cljs +++ /dev/null @@ -1,6 +0,0 @@ -(ns my_app.core-test - (:require-macros [cljs.test :refer (is deftest testing)]) - (:require [cljs.test])) - -(deftest example-passing-test - (is (= 1 1))) diff --git a/test/spec/fixtures/repos/clojurescript-example/test/cljs/my_app/test-runner.cljs b/test/spec/fixtures/repos/clojurescript-example/test/cljs/my_app/test-runner.cljs deleted file mode 100644 index 0717b83..0000000 --- a/test/spec/fixtures/repos/clojurescript-example/test/cljs/my_app/test-runner.cljs +++ /dev/null @@ -1,13 +0,0 @@ -(ns my_app.test-runner - (:require - [cljs.test :refer-macros [run-tests]] - [my_app.core-test])) - -(enable-console-print!) - -(defn runner [] - (if (cljs.test/successful? - (run-tests - 'my_app.core-test)) - 0 - 1)) diff --git a/test/spec/fixtures/repos/immutant-feature-demo/.gitignore b/test/spec/fixtures/repos/immutant-feature-demo/.gitignore deleted file mode 100644 index aaa73be..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -/target -/lib -/classes -/checkouts -/.descriptors -pom.xml -pom.xml.asc -*.jar -*.class -.lein-deps-sum -.lein-failures -.lein-plugins -.lein-repl-history -/.nrepl-port -wildfly-* -hornetq-data \ No newline at end of file diff --git a/test/spec/fixtures/repos/immutant-feature-demo/.openshift/.leinrc b/test/spec/fixtures/repos/immutant-feature-demo/.openshift/.leinrc deleted file mode 100644 index f29fdfe..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/.openshift/.leinrc +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -export LEIN_HOME="${OPENSHIFT_DATA_DIR}/.lein" -export LEIN_JVM_OPTS="-Duser.home=${LEIN_HOME}" -export JVM_OPTS="-Dhornetq.netty.port=15000 -Dhornetq.netty.host=${OPENSHIFT_DIY_IP}" -export DEMO_WEB_HOST=${OPENSHIFT_DIY_IP} -export DEMO_WEB_PORT=${OPENSHIFT_DIY_PORT} - -if [ ! -d ${LEIN_HOME} ]; then - echo "Installing Leiningen" - cd ${OPENSHIFT_DATA_DIR} - wget https://raw.github.com/technomancy/leiningen/stable/bin/lein - if [ -f lein ]; then - chmod +x lein - mkdir -p $LEIN_HOME - fi -fi diff --git a/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/pre_deploy_wildfly b/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/pre_deploy_wildfly deleted file mode 100755 index e898d5b..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/pre_deploy_wildfly +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -source ${OPENSHIFT_REPO_DIR}/.openshift/.leinrc - -cd ${OPENSHIFT_REPO_DIR} -mkdir -p deployments -${OPENSHIFT_DATA_DIR}/lein do clean, immutant war -o deployments -n ROOT diff --git a/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/start b/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/start deleted file mode 100755 index 5a16913..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/start +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -source ${OPENSHIFT_REPO_DIR}/.openshift/.leinrc - -cd ${OPENSHIFT_REPO_DIR} -nohup ${OPENSHIFT_DATA_DIR}/lein trampoline run >${OPENSHIFT_LOG_DIR}/server.log 2>&1 & diff --git a/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/stop b/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/stop deleted file mode 100755 index 12d0ecd..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/.openshift/action_hooks/stop +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -pid=`ps -ef | grep lein | grep -v grep | awk '{ print $2 }'` -if [[ $pid != "" ]]; then - kill $pid -fi diff --git a/test/spec/fixtures/repos/immutant-feature-demo/LICENSE b/test/spec/fixtures/repos/immutant-feature-demo/LICENSE deleted file mode 100644 index d645695..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/test/spec/fixtures/repos/immutant-feature-demo/Procfile b/test/spec/fixtures/repos/immutant-feature-demo/Procfile deleted file mode 100644 index d8d6921..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: java $JVM_OPTS -jar target/demo-standalone.jar host 0.0.0.0 port $PORT diff --git a/test/spec/fixtures/repos/immutant-feature-demo/app.json b/test/spec/fixtures/repos/immutant-feature-demo/app.json deleted file mode 100644 index 9646c07..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/app.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "Immutant Feature Demo", - "description": "A template for getting started with the popular Immutant framework.", - "website": "http://immutant.org", - "success_url": "/index.html", - "addons": ["heroku-postgresql:hobby-dev", "papertrail"] -} diff --git a/test/spec/fixtures/repos/immutant-feature-demo/doc/images/immutant-runtime.png b/test/spec/fixtures/repos/immutant-feature-demo/doc/images/immutant-runtime.png deleted file mode 100644 index 23d4bfc..0000000 Binary files a/test/spec/fixtures/repos/immutant-feature-demo/doc/images/immutant-runtime.png and /dev/null differ diff --git a/test/spec/fixtures/repos/immutant-feature-demo/doc/images/immutant_logo.jpg b/test/spec/fixtures/repos/immutant-feature-demo/doc/images/immutant_logo.jpg deleted file mode 100644 index ed9c8e9..0000000 Binary files a/test/spec/fixtures/repos/immutant-feature-demo/doc/images/immutant_logo.jpg and /dev/null differ diff --git a/test/spec/fixtures/repos/immutant-feature-demo/doc/images/tomcat-runtime.png b/test/spec/fixtures/repos/immutant-feature-demo/doc/images/tomcat-runtime.png deleted file mode 100644 index 0314e66..0000000 Binary files a/test/spec/fixtures/repos/immutant-feature-demo/doc/images/tomcat-runtime.png and /dev/null differ diff --git a/test/spec/fixtures/repos/immutant-feature-demo/doc/overview.org b/test/spec/fixtures/repos/immutant-feature-demo/doc/overview.org deleted file mode 100644 index a2bbb27..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/doc/overview.org +++ /dev/null @@ -1,87 +0,0 @@ -[[file:images/immutant_logo.jpg]] - -* What is Immutant? - - A collection of libraries that can be embedded within any Clojure - application. Optionally, the application can be deployed to a stock - [[http://wildfly.org][WildFly]] application server. - -* The [[https://github.com/immutant/lein-immutant/tree/2x-dev][lein-immutant]] plugin - - Only required if deploying your app to WildFly. - -** Tasks - - - lein immutant war - -* Using outside of WildFly - - Set a =:main= in =project.clj=, and start with =lein run=. - -* Immutant API's - - Functions whose side effects invoke JBoss services - -** immutant.web - - - app segmentation via virtual host and/or context path - - automatic session replication in a cluster - - auto-reloading in dev mode - - static resources served via [[http://ring-clojure.github.io/ring/ring.middleware.resource.html#var-wrap-resource][ring.middleware.resource/wrap-resource]] - - :ring config, e.g. :handler, :init, :destroy, - stacktraces?, :auto-reload?, :reload-paths - - simple websockets - - examples: [[../src/demo/web.clj][demo/web.clj]] and [[../src/demo/websocket.clj][demo/websocket.clj]] - -** immutant.scheduling - - - schedules specified by maps created with helper functions - - singleton by default (runs on only one node in cluster) - - not durable - - examples: [[../src/demo/scheduling.clj][demo/scheduling.clj]] - -*** Parameters - - | :at | java.util.Date, millis since epoch, or a military time string "HHmm" | - | :in | start in millis from now, period alias or period spec | - | :every | delay interval in millis, period alias or period spec | - | :repeat | # of repeats after initial firing; with :every | - | :until | java.util.Date, millis since epoch, or "HHmm"; with :every | - | :cron | a Quartz cron spec, described below | - -*** cron specs - - dash for spans, comma for multiples, division for rates - - | seconds | 0-59 | | - | minutes | 0-59 | | - | hours | 0-23 | | - | dom | 1-31 | ? | - | month | 1-12 or JAN-DEC | | - | dow | 1-7 or SUN-SAT | ? | - | year | 1970-2099 | optional | - - - - -** immutant.messaging - - - allows publishing and listening to queues/topics using HornetQ - - supports point-to-point, request-response messaging - - examples: [[../src/demo/messaging.clj][demo/messaging.clj]] and [[../src/demo/remote_messaging_client.clj][demo/remote_messaging_client.clj]] - -** immutant.caching - - - Infinispan transactional data grid - - flexible clustering: replicated, invalidated, distributed - - strong consistency by default, but trades C for A when P - - eviction, expiration, persistence, conditional writes - - implements core.cache/CacheProtocol - - can be used with core.memoize/PluggableMemoization - - can be shared with ruby apps in an app server - - functional alternative: [[https://projectodd.ci.cloudbees.com/job/immutant2-incremental/lastSuccessfulBuild/artifact/target/apidocs/immutant.caching.html#var-swap-in.21][immutant.caching/swap-in!]] - - examples: [[../src/demo/caching.clj][demo/caching.clj]] diff --git a/test/spec/fixtures/repos/immutant-feature-demo/project.clj b/test/spec/fixtures/repos/immutant-feature-demo/project.clj deleted file mode 100644 index 55270a5..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/project.clj +++ /dev/null @@ -1,29 +0,0 @@ -(defproject demo "0.2.0-SNAPSHOT" - :description "Demo of Immutant 2.x libraries" - :url "http://github.com/immutant/feature-demo" - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.6.0"] - [org.immutant/immutant "2.0.0-beta1"] - - ;; or bring the artifacts in piecemeal: - ;; [org.immutant/caching "2.0.0-beta1"] - ;; [org.immutant/messaging "2.0.0-beta1"] - ;; [org.immutant/scheduling "2.0.0-beta1"] - ;; [org.immutant/web "2.0.0-beta1"] - - [compojure "1.1.8"] - [ring/ring-core "1.3.0"] - [ring/ring-devel "1.3.0"] - [org.clojure/core.memoize "0.5.6"] - [clj-time "0.7.0"] - [cheshire "5.3.1"] - [environ "1.0.0"]] - :repositories [["Immutant incremental builds" - "http://downloads.immutant.org/incremental/"]] - :plugins [[lein-immutant "2.0.0-alpha2"]] - :main demo.core - :uberjar-name "demo-standalone.jar" - :profiles {:uberjar {:aot [demo.core]}} - :min-lein-version "2.4.0" - :aliases {"msg-client" ["run" "-m" "demo.remote-messaging-client"]}) diff --git a/test/spec/fixtures/repos/immutant-feature-demo/resources/public/css/style.css b/test/spec/fixtures/repos/immutant-feature-demo/resources/public/css/style.css deleted file mode 100644 index c0ef4c5..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/resources/public/css/style.css +++ /dev/null @@ -1,29 +0,0 @@ -html { - font-family: Helvetica, Arial, sans-serif; - font-size: 100%; -} - -.opened { - color: green; -} - -.closed { - color: gray; -} - -.error { - color: red; -} - -.received { - color: blue; -} - -.sent { - color: green; -} - -button:hover { - opacity: 0.75; - cursor: pointer; -} diff --git a/test/spec/fixtures/repos/immutant-feature-demo/resources/public/index.html b/test/spec/fixtures/repos/immutant-feature-demo/resources/public/index.html deleted file mode 100644 index e340b99..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/resources/public/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - Feature Demo - - - -

Feature Demo

- - - - diff --git a/test/spec/fixtures/repos/immutant-feature-demo/resources/public/js/app.js b/test/spec/fixtures/repos/immutant-feature-demo/resources/public/js/app.js deleted file mode 100644 index 2898811..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/resources/public/js/app.js +++ /dev/null @@ -1,69 +0,0 @@ - -window.onload = function() { - - // Page elements - var input = document.getElementById('input'); - var openBtn = document.getElementById('open'); - var sendBtn = document.getElementById('send'); - var closeBtn = document.getElementById('close'); - var messages = document.getElementById('messages'); - - // Our websocket - var socket; - - function output(style, text){ - messages.innerHTML += "
" + text + ""; - } - - // Open - openBtn.onclick = function(e) { - e.preventDefault(); - if (socket !== undefined) { - output("error", "Already connected"); - return; - } - - var uri = "ws://" + location.host + location.pathname; - uri = uri.substring(0, uri.lastIndexOf('/')); - socket = new WebSocket(uri); - - socket.onerror = function(error) { - output("error", error); - }; - - socket.onopen = function(event) { - output("opened", "Connected to " + event.currentTarget.url); - }; - - socket.onmessage = function(event) { - var message = event.data; - output("received", "<<< " + message); - }; - - socket.onclose = function(event) { - output("closed", "Disconnected: " + event.code + " " + event.reason); - socket = undefined; - }; - }; - - // Send - sendBtn.onclick = function(e) { - if (socket == undefined) { - output("error", 'Not connected'); - return; - } - var text = document.getElementById("input").value; - socket.send(text); - output("sent", ">>> " + text); - }; - - // Close - closeBtn.onclick = function(e) { - if (socket == undefined) { - output('error', 'Not connected'); - return; - } - socket.close(1000, "Close button clicked"); - }; - -}; diff --git a/test/spec/fixtures/repos/immutant-feature-demo/resources/public/websocket.html b/test/spec/fixtures/repos/immutant-feature-demo/resources/public/websocket.html deleted file mode 100644 index e6a6aad..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/resources/public/websocket.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - WebSocket Demo - - - - - -

WebSocket Demo

- -
- -
- -
- - - -
- -
- - - - diff --git a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/caching.clj b/test/spec/fixtures/repos/immutant-feature-demo/src/demo/caching.clj deleted file mode 100644 index f8e8670..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/caching.clj +++ /dev/null @@ -1,177 +0,0 @@ -(ns demo.caching - (:require [immutant.caching :as c] - [immutant.caching.core-memoize :as cmemo] - [immutant.scheduling :as sch])) - -;; Caches implement org.infinispan.Cache and -;; java.util.concurrent.ConcurrentMap - -(comment writing - "Various ways of putting entries in a cache" - - (def foo (c/cache "foo")) - - ;; The swap-in! function atomically updates cache entries - ;; by applying a function to the current value or nil, if the key is - ;; missing. The function should be side-effect free. - - (c/swap-in! foo :a (fnil inc 0)) ;=> 1 - (c/swap-in! foo :b (constantly "foo")) ;=> "foo" - (c/swap-in! foo :a inc) ;=> 2 - - ;; Internally, swap-in! uses the ConcurrentMap methods, - ;; replace, i.e. "compare and set", and putIfAbsent, to provide a - ;; consistent view of the cache to callers. Of course, you can - ;; invoke these and other methods directly using plain ol' Java - ;; interop... - - ;; Put an entry in the cache - (.put foo :a 1) - - ;; Add all the entries in the map to the cache - (.putAll foo {:b 2, :c 3}) - - ;; Put it in only if key is not already present - (.putIfAbsent foo :b 6) ;=> 2 - (.putIfAbsent foo :d 4) ;=> nil - - ;; Put it in only if key is already present - (.replace foo :e 5) ;=> nil - (.replace foo :b 6) ;=> 2 - - ;; Replace for specific key and value (compare-and-set) - (.replace foo :b 2 0) ;=> false - (.replace foo :b 6 0) ;=> true - ) - -(comment reading - "Caches are just Maps, so core clojure functions work fine" - - (def bar (c/cache "bar")) - (.putAll bar {:a 1, :b {:c 3, :d 4}}) - - ;; Use get to obtain associated values - (get bar :a) ;=> 1 - (get bar :x) ;=> nil - (get bar :x 42) ;=> 42 - - ;; Keywords look up their value - (:a bar) ;=> 1 - (:x bar 42) ;=> 42 - - ;; Nested structures work as you would expect - (get-in bar [:b :c]) ;=> 3 - - ;; Use find to return entries - (find bar :a) ;=> [:a 1] - - ;; Use contains? to check membership - (contains? bar :a) ;=> true - (contains? bar :x) ;=> false - ) - -(comment removing - "Expiration, eviction, and explicit removal" - - (def baz (c/cache "baz", - :ttl [5 :minutes], :idle [1 :minute] ; expiration - :max-entries 3, :eviction :lru)) ; eviction - (.putAll baz {:a 1 :b 2 :c 3}) - - ;; Eviction - (:a baz) ;=> 1 - (select-keys baz [:b :c]) ;=> {:c 3, :b 2} - (.put baz :d 4) - (:a baz) ;=> nil - - ;; You can easily override the cache's expiration settings, - ;; time-to-live and/or max idle time, for all subsequent writes - (let [c (c/with-expiration baz - :ttl [1 :hour] - :idle [20 :minutes])] - (.put c :a 1) - (c/swap-in! c :a dec) - (.putAll c {:b 2, :c 3}) - (.putIfAbsent c :f 6) - (.replace c :f 5)) - - ;; Removing a missing key is harmless - (.remove baz :missing) ;=> nil - - ;; Removing an existing key returns its value - (.remove baz :b) ;=> 2 - - ;; If value is passed, both must match for remove to succeed - (.remove baz :c 2) ;=> false - (.remove baz :c 3) ;=> true - - ;; Clear all entries - (.clear baz) - ) - -(comment encoding - "Cache entries are not encoded by default, but may be decorated with - a codec. Provided codecs include :edn, :json, and :fressian. The - latter two require additional dependencies: 'cheshire' and - 'org.clojure/data.fressian', respectively." - (def ham (c/cache "ham")) - (def encoded (c/with-codec ham :edn)) - - (.put encoded :a {:b 42}) - (:a encoded) ;=> {:b 42} - - ;; Access via non-encoded caches still possible - (get ham :a) ;=> nil - (get ham ":a") ;=> "{:b 42}" - - ;; Infinispan caches don't allow null keys or values - (try - (.put ham nil :a) ;=> Null keys are not supported! - (.put ham :b nil) ;=> Null values are not supported! - (catch NullPointerException _ "ERROR!")) - - ;; But nil keys and values are fine in an encoded cache - (.put encoded nil :a) - (.put encoded :b nil) - (get encoded nil) ;=> :a - (:b encoded) ;=> nil - (contains? encoded :b) ;=> true - (contains? ham "nil") ;=> true - ) - -(comment memoization - "Caches will implement clojure.core.memoize/PluggableMemoization - when you require immutant.caching.core-memoize, but it's up to you - to ensure core.memoize is on the classpath" - - (defn slow-fn [& _] - (Thread/sleep 5000) - 42) - - ;; Other than the function to be memoized, arguments are the same as - ;; for the cache function. - (def memoized-fn (cmemo/memo slow-fn "memo", :ttl [5 :minutes])) - - ;; Invoking the memoized function fills the cache with the result - ;; from the slow function the first time it is called. - (memoized-fn 1 2 3) ;=> 42 - - ;; Subsequent invocations with the same parameters return the result - ;; from the cache, avoiding the overhead of the slow function - (memoized-fn 1 2 3) ;=> 42 - - ;; It's possible to manipulate the cache backing the memoized - ;; function by referring to its name - (def c (c/cache "memo")) - (get c [1 2 3]) ;=> 42 - ) - -(defn -main [& args] - "Schedule a counter" - (let [c (c/cache "counter") - f #(println "Updating count to" - (c/swap-in! c :count (fnil inc 0)))] - (sch/schedule f - :id "counter" - :every [10 :seconds] - :singleton false))) diff --git a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/core.clj b/test/spec/fixtures/repos/immutant-feature-demo/src/demo/core.clj deleted file mode 100644 index c0ead17..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/core.clj +++ /dev/null @@ -1,12 +0,0 @@ -(ns demo.core - (:require demo.web - demo.scheduling - demo.messaging - demo.caching) - (:gen-class)) - -(defn -main [& args] - (apply demo.web/-main args) - (apply demo.messaging/-main args) - (apply demo.scheduling/-main args) - (apply demo.caching/-main args)) diff --git a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/messaging.clj b/test/spec/fixtures/repos/immutant-feature-demo/src/demo/messaging.clj deleted file mode 100644 index a5a176d..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/messaging.clj +++ /dev/null @@ -1,37 +0,0 @@ -(ns demo.messaging - (:require [immutant.messaging :as msg])) - -(defn listener - "A simple message listener" - [m] - (println "listener received" (pr-str m))) - -(defn -main [& _] - - ;; msg/queue creates a queue in HornetQ if it does not already exist - ;; returns a reference to the queue - (msg/queue "my-queue") - - ;; registers a fn to be called each time a message comes in - (msg/listen (msg/queue "my-queue") listener) - - ;; sends 10 messages to the queue - (dotimes [n 10] - (msg/publish (msg/queue "my-queue") {:message n})) - - ;; default encoding is :edn. Other options are: :edn, :fressian, :json, :none - ;; :json requires cheshire, :fressian requires data.fressian - (msg/publish (msg/queue "my-queue") {:message :hi} :encoding :json) - - ;; using synchronous messaging (request/respond) - (msg/queue "sync-queue") - - ;; registers a fn as a responder - a listener who's return value - ;; is sent to the requester - (msg/respond (msg/queue "sync-queue") inc) - - (dotimes [n 5] - ;; request returns a j.u.c.Future - (println "response is:" - @(msg/request (msg/queue "sync-queue") n))) - ) diff --git a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/remote_messaging_client.clj b/test/spec/fixtures/repos/immutant-feature-demo/src/demo/remote_messaging_client.clj deleted file mode 100644 index e868efe..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/remote_messaging_client.clj +++ /dev/null @@ -1,19 +0,0 @@ -(ns demo.remote-messaging-client - (:require [immutant.messaging :as msg] - [clojure.string :as str] - [immutant.util :as util]) - (:gen-class)) - -(defn -main - "Connects to a 'remote' HornetQ running on localhost:5445 and delivers - the message to the given destination. The first argument is the queue - name, the rest of the arguments are considered the message. Example: - - lein msg-client my-queue hi there friends" - [queue-name & message] - (with-open [context (msg/context :host "localhost" :port (util/messaging-remoting-port))] - (let [queue (msg/queue queue-name :context context) - message (str/join " " message)] - (println (format "Sending '%s' to queue %s" - message queue-name)) - (msg/publish queue message)))) diff --git a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/scheduling.clj b/test/spec/fixtures/repos/immutant-feature-demo/src/demo/scheduling.clj deleted file mode 100644 index 7d7a68b..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/scheduling.clj +++ /dev/null @@ -1,88 +0,0 @@ -(ns demo.scheduling - (:require [immutant.scheduling :as sch] - [immutant.util :as util] - immutant.scheduling.joda - clj-time.core - clj-time.periodic) - (:import java.util.Date)) - -;; scheduling specs are just maps. we provide optional helpers for -;; generating thoes maps -(def every-5s - (or {:every (or 5000 - [5 :seconds])} - (sch/every 5 :seconds))) - -;; :at can be a Date, a time as a string, or millis since epoch -(def daily - (-> (sch/at (or (Date.) "1830" 1395439646983)) - (sch/every :day))) - -;; helpers optionally take a map as the first arg, so compose -(def in-5m-until-5pm - (-> (sch/in 5 :minutes) - (sch/every 2 :hours, 30 :minutes) - (sch/until "1700"))) - -;; cron-style strings are also supported -(def nine-am - (sch/cron "0 0 9 * * ?")) - -(def every-5s-cron - (sch/cron "*/5 * * * * ?")) - -(def every-10ms-in-500ms-4-times - (-> (sch/in 500) - (sch/every 10) - (sch/limit 4))) - -;; you can use clj-time periods if using clj-time -(defn every-3s-lazy-seq [] - (let [at (clj-time.core/plus (clj-time.core/now) (clj-time.core/seconds 1)) - every (clj-time.core/seconds 3)] - (clj-time.periodic/periodic-seq at every))) - -(comment - - ;; scheduling a simple job, using bound-fn to capture *out* for the repl - (def every-2-job - (sch/schedule (bound-fn [] - (println "called")) - (sch/every 2 :seconds))) - - ;; the return value of the schedule call can be used to stop it - (sch/stop every-2-job) - - ;; schedule a job from a clj-time sequence - (def seq-job - (immutant.scheduling.joda/schedule-seq #(println "a sequence") - (every-3s-lazy-seq))) - - (sch/stop seq-job) - - ) - -(defn -main [& _] - - ;; start a couple of jobs, along with a job to stop them in 20 seconds - (let [beep (sch/schedule #(println "beep") every-5s) - ;; schedule a clj-time sequence - boop (immutant.scheduling.joda/schedule-seq #(println "boop") (every-3s-lazy-seq))] - (sch/schedule - (fn [] - (println "unscheduling beep & boop") - (sch/stop beep) - (sch/stop boop)) - (sch/in 20 :seconds))) - - ;; start singleton and non-singleton jobs to demo cluster failover - (when (util/in-container?) - - ;; singleton jobs require an id - (sch/schedule #(println "I run on ONE node") - (-> (sch/every 10 :seconds) - (sch/id :a_singleton))) - - (sch/schedule #(println "I run on EVERY node") - (-> (sch/every 9 :seconds) - (sch/singleton false))))) diff --git a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/web.clj b/test/spec/fixtures/repos/immutant-feature-demo/src/demo/web.clj deleted file mode 100644 index 6a1305a..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/src/demo/web.clj +++ /dev/null @@ -1,49 +0,0 @@ -(ns demo.web - (:require [immutant.web :as web] - [immutant.web.websocket :as ws] - [immutant.web.middleware :as web-middleware] - [compojure.route :as route] - [compojure.core :refer (ANY GET defroutes)] - [ring.util.response :refer (response redirect content-type)] - [clojure.pprint :refer (pprint)] - [environ.core :refer (env)])) - -(defn echo - "Echos the request back as a string." - [request] - (-> (response (with-out-str (pprint request))) - (content-type "text/plain"))) - -(defn counter - "From https://github.com/ring-clojure/ring/wiki/Sessions" - [{session :session}] - (let [count (:count session 0) - session (assoc session :count (inc count))] - (println "counter =>" count) - (-> (response (str "You accessed this page " count " times\n")) - (assoc :session session)))) - -(def websocket-callbacks - "WebSocket callback functions" - {:on-open (fn [channel handshake] - (ws/send! channel "Ready to reverse your messages!")) - :on-close (fn [channel {:keys [code reason]}] - (println "close code:" code "reason:" reason)) - :on-message (fn [ch m] - (ws/send! ch (apply str (reverse m))))}) - -(defroutes routes - (GET "/" {c :context} (redirect (str c "/index.html"))) - (GET "/counter" [] counter) - (route/resources "/") - (ANY "*" [] echo)) - -(defn -main [& {:as args}] - (web/run - (-> routes - (web-middleware/wrap-session {:timeout 20}) - ;; wrap the handler with websocket support - ;; websocket requests will go to the callbacks, ring requests to the handler - (ws/wrap-websocket websocket-callbacks)) - (merge {"host" (env :demo-web-host), "port" (env :demo-web-port)} - args))) diff --git a/test/spec/fixtures/repos/immutant-feature-demo/system.properties b/test/spec/fixtures/repos/immutant-feature-demo/system.properties deleted file mode 100644 index 221ae01..0000000 --- a/test/spec/fixtures/repos/immutant-feature-demo/system.properties +++ /dev/null @@ -1 +0,0 @@ -java.runtime.version=8 diff --git a/test/spec/fixtures/repos/lein-1-jdk-8/project.clj b/test/spec/fixtures/repos/lein-1-jdk-8/project.clj deleted file mode 100644 index cbea9ba..0000000 --- a/test/spec/fixtures/repos/lein-1-jdk-8/project.clj +++ /dev/null @@ -1,12 +0,0 @@ -(defproject sample "0.1.0-SNAPSHOT" - :description "FIXME: write description" - :url "http://example.com/FIXME" - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"} - :repositories [["central-https" {:url "https://repo1.maven.org/maven2"}] - ["clojars-https" {:url "https://clojars.org/repo/"}]] - :omit-default-repositories true - :dependencies [[org.clojure/clojure "1.5.1"]] - :main ^:skip-aot sample.core - :target-path "target/%s" - :profiles {:uberjar {:aot :all}}) diff --git a/test/spec/fixtures/repos/lein-1-jdk-8/system.properties b/test/spec/fixtures/repos/lein-1-jdk-8/system.properties deleted file mode 100644 index c53c29f..0000000 --- a/test/spec/fixtures/repos/lein-1-jdk-8/system.properties +++ /dev/null @@ -1 +0,0 @@ -java.runtime.version=zulu-8 diff --git a/test/spec/fixtures/repos/lein-1.x/project.clj b/test/spec/fixtures/repos/lein-1.x/project.clj new file mode 100644 index 0000000..bbb2e3c --- /dev/null +++ b/test/spec/fixtures/repos/lein-1.x/project.clj @@ -0,0 +1,10 @@ +; This project is intentionally very simple since it's hard to create a working HTTP service in 2025 with leiningen 1.x +; that does not fail with download errors. Since this fixture will be removed soon anyways, having such a simple +; project serves its purpose well enough. +(defproject sample "0.1.0-SNAPSHOT" + :repositories [["central-https" {:url "https://repo1.maven.org/maven2"}] + ["clojars-https" {:url "https://clojars.org/repo/"}]] + :omit-default-repositories true + :dependencies [[org.clojure/clojure "1.5.1"]] + :main ^:skip-aot sample.core + :target-path "target/%s") diff --git a/test/spec/fixtures/repos/lein-1-jdk-8/source/sample/core.clj b/test/spec/fixtures/repos/lein-1.x/source/sample/core.clj similarity index 100% rename from test/spec/fixtures/repos/lein-1-jdk-8/source/sample/core.clj rename to test/spec/fixtures/repos/lein-1.x/source/sample/core.clj diff --git a/test/spec/fixtures/repos/cljs-lein-npm-example/system.properties b/test/spec/fixtures/repos/lein-1.x/system.properties similarity index 100% rename from test/spec/fixtures/repos/cljs-lein-npm-example/system.properties rename to test/spec/fixtures/repos/lein-1.x/system.properties diff --git a/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/project.clj b/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/project.clj deleted file mode 100644 index c3b9f40..0000000 --- a/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/project.clj +++ /dev/null @@ -1,17 +0,0 @@ -(defproject clojure-getting-started "1.0.0-SNAPSHOT" - :description "Demo Clojure web app" - :url "http://clojure-getting-started.herokuapp.com" - :license {:name "Eclipse Public License v1.0" - :url "http://www.eclipse.org/legal/epl-v10.html"} - :repositories [["central-https" {:url "https://repo1.maven.org/maven2"}] - ["clojars-https" {:url "https://clojars.org/repo/"}]] - :omit-default-repositories true - :dependencies [[org.clojure/clojure "1.6.0"] - [compojure "1.1.8"] - [ring/ring-jetty-adapter "1.2.2"] - [environ "0.5.0"]] - :min-lein-version "2.0.0" - :plugins [[environ/environ.lein "0.2.1"]] - :hooks [environ.leiningen.hooks] - :uberjar-name "clojure-getting-started-standalone.jar" - :profiles {:production {:env {:production true}}}) diff --git a/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/source/sample/core.clj b/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/source/sample/core.clj deleted file mode 100644 index e495caf..0000000 --- a/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/source/sample/core.clj +++ /dev/null @@ -1,5 +0,0 @@ -(ns sample.core - (:gen-class)) - -(defn -main [& args] - (println "Welcome to my project! These are your args:" args)) diff --git a/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/system.properties b/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/system.properties deleted file mode 100644 index c53c29f..0000000 --- a/test/spec/fixtures/repos/lein-2-jdk-8-uberjar/system.properties +++ /dev/null @@ -1 +0,0 @@ -java.runtime.version=zulu-8 diff --git a/test/spec/fixtures/repos/lein-2-jdk-8/project.clj b/test/spec/fixtures/repos/lein-2-jdk-8/project.clj deleted file mode 100644 index 1d6e073..0000000 --- a/test/spec/fixtures/repos/lein-2-jdk-8/project.clj +++ /dev/null @@ -1,13 +0,0 @@ -(defproject sample "0.1.0-SNAPSHOT" - :description "FIXME: write description" - :url "http://example.com/FIXME" - :license {:name "Eclipse Public License" - :repositories [["central-https" {:url "https://repo1.maven.org/maven2"}] - ["clojars-https" {:url "https://clojars.org/repo/"}]] - :omit-default-repositories true - :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.5.1"]] - :min-lein-version "2.0.0" - :main ^:skip-aot sample.core - :target-path "target/%s" - :profiles {:uberjar {:aot :all}}) diff --git a/test/spec/fixtures/repos/lein-2-jdk-8/source/sample/core.clj b/test/spec/fixtures/repos/lein-2-jdk-8/source/sample/core.clj deleted file mode 100644 index e495caf..0000000 --- a/test/spec/fixtures/repos/lein-2-jdk-8/source/sample/core.clj +++ /dev/null @@ -1,5 +0,0 @@ -(ns sample.core - (:gen-class)) - -(defn -main [& args] - (println "Welcome to my project! These are your args:" args)) diff --git a/test/spec/fixtures/repos/lein-2-jdk-8/system.properties b/test/spec/fixtures/repos/lein-2-jdk-8/system.properties deleted file mode 100644 index c53c29f..0000000 --- a/test/spec/fixtures/repos/lein-2-jdk-8/system.properties +++ /dev/null @@ -1 +0,0 @@ -java.runtime.version=zulu-8 diff --git a/test/spec/fixtures/repos/lein-2.x-no-uberjar/.gitignore b/test/spec/fixtures/repos/lein-2.x-no-uberjar/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-no-uberjar/.gitignore @@ -0,0 +1 @@ +target diff --git a/test/spec/fixtures/repos/lein-2.x-no-uberjar/project.clj b/test/spec/fixtures/repos/lein-2.x-no-uberjar/project.clj new file mode 100644 index 0000000..2bb54ac --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-no-uberjar/project.clj @@ -0,0 +1,10 @@ +(defproject heroku-minimal-clojure "0.1.0" + :description "A minimal Clojure HTTP application" + :dependencies [[org.clojure/clojure "1.12.3"] + [ring/ring-core "1.9.6"] + [ring/ring-jetty-adapter "1.9.6"] + [ring/ring-defaults "0.3.4"] + [compojure "1.7.0"]] + :main com.heroku.ci.core + :aot [com.heroku.ci.core] + :min-lein-version "2.0.0") diff --git a/test/spec/fixtures/repos/lein-2.x-no-uberjar/src/com/heroku/ci/core.clj b/test/spec/fixtures/repos/lein-2.x-no-uberjar/src/com/heroku/ci/core.clj new file mode 100644 index 0000000..b7ef7b5 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-no-uberjar/src/com/heroku/ci/core.clj @@ -0,0 +1,17 @@ +(ns com.heroku.ci.core + (:require [compojure.core :refer [defroutes GET]] + [compojure.route :as route] + [ring.adapter.jetty :refer [run-jetty]] + [ring.middleware.defaults :refer [wrap-defaults api-defaults]]) + (:gen-class)) + +(defroutes app-routes + (GET "/" [] "Hello from Clojure!") + (route/not-found "Not Found")) + +(def app + (wrap-defaults app-routes api-defaults)) + +(defn -main [] + (let [port (Integer/parseInt (System/getenv "PORT"))] + (run-jetty app {:port port :join? false}))) diff --git a/test/spec/fixtures/repos/lein-2.x-no-uberjar/system.properties b/test/spec/fixtures/repos/lein-2.x-no-uberjar/system.properties new file mode 100644 index 0000000..cc7c9d7 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-no-uberjar/system.properties @@ -0,0 +1 @@ +java.runtime.version=25 diff --git a/test/spec/fixtures/repos/lein-2.x-no-uberjar/test/com/heroku/ci/core_test.clj b/test/spec/fixtures/repos/lein-2.x-no-uberjar/test/com/heroku/ci/core_test.clj new file mode 100644 index 0000000..2d860dc --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-no-uberjar/test/com/heroku/ci/core_test.clj @@ -0,0 +1,11 @@ +(ns com.heroku.ci.core-test + (:require [clojure.test :refer :all] + [com.heroku.ci.core :refer :all])) + +(deftest addition-test + (testing "Basic arithmetic" + (is (= 4 (+ 2 2))))) + +(deftest subtraction-test + (testing "Subtraction works" + (is (= 0 (- 2 2))))) \ No newline at end of file diff --git a/test/spec/fixtures/repos/lein-2.x-with-lein-npm/.gitignore b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/.gitignore @@ -0,0 +1 @@ +target diff --git a/test/spec/fixtures/repos/lein-2.x-with-lein-npm/project.clj b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/project.clj new file mode 100644 index 0000000..e559b8b --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/project.clj @@ -0,0 +1,11 @@ +(defproject heroku-minimal-clojure "0.1.0" + :description "A minimal Clojure HTTP application with lein-npm" + :dependencies [[org.clojure/clojure "1.12.3"] + [ring/ring-core "1.9.6"] + [ring/ring-jetty-adapter "1.9.6"] + [ring/ring-defaults "0.3.4"] + [compojure "1.7.0"]] + :plugins [[lein-npm "0.6.2"]] + :main com.heroku.ci.core + :aot [com.heroku.ci.core] + :min-lein-version "2.0.0") diff --git a/test/spec/fixtures/repos/lein-2.x-with-lein-npm/src/com/heroku/ci/core.clj b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/src/com/heroku/ci/core.clj new file mode 100644 index 0000000..bf710c1 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/src/com/heroku/ci/core.clj @@ -0,0 +1,17 @@ +(ns com.heroku.ci.core + (:require [compojure.core :refer [defroutes GET]] + [compojure.route :as route] + [ring.adapter.jetty :refer [run-jetty]] + [ring.middleware.defaults :refer [wrap-defaults api-defaults]]) + (:gen-class)) + +(defroutes app-routes + (GET "/" [] "Hello from Clojure with lein-npm!") + (route/not-found "Not Found")) + +(def app + (wrap-defaults app-routes api-defaults)) + +(defn -main [] + (let [port (Integer/parseInt (System/getenv "PORT"))] + (run-jetty app {:port port :join? false}))) diff --git a/test/spec/fixtures/repos/lein-2.x-with-lein-npm/system.properties b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/system.properties new file mode 100644 index 0000000..cc7c9d7 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/system.properties @@ -0,0 +1 @@ +java.runtime.version=25 diff --git a/test/spec/fixtures/repos/lein-2.x-with-lein-npm/test/com/heroku/ci/core_test.clj b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/test/com/heroku/ci/core_test.clj new file mode 100644 index 0000000..26c274d --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-lein-npm/test/com/heroku/ci/core_test.clj @@ -0,0 +1,11 @@ +(ns com.heroku.ci.core-test + (:require [clojure.test :refer :all] + [com.heroku.ci.core :refer :all])) + +(deftest addition-test + (testing "Basic arithmetic" + (is (= 4 (+ 2 2))))) + +(deftest subtraction-test + (testing "Subtraction works" + (is (= 0 (- 2 2))))) diff --git a/test/spec/fixtures/repos/lein-2.x-with-uberjar/.gitignore b/test/spec/fixtures/repos/lein-2.x-with-uberjar/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-uberjar/.gitignore @@ -0,0 +1 @@ +target diff --git a/test/spec/fixtures/repos/lein-2.x-with-uberjar/project.clj b/test/spec/fixtures/repos/lein-2.x-with-uberjar/project.clj new file mode 100644 index 0000000..3bd1068 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-uberjar/project.clj @@ -0,0 +1,11 @@ +(defproject heroku-minimal-clojure "0.1.0" + :description "A minimal Clojure HTTP application" + :dependencies [[org.clojure/clojure "1.12.3"] + [ring/ring-core "1.9.6"] + [ring/ring-jetty-adapter "1.9.6"] + [ring/ring-defaults "0.3.4"] + [compojure "1.7.0"]] + :main com.heroku.ci.core + :aot [com.heroku.ci.core] + :uberjar-name "app-standalone.jar" + :min-lein-version "2.0.0") diff --git a/test/spec/fixtures/repos/lein-2.x-with-uberjar/src/com/heroku/ci/core.clj b/test/spec/fixtures/repos/lein-2.x-with-uberjar/src/com/heroku/ci/core.clj new file mode 100644 index 0000000..b7ef7b5 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-uberjar/src/com/heroku/ci/core.clj @@ -0,0 +1,17 @@ +(ns com.heroku.ci.core + (:require [compojure.core :refer [defroutes GET]] + [compojure.route :as route] + [ring.adapter.jetty :refer [run-jetty]] + [ring.middleware.defaults :refer [wrap-defaults api-defaults]]) + (:gen-class)) + +(defroutes app-routes + (GET "/" [] "Hello from Clojure!") + (route/not-found "Not Found")) + +(def app + (wrap-defaults app-routes api-defaults)) + +(defn -main [] + (let [port (Integer/parseInt (System/getenv "PORT"))] + (run-jetty app {:port port :join? false}))) diff --git a/test/spec/fixtures/repos/lein-2.x-with-uberjar/system.properties b/test/spec/fixtures/repos/lein-2.x-with-uberjar/system.properties new file mode 100644 index 0000000..cc7c9d7 --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-uberjar/system.properties @@ -0,0 +1 @@ +java.runtime.version=25 diff --git a/test/spec/fixtures/repos/lein-2.x-with-uberjar/test/com/heroku/ci/core_test.clj b/test/spec/fixtures/repos/lein-2.x-with-uberjar/test/com/heroku/ci/core_test.clj new file mode 100644 index 0000000..26c274d --- /dev/null +++ b/test/spec/fixtures/repos/lein-2.x-with-uberjar/test/com/heroku/ci/core_test.clj @@ -0,0 +1,11 @@ +(ns com.heroku.ci.core-test + (:require [clojure.test :refer :all] + [com.heroku.ci.core :refer :all])) + +(deftest addition-test + (testing "Basic arithmetic" + (is (= 4 (+ 2 2))))) + +(deftest subtraction-test + (testing "Subtraction works" + (is (= 0 (- 2 2))))) diff --git a/test/spec/fixtures/repos/non-clojure-app/README.md b/test/spec/fixtures/repos/non-clojure-app/README.md new file mode 100644 index 0000000..2934dfa --- /dev/null +++ b/test/spec/fixtures/repos/non-clojure-app/README.md @@ -0,0 +1,4 @@ +# Non-Clojure App + +This is a test fixture that does not contain a project.clj file. +Used to test detection failure scenarios. diff --git a/test/spec/lein_1_spec.rb b/test/spec/lein_1_spec.rb new file mode 100644 index 0000000..2854c0e --- /dev/null +++ b/test/spec/lein_1_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require_relative 'spec_helper' + +describe 'Leiningen 1.x' do + it 'works with lein 1.x' do + new_default_hatchet_runner('lein-1.x').tap do |app| + app.deploy do + expect(clean_output(app.output)).to eq(<<~OUTPUT) + remote: -----> Clojure app detected + remote: -----> Installing Azul Zulu OpenJDK $VERSION + remote: -----> Installing Clojure 1.10.0.411 CLI tools + remote: Downloading and expanding tar + remote: Installing libs into $BUILD_DIR/.heroku/clj/lib/clojure + remote: Installing clojure and clj into $BUILD_DIR/.heroku/clj/bin + remote: Installing man pages into $BUILD_DIR/.heroku/clj/share/man/man1 + remote: Removing download + remote: Use clj -h for help. + + remote: ! WARNING: No :min-lein-version found in project.clj; using 1.7.1. + remote: You probably don't want this! + + remote: -----> Installing Leiningen + remote: Downloading: leiningen-1.7.1-standalone.jar + remote: To use Leiningen 2.x, add this to project.clj: :min-lein-version "2.0.0" + remote: Writing: lein script + remote: -----> Building with Leiningen + remote: Running: lein deps + remote: Downloading: org/clojure/clojure/1.5.1/clojure-1.5.1.pom from repository central-https at https://repo1.maven.org/maven2 + remote: Downloading: org/sonatype/oss/oss-parent/5/oss-parent-5.pom from repository central-https at https://repo1.maven.org/maven2 + remote: Downloading: org/clojure/clojure/1.5.1/clojure-1.5.1.jar from repository central-https at https://repo1.maven.org/maven2 + remote: Transferring 3501K from central-https + remote: Copying 1 file to $BUILD_DIR/lib + remote: -----> Discovering process types + remote: Procfile declares types -> (none) + remote: Default types for buildpack -> web + + remote: -----> Compressing... + remote: Done: 82.1M + OUTPUT + end + end + end +end diff --git a/test/spec/lein_npm_spec.rb b/test/spec/lein_npm_spec.rb new file mode 100644 index 0000000..2493a63 --- /dev/null +++ b/test/spec/lein_npm_spec.rb @@ -0,0 +1,203 @@ +# frozen_string_literal: true + +require_relative 'spec_helper' + +RSpec.describe 'Clojure buildpack' do + it 'installs Node.js when lein-npm is detected' do + new_default_hatchet_runner('lein-2.x-with-lein-npm').tap do |app| + app.deploy do + # Verify Node.js installation + expect(clean_output(app.output)).to include('-----> Installing Node.js 18.16.0...') + expect(clean_output(app.output)).to include('Downloading Node.js 18.16.0...') + + # Verify correct build task for lein-npm + expect(clean_output(app.output)).to include('Running: lein with-profile production do deps, compile :all') + + # Verify successful deployment + expect(app).to be_deployed + end + end + end + + it 'installs Node.js when lein-npm is detected (full output match)' do + new_default_hatchet_runner('lein-2.x-with-lein-npm').tap do |app| + app.deploy do + expect(clean_output(app.output)).to match(<<~OUTPUT) + remote: -----> Clojure (Leiningen 2) app detected + remote: -----> Installing Azul Zulu OpenJDK $VERSION + remote: -----> Installing Node.js 18.16.0... + remote: Downloading Node.js 18.16.0... + remote: -----> Installing Clojure 1.10.0.411 CLI tools + remote: Downloading and expanding tar + remote: Installing libs into $BUILD_DIR/.heroku/clj/lib/clojure + remote: Installing clojure and clj into $BUILD_DIR/.heroku/clj/bin + remote: Installing man pages into $BUILD_DIR/.heroku/clj/share/man/man1 + remote: Removing download + remote: Use clj -h for help. + remote: -----> Installing Leiningen + remote: Downloading: leiningen-2.9.1-standalone.jar + remote: Writing: lein script + remote: -----> Building with Leiningen + remote: Running: lein with-profile production do deps, compile :all + remote: Downloading Leiningen to /app/.lein/self-installs/leiningen-2.9.1-standalone.jar now... + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Warning: implicit hook found: lein-npm.plugin/hooks + remote: Hooks are deprecated and will be removed in a future version. + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: Retrieving $DEPENDENCY from $REPO + remote: + remote: up to date, audited $NUM packages in $TIME + remote: + remote: found 0 vulnerabilities + remote: Compiling com.heroku.ci.core + remote: $TIMESTAMP:INFO::main: Logging initialized @$TIMEms to org.eclipse.jetty.util.log.StdErrLog + remote: -----> Discovering process types + remote: Procfile declares types -> (none) + remote: Default types for buildpack -> web + + remote: -----> Compressing... + remote: Done: 171.2M + OUTPUT + end + end + end + + it 'respects NODEJS_VERSION environment variable' do + new_default_hatchet_runner('lein-2.x-with-lein-npm').tap do |app| + app.before_deploy do + app.set_config('NODEJS_VERSION' => '20.10.0') + end + + app.deploy do + # Verify custom Node.js version is installed + expect(clean_output(app.output)).to include('-----> Installing Node.js 20.10.0') + expect(clean_output(app.output)).to include('Downloading Node.js 20.10.0') + + # Verify successful deployment + expect(app).to be_deployed + end + end + end + + it 'skips Node.js installation when SKIP_NODEJS_INSTALL is set' do + new_default_hatchet_runner('lein-2.x-with-lein-npm', allow_failure: true).tap do |app| + app.before_deploy do + app.set_config('SKIP_NODEJS_INSTALL' => 'true') + end + + app.deploy do + # Verify Node.js installation is skipped + expect(clean_output(app.output)).not_to include('-----> Installing Node.js') + expect(clean_output(app.output)).not_to include('Downloading Node.js') + end + end + end +end diff --git a/test/spec/runtime_spec.rb b/test/spec/runtime_spec.rb new file mode 100644 index 0000000..b38c346 --- /dev/null +++ b/test/spec/runtime_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require_relative 'spec_helper' + +RSpec.describe 'Clojure buildpack runtime' do + it 'makes clj and lein available at runtime' do + new_default_hatchet_runner('lein-2.x-no-uberjar').tap do |app| + app.deploy do + expect(app).to be_deployed + + # Verify clj is available and works + clj_output = app.run('clj -e \'(println "Clojure works")\'') + expect(clj_output).to eq(<<~OUTPUT) + Warning: Using minimal rlwrap replacement. Command history and line editing are not available. + To enable full readline support, add the APT buildpack and create an Aptfile: + + 1. heroku buildpacks:add --index 1 heroku-community/apt + 2. echo "rlwrap" > Aptfile + 3. git add Aptfile && git commit -m "Add rlwrap support" + 4. git push heroku main + + Downloading: org/clojure/clojure/1.10.0/clojure-1.10.0.pom from https://repo1.maven.org/maven2/ + Downloading: org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.pom from https://repo1.maven.org/maven2/ + Downloading: org/clojure/core.specs.alpha/0.2.44/core.specs.alpha-0.2.44.pom from https://repo1.maven.org/maven2/ + Downloading: org/clojure/clojure/1.10.0/clojure-1.10.0.jar from https://repo1.maven.org/maven2/ + Downloading: org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.jar from https://repo1.maven.org/maven2/ + Downloading: org/clojure/core.specs.alpha/0.2.44/core.specs.alpha-0.2.44.jar from https://repo1.maven.org/maven2/ + Clojure works + OUTPUT + + # Verify lein is available + lein_output = app.run('lein version') + expect(lein_output).to match(/Downloading Leiningen to \/app\/\.lein\/self-installs\/leiningen-\d+\.\d+\.\d+-standalone\.jar now\.\.\./) + expect(lein_output).to match(/Leiningen \d+\.\d+\.\d+ on Java \d+\.\d+\.\d+ OpenJDK 64-Bit Server VM/) + end + end + end +end diff --git a/test/spec/spec_helper.rb b/test/spec/spec_helper.rb index 44a62b1..b884885 100644 --- a/test/spec/spec_helper.rb +++ b/test/spec/spec_helper.rb @@ -6,8 +6,6 @@ require 'hatchet' require 'java-properties' -DEFAULT_OPENJDK_VERSION = '1.8' - RSpec.configure do |config| config.fail_if_no_examples = true config.full_backtrace = true @@ -30,23 +28,6 @@ def new_default_hatchet_runner(*args, **kwargs) Hatchet::Runner.new(*args, **kwargs) end -def java_version(version_string) - set_system_properties_key('java.runtime.version', version_string) -end - -def maven_version(version_string) - set_system_properties_key('maven.version', version_string) -end - -def set_system_properties_key(key, value) - properties = {} - - properties = JavaProperties.load('system.properties') if File.file?('system.properties') - - properties[key.to_sym] = value - JavaProperties.write(properties, 'system.properties') -end - def write_to_procfile(content) File.write('Procfile', content) end @@ -62,5 +43,75 @@ def http_get(app, options = {}) retry_limit = options[:retry_limit] || 50 path = options[:path] ? "/#{options[:path]}" : '' Excon.get("#{app.platform_api.app.info(app.name).fetch('web_url')}#{path}", idempotent: true, expects: 200, - retry_limit: retry_limit).body + retry_limit: retry_limit).body +end + +def find_output_start_index(lines) + # Find the first "app detected" line. This skips the buildpack list at the beginning which will contain a GitHub URL + # for the buildpack under test that will be different for each PR/branch under test. + # For detection failures, look for the "App not compatible" line instead. + lines.index { |line| line.match?(/-----> .* app detected|-----> App not compatible with buildpack/) } +end + +def find_output_end_index(lines) + # Find the end of relevant build output. For successful builds, this is the "Done: 12.3M" line after compression. + # For failed builds, this is the "Push failed" line. This skips build-system output after these lines that is + # irrelevant for our tests and changes for each deploy. + success_end_index = lines.index { |line| line.match?(/Done: \d+(\.\d+)?[MG]/) } + failure_end_index = lines.index { |line| line.match?(/!\s+Push failed/) } + [success_end_index, failure_end_index].compact.first +end + +def clean_output(output) + # Remove output from the build system before and after the actual build + lines = output.lines + output = lines[find_output_start_index(lines)..find_output_end_index(lines)].join + + generic = { + ################################################## + # Generic + ################################################## + # Trailing whitespace characters added by Git: + # https://github.com/heroku/hatchet/issues/162 + / {8}(?=\R)/ => '', + # ANSI colour codes used in buildpack output (e.g. error messages). + /\e\[[0-9;]+m/ => '', + # Trailing spaces from empty "remote: " lines added by Heroku + /^remote: $/ => '', + /remote: Released v\d+/ => 'remote: Released $VERSION', + # Build directory + %r{/tmp/build_[0-9a-f]{8}} => '$BUILD_DIR', + # Build id + /build_[0-9a-f]{8}/ => '$BUILD_ID', + # Buildpack URL in detection failure message + %r{https://github\.com/heroku/heroku-buildpack-clojure#[\w\-/]+} => '$BUILDPACK_URL', + + ################################################## + # Java + ################################################## + /(OpenJDK|Java) \d+\.\d+\.\d+(_\d+)?/ => '\1 $VERSION', + + ################################################## + # Clojure / Leiningen + ################################################## + # Maven/Leiningen dependency retrieval (normalize non-deterministic download order) + /Retrieving [\w\/\.\-]+\.(pom|jar) from \w+/ => 'Retrieving $DEPENDENCY from $REPO', + # Jetty logging timestamp + /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+:INFO::main: Logging initialized @\d+ms/ => '$TIMESTAMP:INFO::main: Logging initialized @$TIMEms', + + ################################################## + # npm + ################################################## + # npm audit timing + /up to date, audited \d+ packages? in \d+m?s/ => 'up to date, audited $NUM packages in $TIME', + } + + output = generic.reduce(output) { |output, (pattern, replacement)| output.gsub(pattern, replacement) } + + # Save the cleaned output to disk so it can be copied byte-for-byte when writing or updating test expectations. + # Copying from terminal output can introduce issues (especially with whitespace output). Writing this file every time + # is inexpensive and ensures it's always available when needed. + File.write('/tmp/clojure_buildpack_integration_last_test_output.txt', output) + + output end