diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..79559ff9 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,77 @@ +version: 2 +jobs: + build: + working_directory: ~/themarshallproject/klaxon + parallelism: 1 + docker: + # Includes ruby, node, and chrome/phantomjs + # TODO: Go back to the non-legacy version of this image, when our test + # infrastructure no longer depends on phantomjs + - image: circleci/ruby:2.4 # ...with this image as the primary container; this is where all `steps` will run + environment: # environment variables for primary container + BUNDLE_JOBS: 3 + BUNDLE_RETRY: 3 + BUNDLE_PATH: vendor/bundle + PGHOST: 127.0.0.1 + PGUSER: klaxon-test-user + RAILS_ENV: test + RACK_ENV: test + NODE_ENV: test + - image: circleci/postgres:9.5-alpine # database image + environment: # environment variables for database + POSTGRES_USER: klaxon-test-user + POSTGRES_DB: klaxon_test + POSTGRES_PASSWORD: "" + steps: + # Check out the repo + - checkout + + # Dependencies + # Which version of bundler? + - run: + name: Which bundler? + command: bundle -v + + # Restore the dependency cache + - restore_cache: + keys: + - klaxon-v2-{{ checksum "Gemfile.lock" }}- + - klaxon-v2- + + - run: + name: Bundle Install + command: bundle check || bundle install + + # Store bundle cache + - save_cache: + key: klaxon-v2-{{ checksum "Gemfile.lock" }}- + paths: + - vendor/bundle + + - run: + name: Compile assets + command: bundle exec rake assets:precompile assets:clean + environment: + RAILS_GROUPS: assets + + - run: + name: Wait for DB + command: dockerize -wait tcp://localhost:5432 -timeout 1m + + - run: + command: bundle exec rake db:create db:schema:load --trace + environment: + RAILS_ENV: test + RACK_ENV: test + + - run: + name: Make results directory + command: mkdir -p test-results/rspec/ + + - run: + name: Run the tests + command: bundle exec rspec -r rspec_junit_formatter --format RspecJunitFormatter -o test-results/rspec/rspec.xml + + # Save test results for reporting in the UI + - store_test_results: + path: test-results diff --git a/.ruby-version b/.ruby-version index 3f684d2d..79a61441 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.3.4 +2.4.4 diff --git a/Gemfile b/Gemfile index 2dc6736b..0422b4c6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,8 +1,8 @@ source 'https://rubygems.org' -ruby '2.3.4' +ruby '2.4.4' -gem 'rails', '~> 4.2' -gem 'pg', '~> 0.15' +gem 'rails', '~> 5.2.1' +gem 'pg', '~> 0.21' gem 'sass-rails', '~> 5.0' gem 'uglifier', '>= 1.3.0' gem 'therubyracer' @@ -10,14 +10,16 @@ gem 'therubyracer' gem 'dotenv' gem 'jquery-rails' gem 'turbolinks' -gem 'sdoc', '~> 0.4.0', group: :doc +gem 'bootsnap', require: false +gem 'coffee-rails' +gem 'sdoc', '~> 1.0.0', group: :doc gem 'rack-cache' -gem 'bcrypt', '~> 3.1.7' -gem 'puma', '~> 3.2' +gem 'bcrypt', '~> 3.1.12' +gem 'puma', '~> 3.12' gem 'rails_12factor' -gem 'simple_form', '~> 3.2' +gem 'simple_form', '~> 4.0' gem 'jwt' gem 'premailer-rails' @@ -26,25 +28,26 @@ gem 'httparty' gem 'diffy' gem 'kramdown' -# only used for alerting SQS. -gem 'aws-sdk', '~> 2.0' +gem 'aws-sdk-sqs', '~> 1.6' group :development, :test do gem 'byebug' - gem 'rspec-rails', '~> 3.0' + gem 'rspec-rails', '~> 3.8' gem 'guard-rspec', require: false - gem 'factory_girl_rails', '~> 4.0' + gem 'factory_bot_rails', '~> 4.11' gem 'database_cleaner' gem 'sinatra' end group :test do gem 'webmock' + gem 'rails-controller-testing' + gem 'rspec_junit_formatter' gem 'codeclimate-test-reporter', require: nil end group :development do gem 'letter_opener' - gem 'web-console', '~> 2.0' + gem 'web-console', '~> 3.7' gem 'spring' end diff --git a/Gemfile.lock b/Gemfile.lock index d07510cc..a99c1d54 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,122 +1,132 @@ GEM remote: https://rubygems.org/ specs: - actionmailer (4.2.10) - actionpack (= 4.2.10) - actionview (= 4.2.10) - activejob (= 4.2.10) + actioncable (5.2.1) + actionpack (= 5.2.1) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.10) - actionview (= 4.2.10) - activesupport (= 4.2.10) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) + rails-dom-testing (~> 2.0) + actionpack (5.2.1) + actionview (= 5.2.1) + activesupport (= 5.2.1) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.10) - activesupport (= 4.2.10) + actionview (5.2.1) + activesupport (= 5.2.1) builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (4.2.10) - activesupport (= 4.2.10) - globalid (>= 0.3.0) - activemodel (4.2.10) - activesupport (= 4.2.10) - builder (~> 3.1) - activerecord (4.2.10) - activemodel (= 4.2.10) - activesupport (= 4.2.10) - arel (~> 6.0) - activesupport (4.2.10) - i18n (~> 0.7) + activejob (5.2.1) + activesupport (= 5.2.1) + globalid (>= 0.3.6) + activemodel (5.2.1) + activesupport (= 5.2.1) + activerecord (5.2.1) + activemodel (= 5.2.1) + activesupport (= 5.2.1) + arel (>= 9.0) + activestorage (5.2.1) + actionpack (= 5.2.1) + activerecord (= 5.2.1) + marcel (~> 0.3.1) + activesupport (5.2.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - addressable (2.4.0) - arel (6.0.4) - aws-sdk (2.6.26) - aws-sdk-resources (= 2.6.26) - aws-sdk-core (2.6.26) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + arel (9.0.0) + aws-eventstream (1.0.1) + aws-partitions (1.103.0) + aws-sdk-core (3.27.0) + aws-eventstream (~> 1.0) + aws-partitions (~> 1.0) aws-sigv4 (~> 1.0) jmespath (~> 1.0) - aws-sdk-resources (2.6.26) - aws-sdk-core (= 2.6.26) - aws-sigv4 (1.0.0) - bcrypt (3.1.11) - binding_of_caller (0.7.2) - debug_inspector (>= 0.0.1) + aws-sdk-sqs (1.6.0) + aws-sdk-core (~> 3, >= 3.26.0) + aws-sigv4 (~> 1.0) + aws-sigv4 (1.0.3) + bcrypt (3.1.12) + bindex (0.5.0) + bootsnap (1.3.2) + msgpack (~> 1.0) builder (3.2.3) - byebug (9.0.5) + byebug (10.0.2) codeclimate-test-reporter (0.5.2) simplecov (>= 0.7.1, < 1.0.0) - coderay (1.1.1) - coffee-rails (4.1.1) + coderay (1.1.2) + coffee-rails (4.2.2) coffee-script (>= 2.2.0) - railties (>= 4.0.0, < 5.1.x) + railties (>= 4.0.0) coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.10.0) + coffee-script-source (1.12.2) concurrent-ruby (1.0.5) crack (0.4.3) safe_yaml (~> 1.0.0) crass (1.0.4) - css_parser (1.4.2) + css_parser (1.6.0) addressable - database_cleaner (1.5.3) - debug_inspector (0.0.2) - diff-lcs (1.2.5) - diffy (3.1.0) + database_cleaner (1.7.0) + diff-lcs (1.3) + diffy (3.2.1) docile (1.1.5) - dotenv (2.1.1) - erubis (2.7.0) + dotenv (2.5.0) + erubi (1.7.1) execjs (2.7.0) - factory_girl (4.7.0) + factory_bot (4.11.1) activesupport (>= 3.0.0) - factory_girl_rails (4.7.0) - factory_girl (~> 4.7.0) + factory_bot_rails (4.11.1) + factory_bot (~> 4.11.1) railties (>= 3.0.0) - ffi (1.9.10) + ffi (1.9.25) formatador (0.2.5) globalid (0.4.1) activesupport (>= 4.2.0) - guard (2.14.0) + guard (2.14.2) formatador (>= 0.2.4) listen (>= 2.7, < 4.0) - lumberjack (~> 1.0) + lumberjack (>= 1.0.12, < 2.0) nenv (~> 0.1) notiffany (~> 0.0) pry (>= 0.9.12) shellany (~> 0.0) thor (>= 0.18.1) guard-compat (1.2.1) - guard-rspec (4.7.2) + guard-rspec (4.7.3) guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) - hashdiff (0.3.0) + hashdiff (0.3.7) htmlentities (4.3.4) - httparty (0.13.7) - json (~> 1.8) + httparty (0.16.2) multi_xml (>= 0.5.2) - i18n (0.9.4) + i18n (1.1.0) concurrent-ruby (~> 1.0) - jmespath (1.3.1) - jquery-rails (4.1.1) + jmespath (1.4.0) + jquery-rails (4.3.3) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (1.8.6) - jwt (1.5.4) - kramdown (1.11.1) + jwt (2.1.0) + kramdown (1.17.0) launchy (2.4.3) addressable (~> 2.3) - letter_opener (1.4.1) + letter_opener (1.6.0) launchy (~> 2.2) - libv8 (3.16.14.15) + libv8 (3.16.14.19) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -124,56 +134,66 @@ GEM loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) - lumberjack (1.0.10) + lumberjack (1.0.13) mail (2.7.0) mini_mime (>= 0.1.1) - method_source (0.8.2) - mini_mime (1.0.0) + marcel (0.3.2) + mimemagic (~> 0.3.2) + method_source (0.9.0) + mimemagic (0.3.2) + mini_mime (1.0.1) mini_portile2 (2.3.0) minitest (5.11.3) - multi_xml (0.5.5) + msgpack (1.2.4) + multi_xml (0.6.0) + mustermann (1.0.3) nenv (0.3.0) - nokogiri (1.8.2) + nio4r (2.3.1) + nokogiri (1.8.4) mini_portile2 (~> 2.3.0) - notiffany (0.1.0) + notiffany (0.1.1) nenv (~> 0.1) shellany (~> 0.0) - pg (0.18.4) - premailer (1.8.6) - css_parser (>= 1.3.6) + pg (0.21.0) + premailer (1.11.1) + addressable + css_parser (>= 1.6.0) htmlentities (>= 4.0.0) - premailer-rails (1.9.3) + premailer-rails (1.10.2) actionmailer (>= 3, < 6) premailer (~> 1.7, >= 1.7.9) - pry (0.10.3) + pry (0.11.3) coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - puma (3.4.0) - rack (1.6.10) - rack-cache (1.6.1) + method_source (~> 0.9.0) + public_suffix (3.0.3) + puma (3.12.0) + rack (2.0.5) + rack-cache (1.8.0) rack (>= 0.4) - rack-protection (1.5.5) + rack-protection (2.0.4) rack - rack-test (0.6.3) - rack (>= 1.0) - rails (4.2.10) - actionmailer (= 4.2.10) - actionpack (= 4.2.10) - actionview (= 4.2.10) - activejob (= 4.2.10) - activemodel (= 4.2.10) - activerecord (= 4.2.10) - activesupport (= 4.2.10) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.10) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.9) - activesupport (>= 4.2.0, < 5.0) - nokogiri (~> 1.6) - rails-deprecated_sanitizer (>= 1.0.1) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.1) + actioncable (= 5.2.1) + actionmailer (= 5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) + activemodel (= 5.2.1) + activerecord (= 5.2.1) + activestorage (= 5.2.1) + activesupport (= 5.2.1) + bundler (>= 1.3.0) + railties (= 5.2.1) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) rails_12factor (0.0.3) @@ -181,66 +201,72 @@ GEM rails_stdout_logging rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (4.2.10) - actionpack (= 4.2.10) - activesupport (= 4.2.10) + railties (5.2.1) + actionpack (= 5.2.1) + activesupport (= 5.2.1) + method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rake (12.3.0) - rb-fsevent (0.9.7) - rb-inotify (0.9.7) - ffi (>= 0.5.0) - rdoc (4.2.2) - json (~> 1.4) + thor (>= 0.19.0, < 2.0) + rake (12.3.1) + rb-fsevent (0.10.3) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + rdoc (6.0.4) ref (2.0.0) - rspec (3.4.0) - rspec-core (~> 3.4.0) - rspec-expectations (~> 3.4.0) - rspec-mocks (~> 3.4.0) - rspec-core (3.4.4) - rspec-support (~> 3.4.0) - rspec-expectations (3.4.0) + rspec (3.8.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-core (3.8.0) + rspec-support (~> 3.8.0) + rspec-expectations (3.8.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-mocks (3.4.1) + rspec-support (~> 3.8.0) + rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-rails (3.4.2) - actionpack (>= 3.0, < 4.3) - activesupport (>= 3.0, < 4.3) - railties (>= 3.0, < 4.3) - rspec-core (~> 3.4.0) - rspec-expectations (~> 3.4.0) - rspec-mocks (~> 3.4.0) - rspec-support (~> 3.4.0) - rspec-support (3.4.1) - ruby_dep (1.3.1) + rspec-support (~> 3.8.0) + rspec-rails (3.8.0) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-support (~> 3.8.0) + rspec-support (3.8.0) + rspec_junit_formatter (0.4.1) + rspec-core (>= 2, < 4, != 2.12.0) + ruby_dep (1.5.0) safe_yaml (1.0.4) - sass (3.4.22) - sass-rails (5.0.4) - railties (>= 4.0.0, < 5.0) + sass (3.5.7) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - sdoc (0.4.1) - json (~> 1.7, >= 1.7.7) - rdoc (~> 4.0) + sdoc (1.0.0) + rdoc (>= 5.0) shellany (0.0.1) - simple_form (3.2.1) - actionpack (> 4, < 5.1) - activemodel (> 4, < 5.1) + simple_form (4.0.1) + actionpack (>= 5.0) + activemodel (>= 5.0) simplecov (0.11.2) docile (~> 1.1.0) json (~> 1.8) simplecov-html (~> 0.10.0) simplecov-html (0.10.0) - sinatra (1.4.7) - rack (~> 1.5) - rack-protection (~> 1.4) - tilt (>= 1.3, < 3) - slop (3.6.0) - spring (1.7.1) + sinatra (2.0.4) + mustermann (~> 1.0) + rack (~> 2.0) + rack-protection (= 2.0.4) + tilt (~> 2.0) + spring (2.0.2) + activesupport (>= 4.2) sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) @@ -248,66 +274,74 @@ GEM actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - therubyracer (0.12.2) - libv8 (~> 3.16.14.0) + therubyracer (0.12.3) + libv8 (~> 3.16.14.15) ref thor (0.20.0) thread_safe (0.3.6) - tilt (2.0.5) - turbolinks (2.5.3) - coffee-rails + tilt (2.0.8) + turbolinks (5.2.0) + turbolinks-source (~> 5.2) + turbolinks-source (5.2.0) tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (3.0.0) + uglifier (4.1.19) execjs (>= 0.3.0, < 3) - web-console (2.3.0) - activemodel (>= 4.0) - binding_of_caller (>= 0.7.2) - railties (>= 4.0) - sprockets-rails (>= 2.0, < 4.0) - webmock (2.1.0) + web-console (3.7.0) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) + webmock (3.4.2) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff + websocket-driver (0.7.0) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) PLATFORMS ruby DEPENDENCIES - aws-sdk (~> 2.0) - bcrypt (~> 3.1.7) + aws-sdk-sqs (~> 1.6) + bcrypt (~> 3.1.12) + bootsnap byebug codeclimate-test-reporter + coffee-rails database_cleaner diffy dotenv - factory_girl_rails (~> 4.0) + factory_bot_rails (~> 4.11) guard-rspec httparty jquery-rails jwt kramdown letter_opener - pg (~> 0.15) + pg (~> 0.21) premailer-rails - puma (~> 3.2) + puma (~> 3.12) rack-cache - rails (~> 4.2) + rails (~> 5.2.1) + rails-controller-testing rails_12factor - rspec-rails (~> 3.0) + rspec-rails (~> 3.8) + rspec_junit_formatter sass-rails (~> 5.0) - sdoc (~> 0.4.0) - simple_form (~> 3.2) + sdoc (~> 1.0.0) + simple_form (~> 4.0) sinatra spring therubyracer turbolinks uglifier (>= 1.3.0) - web-console (~> 2.0) + web-console (~> 3.7) webmock RUBY VERSION - ruby 2.3.4p301 + ruby 2.4.4p296 BUNDLED WITH - 1.14.6 + 1.16.3 diff --git a/README.md b/README.md index 9f7e4520..ddaa6893 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,13 @@ Read more below, or say hello to the humans behind the project at the [Google Gr ## Alerting journalists to changes on the web -Built and refined in the newsroom of [The Marshall Project](https://www.themarshallproject.org/), Klaxon has provided our journalists with many news tips, giving us early warnings and valuable time to pursue stories. Klaxon has been used and tested by journalists at The Marshall Project, The New York Times, the Texas Tribune, the Associated Press [and elsewhere](NEWSROOMS.md). The public release of this free and open source software was supported by Knight-Mozilla [OpenNews](https://opennews.org/). [If you need help using Klaxon once it's already been set up, [you can find it here.](https://github.com/themarshallproject/klaxon/blob/master/data/help.md)] +Built and refined in the newsroom of [The Marshall Project](https://www.themarshallproject.org/), Klaxon has provided our journalists with many news tips, giving us early warnings and valuable time to pursue stories. Klaxon has been used and tested by journalists at The Marshall Project, The New York Times, the Texas Tribune, the Associated Press [and elsewhere](NEWSROOMS.md). + +The public release of this free and open source software was supported by Knight-Mozilla [OpenNews](https://opennews.org/). + +## How Does Klaxon Work? + +Klaxon enables users to "bookmark" portions of a webpage and be notified (via email or [Slack](#notify-a-slack-channel)) of any changes that may occur to those sections. [Learn more about bookmarklets on the help.md page](data/help.md). [![Circle CI](https://circleci.com/gh/themarshallproject/klaxon.svg?style=svg)](https://circleci.com/gh/themarshallproject/klaxon) @@ -116,6 +122,7 @@ The core contributors to Klaxon have been Ivar Vong, Andy Rossback, Tom Meagher We've been grateful for additional contributions to the project from: * Jackson Gothe-Snape, SBS News +* Cameo Hill * Emily Hopkins * Yolanda Martinez * Jeremy Merrill diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 50ad6bd6..2653d320 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -8,7 +8,7 @@ def authorize end end - before_filter :set_default_host + before_action :set_default_host def set_default_host # determine the host we're running on, so we can generate urls for emails, etc # keep this in an AppSetting (persisted) and pass to Rails when blank diff --git a/app/controllers/changes_controller.rb b/app/controllers/changes_controller.rb index 342bb916..8d980267 100644 --- a/app/controllers/changes_controller.rb +++ b/app/controllers/changes_controller.rb @@ -1,5 +1,5 @@ class ChangesController < ApplicationController - before_filter :set_change, only: [:page, :update, :resend] + before_action :set_change, only: [:page, :update, :resend] before_action :authorize def page diff --git a/app/lib/sqs_notification.rb b/app/lib/sqs_notification.rb index 7abf5682..e98ea7f7 100644 --- a/app/lib/sqs_notification.rb +++ b/app/lib/sqs_notification.rb @@ -1,5 +1,3 @@ -require 'aws-sdk' - class SqsNotification def self.perform(queue_url, payload) client = Aws::SQS::Client.new( @@ -11,16 +9,16 @@ def self.perform(queue_url, payload) begin return client.send_message({ - delay_seconds: 10, + delay_seconds: 10, message_attributes: { "payload" => { - data_type: "String", - string_value: json, + data_type: "String", + string_value: json, } - }, - message_body: json, - queue_url: queue_url, - }) + }, + message_body: json, + queue_url: queue_url, + }) rescue Aws::SQS::Errors::ServiceError => e puts "Error sending SQS message to queue_url=#{queue_url} for payload=#{payload.to_json}; Error: #{e}" return false diff --git a/app/mailers/change_mailer.rb b/app/mailers/change_mailer.rb index e291e9af..b6646b19 100644 --- a/app/mailers/change_mailer.rb +++ b/app/mailers/change_mailer.rb @@ -1,5 +1,4 @@ class ChangeMailer < ApplicationMailer - def page(user: nil, change: nil) @change = change @page = @change.after.page @@ -7,5 +6,4 @@ def page(user: nil, change: nil) mail(to: @user.email, subject: "#{@page.name} changed") end - end diff --git a/app/models/app_setting.rb b/app/models/app_setting.rb index 74455270..07ff1d2c 100644 --- a/app/models/app_setting.rb +++ b/app/models/app_setting.rb @@ -1,4 +1,4 @@ -class AppSetting < ActiveRecord::Base +class AppSetting < ApplicationRecord def self.default_host_key 'default_host' diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 00000000..10a4cba8 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/app/models/change.rb b/app/models/change.rb index 2b46bf3b..9953f49c 100644 --- a/app/models/change.rb +++ b/app/models/change.rb @@ -1,4 +1,4 @@ -class Change < ActiveRecord::Base +class Change < ApplicationRecord belongs_to :before, polymorphic: true validates :before, presence: true diff --git a/app/models/page.rb b/app/models/page.rb index 6a81c1ad..204cca51 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -1,4 +1,4 @@ -class Page < ActiveRecord::Base +class Page < ApplicationRecord belongs_to :user has_many :page_snapshots, dependent: :destroy diff --git a/app/models/page_snapshot.rb b/app/models/page_snapshot.rb index b17aaa3a..aab0ac5a 100644 --- a/app/models/page_snapshot.rb +++ b/app/models/page_snapshot.rb @@ -1,6 +1,6 @@ -class PageSnapshot < ActiveRecord::Base +class PageSnapshot < ApplicationRecord belongs_to :page - validates :page, presence: true + validates :sha2_hash, presence: true after_destroy do |record| diff --git a/app/models/slack_integration.rb b/app/models/slack_integration.rb index e4cf74b4..da2a7fb7 100644 --- a/app/models/slack_integration.rb +++ b/app/models/slack_integration.rb @@ -1,4 +1,4 @@ -class SlackIntegration < ActiveRecord::Base +class SlackIntegration < ApplicationRecord validates :channel, length: { minimum: 2 } validates :webhook_url, length: { minimum: 10 } @@ -38,7 +38,7 @@ def send_notification(change) page_name = change&.after&.page&.name text = "#{page_name} changed #{page_change_url(change)}" - icon_url = URI.join(root_url, ActionController::Base.helpers.asset_path("klaxon-logo-100px.png")).to_s + icon_url = URI.join(root_url, '/images/klaxon-logo-100px.png').to_s payload = { "username": "Klaxon", diff --git a/app/models/sqs_integration.rb b/app/models/sqs_integration.rb index 931ca3fe..18084dde 100644 --- a/app/models/sqs_integration.rb +++ b/app/models/sqs_integration.rb @@ -1,4 +1,4 @@ -class SqsIntegration < ActiveRecord::Base +class SqsIntegration < ApplicationRecord validates :queue_url, length: { minimum: 10 } validate :starts_with_https diff --git a/app/models/subscription.rb b/app/models/subscription.rb index 78e3c5aa..ea9de394 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -1,4 +1,4 @@ -class Subscription < ActiveRecord::Base +class Subscription < ApplicationRecord belongs_to :watcher, polymorphic: true validates :watcher, presence: true diff --git a/app/models/user.rb b/app/models/user.rb index a4514df2..832c6a41 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,4 @@ -class User < ActiveRecord::Base +class User < ApplicationRecord validates :email, length: { minimum: 3 }, uniqueness: { case_sensitive: false } validate :email_domain_is_approved, on: [ :create, :update ] has_many :pages @@ -35,7 +35,7 @@ def is_subscribed_to?(watchable) def send_notification(change) puts "user#send_notification #{self.email}" - ChangeMailer.page(change: change, user: self).deliver_later + ChangeMailer.page(change: change, user: self).deliver_now end def email_domain_is_approved diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 9dc0061e..00000000 --- a/circle.yml +++ /dev/null @@ -1,8 +0,0 @@ -deployment: - production: - branch: master - commands: - - "[[ ! -s \"$(git rev-parse --git-dir)/shallow\" ]] || git fetch --unshallow" - - git push git@heroku.com:klaxon-demo.git $CIRCLE_SHA1:refs/heads/master - - heroku run rake db:migrate --app klaxon-demo: - timeout: 400 diff --git a/config/application.rb b/config/application.rb index 4519b6c4..d3c8b83b 100644 --- a/config/application.rb +++ b/config/application.rb @@ -35,10 +35,7 @@ class Application < Rails::Application config.autoload_paths << "#{Rails.root}/lib" - # Do not swallow errors in after_commit/after_rollback callbacks. - config.active_record.raise_in_transactional_callbacks = true - - config.static_cache_control = "public, max-age=31536000" + config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=31536000' } config.middleware.use Rack::Cache, verbose: true, diff --git a/config/boot.rb b/config/boot.rb index 6b750f00..b9e460ce 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,4 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. +require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/database.yml b/config/database.yml index 0d1313ca..0d0e821e 100644 --- a/config/database.yml +++ b/config/database.yml @@ -13,7 +13,7 @@ development: test: <<: *default database: klaxon_test - username: <%= `whoami` %> + username: <%= ENV['PGUSER'] || `whoami` %> host: localhost port: 5432 diff --git a/config/environments/production.rb b/config/environments/production.rb index 328bd36f..fc028a47 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -22,13 +22,14 @@ # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. - config.serve_static_files = true + config.public_file_server.enabled = true # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier # config.assets.css_compressor = :sass - config.assets.compile = true + # Do not fall back to locating/compiling missing assets. + config.assets.compile = false # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. @@ -83,7 +84,7 @@ address = ENV["#{provider}_ADDRESS"] || "smtp.sendgrid.net" # if you use SES as your SMTP provider, then your username and password are actually your AWS credentials. user_name = ENV["#{provider}_USERNAME" || (provider == "SES" ? (ENV["AWS_ACCESS_KEY_ID"] || ENV["ACCESS_KEY_ID"] ) : nil) ] # for AWS SES, this is your access key id - password = ENV["#{provider}_PASSWORD" || (provider == "SES" ? (ENV["AWS_SECRET_ACCESS_KEY"] || ENV["SECRET_ACCESS_KEY"] ) : nil) ] # for AWS SES, this is your secret access key + password = ENV["#{provider}_PASSWORD" || (provider == "SES" ? (ENV["AWS_SECRET_ACCESS_KEY"] || ENV["SECRET_ACCESS_KEY"] ) : nil) ] # for AWS SES, this is your secret access key domain = ENV["#{provider}_DOMAIN"] || "heroku.com" port = ENV["#{provider}_PORT"] || "587" diff --git a/config/environments/test.rb b/config/environments/test.rb index 1c19f08b..740d1383 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -13,8 +13,8 @@ config.eager_load = false # Configure static file server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' + config.public_file_server.enabled = true + config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } # Show full error reports and disable caching. config.consider_all_requests_local = true diff --git a/data/help.md b/data/help.md index 97a4f91e..e06a7eb3 100644 --- a/data/help.md +++ b/data/help.md @@ -4,54 +4,29 @@ Klaxon is a tool that enables journalists and researchers to monitor scores of w #Bookmark Set-Up -Working with Klaxon requires the one-time setup of a bookmarklet. Once the bookmarklet is added to your browser, clicking on it will allow you to save a page. +Working with Klaxon requires the one-time setup of a bookmarklet. Once the bookmarklet is added to your browser, clicking on it will allow you to save a page. -To add the bookmarklet, visit the Klaxon website. The first time you visit you'll notice a box that says “Watch Your First Item.” Underneath that, you’ll see a button that says “Add to Klaxon.” Click and drag that button to the bookmarks bar on your browser. Now anytime you’re on a site you want follow through Klaxon, you can click on the bookmarklet *without having to leave the site*. This works similarly to services like Digg and Pinterest. +To add the bookmarklet, visit the Klaxon website. The first time you visit you'll notice a box that says “Watch Your First Item.” Underneath that, you’ll see a button that says “Add to Klaxon.” Click and drag that button to the bookmarks bar on your browser. Now anytime you’re on a site you want follow through Klaxon, you can click on the bookmarklet *without having to leave the site*. This works similarly to services like Digg and Pinterest. Clicking on the bookmark will open a popup on the right side of your browser window. As you move your mouse around the page, different sections are highlighted. Web pages have images, files, tables and text that live in specific sections of the HTML document. With your mouse, you can select a table row (tr), paragraph (p), headline (h2) or the whole body of text (body). These selectors tell Klaxon *which* part of the page to follow, so you’ll only get alerts when that specific section changes. To tell Klaxon where to look, hover your mouse over different sections of the page. Notice how each section is highlighted in red when you hover. This is one indicator to help Klaxon home in on the right area. -![](/assets/bookmarklet.png) +![Example of choosing an element to watch](/images/bookmarklet.png) When you think you have highlighted the correct section of the page—say the list of Supreme Court decisions, or the latest documents in next year’s state budget—click the mouse. Now, look under the “Save and Edit” box in the Klaxon window, and you’ll notice it says “Done!” That means that Klaxon has saved this page and will start watching it for you. -Before you close the window though, see the red box under the heading “Content Preview?” That shows you what information is captured in the section of the page you selected. If the words you see in the red box don’t match what you’re hoping to monitor, you might have chosen the wrong part of the page. Not to worry, you can hover and click on any different section of the page until you get the right area selected and saved. +Before you close the window though, see the red box under the heading “Content Preview?” That shows you what information is captured in the section of the page you selected. If the words you see in the red box don’t match what you’re hoping to monitor, you might have chosen the wrong part of the page. Not to worry, you can hover and click on any different section of the page until you get the right area selected and saved. For the last step, you’ll want to click the ‘Save and Edit’ button, which will bring you back to Klaxon so you can give this page a name (like a slug) in the system. -#### Bookmarklet not working? - -In some cases, certain Chrome extensions may break the bookmarklet. -In some cases, it may look somethings like this: - -!["example of broken bookmarlet"](https://user-images.githubusercontent.com/190733/28034680-8375a8a2-6577-11e7-86fd-c594d35bd4b1.png) - -For example, the Electronic Frontier Foundation's ["Privacy Badger"](https://www.eff.org/privacybadger) is a script blocker. When you use Klaxon in addition to Privacy Badger, EFF's extension detects Klaxon as a script and blocks it. This breaks the service. - -The solution: - -Whitelist your organization’s specific Klaxon in Privacy Badger. - -To do this, click on the Privacy Badger icon in your Chrome extension bar. A dialog box should appear. Click the gear in the upper right hand corner of the dialog box. This will open Privacy Badger Settings in a new tab. - -!["Privac Badger Dialog box"](/docs/privacy_badger_dialog.PNG) - -There should be a tab for "Whitelisted Domains" in your Privacy Badger settings. Go to that and add your organization's Klaxon (XXX-klaxon.herokuapp.com) to it. Click add domain. - -!["Privac Badger Dialog settings"](/docs/privacy_badger_settings.PNG) - -This should fix this issue. Apply the same logic for other extensions that might cause Klaxon to not work. - -For further reference on these issues, refer to issues [#135](https://github.com/themarshallproject/klaxon/issues/135) and [#138](https://github.com/themarshallproject/klaxon/issues/138). - ## The Feed -In [the Feed](/) you'll find a list of recent snapshots of pages people in your newsroom are following. This is a good place to see what’s new in the system and to discover and subscribe to Klaxons that other reporters or editors find useful. These links are in order of most recent changes. You will also get a team summary of how many changes have been monitored, the number of pages the team is following and how many users are using Klaxon. +In [the Feed](/) you'll find a list of recent snapshots of pages people in your newsroom are following. This is a good place to see what’s new in the system and to discover and subscribe to Klaxons that other reporters or editors find useful. These links are in order of most recent changes. You will also get a team summary of how many changes have been monitored, the number of pages the team is following and how many users are using Klaxon. If you want to step back through each stage of the site’s evolution, you can explore its history on the “[Watching](/watching/pages)” page. ## Watching -The “[Watching](/watching/pages)” page displays a list of all the pages that your newsroom is monitoring (as opposed to a chronological stream of the latest updates as seen in the [Feed](/)). Here you can also change settings for individual pages. +The “[Watching](/watching/pages)” page displays a list of all the pages that your newsroom is monitoring (as opposed to a chronological stream of the latest updates as seen in the [Feed](/)). Here you can also change settings for individual pages. To change the name or URL of any of the Klaxons you’ve created or to adjust their notification settings, simply click the “Edit” button next to the appropriate page. You can also click into each to view the differences of each snapshot the system has collected since you added it to Klaxon. @@ -63,17 +38,17 @@ To make it easier to keep track of what’s significant about each change and to In the “[Watching](/watching/pages)” page you can manually add sites to monitor if you already know which CSS Selector on the page you want to follow or are having difficulty with the bookmarklet. -Click on "Manually Watch and Item" on the right side of the heading. This will take you to directly to the Edit page for links. Here you can include the title, link to the site and the specific selector(s) you want to focus on. +Click on "Manually Watch and Item" on the right side of the heading. This will take you to directly to the Edit page for links. Here you can include the title, link to the site and the specific selector(s) you want to focus on. ## Understand what’s changed on a page -Sometimes you want to see how the current version of a site compares to a version that you captured, say, six months ago. Because Klaxon stores each snapshot it finds of a site, this is fairly easy to do. You can reach the history of snapshots in a couple of ways. If it’s a site someone else in your newsroom is following, from the Feed, click on the latest snapshot you see for your site, which would say something like “GA Sec’y of State changed” or “The Marshall Project changed”. If it’s a site you added to Klaxon, from the “Watching” page, click on the “Latest snapshot” button next the site you want to explore. Either of these routes takes you to the most recent snapshot for that site. +Sometimes you want to see how the current version of a site compares to a version that you captured, say, six months ago. Because Klaxon stores each snapshot it finds of a site, this is fairly easy to do. You can reach the history of snapshots in a couple of ways. If it’s a site someone else in your newsroom is following, from the Feed, click on the latest snapshot you see for your site, which would say something like “GA Sec’y of State changed” or “The Marshall Project changed”. If it’s a site you added to Klaxon, from the “Watching” page, click on the “Latest snapshot” button next the site you want to explore. Either of these routes takes you to the most recent snapshot for that site. Now, click the “Past snapshots” button in the upper right corner. This takes you to a list of every snapshot Klaxon has captured of the site in question. -![](/assets/compare_versions.png) +![Example of comparing two snapshots](/images/compare_versions.png) -First, select the “older” version from the left column that you want to be the basis of comparison. Then, in the right column, select the “newer” snapshot from the list. Finally, click the compare button. This takes you to a new page to compare the snapshots. The difference between the two pages will be displayed just as it is in the “Latest snapshot” page: additions to the site will be highlighted in green, deletions will be marked in red. Using the “Past snapshots” list, you can step through every change, one at a time, to find the update you’re looking for. When you find what you’re looking for, add a note in the “What’s Changed” field to make it easier to find later when you need it. +First, select the “older” version from the left column that you want to be the basis of comparison. Then, in the right column, select the “newer” snapshot from the list. Finally, click the compare button. This takes you to a new page to compare the snapshots. The difference between the two pages will be displayed just as it is in the “Latest snapshot” page: additions to the site will be highlighted in green, deletions will be marked in red. Using the “Past snapshots” list, you can step through every change, one at a time, to find the update you’re looking for. When you find what you’re looking for, add a note in the “What’s Changed” field to make it easier to find later when you need it. ## How to add notifications to a Slack channel @@ -89,3 +64,27 @@ Built and refined in the newsroom of [The Marshall Project](https://www.themarsh When we release major changes to Klaxon, we’ll make an announcement to our [Google Group email list](https://groups.google.com/forum/#!forum/news-klaxon-users). At that point, you’ll likely want to adopt those in your system as well. To do that, you can find [everything you'll need to upgrade here](https://github.com/themarshallproject/klaxon#applying-upgrades-as-the-project-develops). +## Bookmarklet not working? + +In some cases, certain Chrome extensions may break the bookmarklet. +It may look something like this: + +![example of broken bookmarlet](https://user-images.githubusercontent.com/190733/28034680-8375a8a2-6577-11e7-86fd-c594d35bd4b1.png) + +For example, the Electronic Frontier Foundation's ["Privacy Badger"](https://www.eff.org/privacybadger) is a script blocker. When you use Klaxon in addition to Privacy Badger, the extension detects Klaxon as a script and blocks it. This breaks the service. + +The solution: + +Whitelist your organization’s specific Klaxon in Privacy Badger. + +To do this, click on the Privacy Badger icon in your Chrome extension bar. A dialog box should appear. Click the gear in the upper right hand corner of the dialog box. This will open Privacy Badger Settings in a new tab. + +![Privacy Badger Dialog box](/images/privacy_badger_dialog.PNG) + +There should be a tab for "Whitelisted Domains" in your Privacy Badger settings. Go to that and add your organization's Klaxon (XXX-klaxon.herokuapp.com) to it. Click add domain. + +![Privacy Badger Dialog settings](/images/privacy_badger_settings.PNG) + +This should fix this issue. Apply the same logic for other ad-blocking, tracking-prevention extensions that might cause Klaxon to not work. + +For further reference on these issues, refer to issues [#135](https://github.com/themarshallproject/klaxon/issues/135) and [#138](https://github.com/themarshallproject/klaxon/issues/138). diff --git a/app/assets/images/bookmarklet.png b/public/images/bookmarklet.png similarity index 100% rename from app/assets/images/bookmarklet.png rename to public/images/bookmarklet.png diff --git a/app/assets/images/compare_versions.png b/public/images/compare_versions.png similarity index 100% rename from app/assets/images/compare_versions.png rename to public/images/compare_versions.png diff --git a/app/assets/images/klaxon-logo-100px.png b/public/images/klaxon-logo-100px.png similarity index 100% rename from app/assets/images/klaxon-logo-100px.png rename to public/images/klaxon-logo-100px.png diff --git a/docs/privacy_badger_dialog.PNG b/public/images/privacy_badger_dialog.PNG similarity index 100% rename from docs/privacy_badger_dialog.PNG rename to public/images/privacy_badger_dialog.PNG diff --git a/docs/privacy_badger_settings.PNG b/public/images/privacy_badger_settings.PNG similarity index 100% rename from docs/privacy_badger_settings.PNG rename to public/images/privacy_badger_settings.PNG diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 46f8eaed..be4e21bb 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -12,13 +12,13 @@ describe "POST #create" do it "accepts an email for login" do user = create(:user) - post :create, email: user.email + post :create, params: { email: user.email } expect(response).not_to redirect_to(unknown_user_path) end it "is case-insensitive when checking emails" do user = create(:user) - post :create, email: user.email.upcase + post :create, params: { email: user.email.upcase } expect(response).not_to redirect_to(unknown_user_path) end end diff --git a/spec/controllers/slack_integrations_controller_spec.rb b/spec/controllers/slack_integrations_controller_spec.rb index 641c14d1..6b8d4503 100644 --- a/spec/controllers/slack_integrations_controller_spec.rb +++ b/spec/controllers/slack_integrations_controller_spec.rb @@ -31,15 +31,10 @@ skip("Add a hash of attributes invalid for your model") } - # This should return the minimal set of values that should be in the session - # in order to pass any filters (e.g. authentication) defined in - # SlackIntegrationsController. Be sure to keep this updated too. - let(:valid_session) { {} } - describe "GET #index" do it "assigns all slack_integrations as @slack_integrations" do slack_integration = SlackIntegration.create! valid_attributes - get :index, {}, valid_session + get :index, params: {} expect(assigns(:slack_integrations)).to eq([slack_integration]) end end @@ -47,14 +42,14 @@ describe "GET #show" do it "assigns the requested slack_integration as @slack_integration" do slack_integration = SlackIntegration.create! valid_attributes - get :show, {:id => slack_integration.to_param}, valid_session + get :show, params: {:id => slack_integration.to_param} expect(assigns(:slack_integration)).to eq(slack_integration) end end describe "GET #new" do it "assigns a new slack_integration as @slack_integration" do - get :new, {}, valid_session + get :new, params: {} expect(assigns(:slack_integration)).to be_a_new(SlackIntegration) end end @@ -62,7 +57,7 @@ describe "GET #edit" do it "assigns the requested slack_integration as @slack_integration" do slack_integration = SlackIntegration.create! valid_attributes - get :edit, {:id => slack_integration.to_param}, valid_session + get :edit, params: {:id => slack_integration.to_param} expect(assigns(:slack_integration)).to eq(slack_integration) end end @@ -71,30 +66,30 @@ context "with valid params" do it "creates a new SlackIntegration" do expect { - post :create, {:slack_integration => valid_attributes}, valid_session + post :create, params: {:slack_integration => valid_attributes} }.to change(SlackIntegration, :count).by(1) end it "assigns a newly created slack_integration as @slack_integration" do - post :create, {:slack_integration => valid_attributes}, valid_session + post :create, params: {:slack_integration => valid_attributes} expect(assigns(:slack_integration)).to be_a(SlackIntegration) expect(assigns(:slack_integration)).to be_persisted end it "redirects to the created slack_integration" do - post :create, {:slack_integration => valid_attributes}, valid_session + post :create, params: {:slack_integration => valid_attributes} expect(response).to redirect_to(SlackIntegration.last) end end context "with invalid params" do it "assigns a newly created but unsaved slack_integration as @slack_integration" do - post :create, {:slack_integration => invalid_attributes}, valid_session + post :create, params: {:slack_integration => invalid_attributes} expect(assigns(:slack_integration)).to be_a_new(SlackIntegration) end it "re-renders the 'new' template" do - post :create, {:slack_integration => invalid_attributes}, valid_session + post :create, params: {:slack_integration => invalid_attributes} expect(response).to render_template("new") end end @@ -108,20 +103,20 @@ it "updates the requested slack_integration" do slack_integration = SlackIntegration.create! valid_attributes - put :update, {:id => slack_integration.to_param, :slack_integration => new_attributes}, valid_session + put :update, params: {:id => slack_integration.to_param, :slack_integration => new_attributes} slack_integration.reload skip("Add assertions for updated state") end it "assigns the requested slack_integration as @slack_integration" do slack_integration = SlackIntegration.create! valid_attributes - put :update, {:id => slack_integration.to_param, :slack_integration => valid_attributes}, valid_session + put :update, params: {:id => slack_integration.to_param, :slack_integration => valid_attributes} expect(assigns(:slack_integration)).to eq(slack_integration) end it "redirects to the slack_integration" do slack_integration = SlackIntegration.create! valid_attributes - put :update, {:id => slack_integration.to_param, :slack_integration => valid_attributes}, valid_session + put :update, params: {:id => slack_integration.to_param, :slack_integration => valid_attributes} expect(response).to redirect_to(slack_integration) end end @@ -129,13 +124,13 @@ context "with invalid params" do it "assigns the slack_integration as @slack_integration" do slack_integration = SlackIntegration.create! valid_attributes - put :update, {:id => slack_integration.to_param, :slack_integration => invalid_attributes}, valid_session + put :update, params: {:id => slack_integration.to_param, :slack_integration => invalid_attributes} expect(assigns(:slack_integration)).to eq(slack_integration) end it "re-renders the 'edit' template" do slack_integration = SlackIntegration.create! valid_attributes - put :update, {:id => slack_integration.to_param, :slack_integration => invalid_attributes}, valid_session + put :update, params: {:id => slack_integration.to_param, :slack_integration => invalid_attributes} expect(response).to render_template("edit") end end @@ -145,13 +140,13 @@ it "destroys the requested slack_integration" do slack_integration = SlackIntegration.create! valid_attributes expect { - delete :destroy, {:id => slack_integration.to_param}, valid_session + delete :destroy, params: {:id => slack_integration.to_param} }.to change(SlackIntegration, :count).by(-1) end it "redirects to the slack_integrations list" do slack_integration = SlackIntegration.create! valid_attributes - delete :destroy, {:id => slack_integration.to_param}, valid_session + delete :destroy, params: {:id => slack_integration.to_param} expect(response).to redirect_to(slack_integrations_url) end end diff --git a/spec/controllers/sqs_integrations_controller_spec.rb b/spec/controllers/sqs_integrations_controller_spec.rb index 6eb3963e..25071d49 100644 --- a/spec/controllers/sqs_integrations_controller_spec.rb +++ b/spec/controllers/sqs_integrations_controller_spec.rb @@ -35,15 +35,10 @@ } } - # This should return the minimal set of values that should be in the session - # in order to pass any filters (e.g. authentication) defined in - # SqsIntegrationsController. Be sure to keep this updated too. - let(:valid_session) { {} } - describe "GET #index" do it "assigns all sqs_integrations as @sqs_integrations" do sqs_integration = SqsIntegration.create! valid_attributes - get :index, {}, valid_session + get :index, params: {} expect(assigns(:sqs_integrations)).to eq([sqs_integration]) end end @@ -51,14 +46,14 @@ describe "GET #show" do it "assigns the requested sqs_integration as @sqs_integration" do sqs_integration = SqsIntegration.create! valid_attributes - get :show, {:id => sqs_integration.to_param}, valid_session + get :show, params: {:id => sqs_integration.to_param} expect(assigns(:sqs_integration)).to eq(sqs_integration) end end describe "GET #new" do it "assigns a new sqs_integration as @sqs_integration" do - get :new, {}, valid_session + get :new, params: {} expect(assigns(:sqs_integration)).to be_a_new(SqsIntegration) end end @@ -66,7 +61,7 @@ describe "GET #edit" do it "assigns the requested sqs_integration as @sqs_integration" do sqs_integration = SqsIntegration.create! valid_attributes - get :edit, {:id => sqs_integration.to_param}, valid_session + get :edit, params: {:id => sqs_integration.to_param} expect(assigns(:sqs_integration)).to eq(sqs_integration) end end @@ -75,30 +70,30 @@ context "with valid params" do it "creates a new SqsIntegration" do expect { - post :create, {:sqs_integration => valid_attributes}, valid_session + post :create, params: {:sqs_integration => valid_attributes} }.to change(SqsIntegration, :count).by(1) end it "assigns a newly created sqs_integration as @sqs_integration" do - post :create, {:sqs_integration => valid_attributes}, valid_session + post :create, params: {:sqs_integration => valid_attributes} expect(assigns(:sqs_integration)).to be_a(SqsIntegration) expect(assigns(:sqs_integration)).to be_persisted end it "redirects to the intersections path" do - post :create, {:sqs_integration => valid_attributes}, valid_session + post :create, params: {:sqs_integration => valid_attributes} expect(response).to redirect_to(integrations_path) end end context "with invalid params" do it "assigns a newly created but unsaved sqs_integration as @sqs_integration" do - post :create, {:sqs_integration => invalid_attributes}, valid_session + post :create, params: {:sqs_integration => invalid_attributes} expect(assigns(:sqs_integration)).to be_a_new(SqsIntegration) end it "re-renders the 'new' template" do - post :create, {:sqs_integration => invalid_attributes}, valid_session + post :create, params: {:sqs_integration => invalid_attributes} expect(response).to render_template("new") end end @@ -114,7 +109,7 @@ it "updates the requested sqs_integration" do sqs_integration = SqsIntegration.create! valid_attributes - put :update, {:id => sqs_integration.to_param, :sqs_integration => new_attributes}, valid_session + put :update, params: {:id => sqs_integration.to_param, :sqs_integration => new_attributes} sqs_integration.reload expect(sqs_integration.queue_url).to eq(new_attributes[:queue_url]) expect(sqs_integration).to be_persisted @@ -122,13 +117,13 @@ it "assigns the requested sqs_integration as @sqs_integration" do sqs_integration = SqsIntegration.create! valid_attributes - put :update, {:id => sqs_integration.to_param, :sqs_integration => valid_attributes}, valid_session + put :update, params: {:id => sqs_integration.to_param, :sqs_integration => valid_attributes} expect(assigns(:sqs_integration)).to eq(sqs_integration) end it "redirects to the sqs_integration" do sqs_integration = SqsIntegration.create! valid_attributes - put :update, {:id => sqs_integration.to_param, :sqs_integration => valid_attributes}, valid_session + put :update, params: {:id => sqs_integration.to_param, :sqs_integration => valid_attributes} expect(response).to redirect_to(integrations_path) end end @@ -136,13 +131,13 @@ context "with invalid params" do it "assigns the sqs_integration as @sqs_integration" do sqs_integration = SqsIntegration.create! valid_attributes - put :update, {:id => sqs_integration.to_param, :sqs_integration => invalid_attributes}, valid_session + put :update, params: {:id => sqs_integration.to_param, :sqs_integration => invalid_attributes} expect(assigns(:sqs_integration)).to eq(sqs_integration) end it "re-renders the 'edit' template" do sqs_integration = SqsIntegration.create! valid_attributes - put :update, {:id => sqs_integration.to_param, :sqs_integration => invalid_attributes}, valid_session + put :update, params: {:id => sqs_integration.to_param, :sqs_integration => invalid_attributes} expect(response).to render_template("edit") end end @@ -152,13 +147,13 @@ it "destroys the requested sqs_integration" do sqs_integration = SqsIntegration.create! valid_attributes expect { - delete :destroy, {:id => sqs_integration.to_param}, valid_session + delete :destroy, params: {:id => sqs_integration.to_param} }.to change(SqsIntegration, :count).by(-1) end it "redirects to the sqs_integrations list" do sqs_integration = SqsIntegration.create! valid_attributes - delete :destroy, {:id => sqs_integration.to_param}, valid_session + delete :destroy, params: {:id => sqs_integration.to_param} expect(response).to redirect_to(integrations_path) end end diff --git a/spec/factories.rb b/spec/factories.rb index 35935b51..dcaf2115 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1,4 +1,4 @@ -FactoryGirl.define do +FactoryBot.define do factory :page_snapshot do page { create(:page) } @@ -9,12 +9,12 @@ end factory :slack_integration do - channel "#klaxon" - webhook_url "http://test-webhook.com/test-webhook" + channel { "#klaxon" } + webhook_url { "http://test-webhook.com/test-webhook" } end factory :sqs_integration do - queue_url "https://sqs.us-east-1.amazonaws.com/1234567890/klaxon-sqs-q-test" + queue_url { "https://sqs.us-east-1.amazonaws.com/1234567890/klaxon-sqs-q-test" } end factory :change do @@ -27,13 +27,13 @@ end factory :page do - name "nyt homepage" - url "http://www.nytimes.com/" - css_selector "h2.story-heading" + name { "nyt homepage" } + url { "http://www.nytimes.com/" } + css_selector { "h2.story-heading" } trait :with_snapshots do transient do - snapshot_count 2 + snapshot_count { 2 } end after(:create) do |page, evaluator| create_list(:page_snapshot, evaluator.snapshot_count, page: page) diff --git a/spec/models/change_spec.rb b/spec/models/change_spec.rb index 06d50efd..b45f90cd 100644 --- a/spec/models/change_spec.rb +++ b/spec/models/change_spec.rb @@ -48,8 +48,7 @@ last_change = Change.order('created_at DESC').first expect(last_change.before).to eq expect_before expect(last_change.after).to eq expect_after - - assert_enqueued_jobs 1 # (and not more than 1) + expect(ActionMailer::Base.deliveries.length).to eq 1 end it "doesnt send anything if there is only one snapshot for a page" do @@ -63,7 +62,7 @@ # perform Change.check - assert_enqueued_jobs 0 # (and not more than 0) + expect(ActionMailer::Base.deliveries.length).to eq 0 end end diff --git a/spec/models/slack_integration_spec.rb b/spec/models/slack_integration_spec.rb index 99cb94b1..cb5f4191 100644 --- a/spec/models/slack_integration_spec.rb +++ b/spec/models/slack_integration_spec.rb @@ -14,7 +14,7 @@ payload = slack.send_notification(change) expect(payload[:icon_url]).to start_with 'http' - expect(payload[:icon_url]).to include '/assets/klaxon-logo' + expect(payload[:icon_url]).to include '/images/klaxon-logo' expect(payload[:channel]).to eq slack.channel expect(payload[:username]).to include "Klaxon" expect(payload[:text]).to include page.name diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 9e97b0cc..eee58291 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -37,7 +37,7 @@ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures" - config.include FactoryGirl::Syntax::Methods + config.include FactoryBot::Syntax::Methods config.use_transactional_fixtures = false diff --git a/spec/requests/api_controller_spec.rb b/spec/requests/api_controller_spec.rb index e365d616..bf579df8 100644 --- a/spec/requests/api_controller_spec.rb +++ b/spec/requests/api_controller_spec.rb @@ -7,7 +7,7 @@ # login @user = User.where(email: 'test@test.com').first_or_create - get(token_session_path, token: LoginToken.create(user: @user)) + get(token_session_path, params: { token: LoginToken.create(user: @user) }) end describe "/page-preview" do @@ -16,7 +16,7 @@ url = 'https://www.themarshallproject.org' css_selector = 'header' - get(api_page_preview_path, url: url, css_selector: css_selector) + get(api_page_preview_path, params: { url: url, css_selector: css_selector }) expect(response).to have_http_status(:success) @@ -37,7 +37,7 @@ selector = ".first-column-region .story" # create the page - post(embed_find_page_path, url: url) + post(embed_find_page_path, params: { url: url }) expect(response).to have_http_status(:success) data = JSON.parse(response.body) expect(data['url']).to eq url @@ -46,7 +46,7 @@ expect(page.user).to eq @user # update the page - post(embed_update_page_selector_path, id: page.id, css_selector: selector) + post(embed_update_page_selector_path, params: { id: page.id, css_selector: selector }) data = JSON.parse(response.body) expect(data['css_selector']).to eq selector expect(data['user_id']).to eq @user.id diff --git a/spec/requests/change_spec.rb b/spec/requests/change_spec.rb index 182a4f5d..cbc7c599 100644 --- a/spec/requests/change_spec.rb +++ b/spec/requests/change_spec.rb @@ -8,11 +8,10 @@ # login @user = User.where(email: 'test@test.com').first_or_create - get(token_session_path, token: LoginToken.create(user: @user)) + get(token_session_path, params: { token: LoginToken.create(user: @user) }) end it "can create multiple snapshots and send an email based on the last pair" do - stub_request(:any, /faketimeserver.com/).to_rack(FakeTimeServer) page = Page.create!(url: "http://faketimeserver.com/now", user: @user, css_selector: 'body') @@ -27,12 +26,6 @@ Change.check - assert_enqueued_jobs 1 # even though we had three snapshots, expect just one email - - ## TODO: WIP! - + expect(ActionMailer::Base.deliveries.length).to eq 1 # even though we had three snapshots, expect just one email end - - - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index babfb0cb..a9e4ccf1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -43,6 +43,10 @@ mocks.verify_partial_doubles = true end + # Clear out all sent emails before each test + config.before(:each) { ActionMailer::Base.deliveries.clear } + + # The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. =begin