diff --git a/.gitignore b/.gitignore index 336b921..32522ff 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ spec/dummy/db/*.sqlite3 spec/dummy/log/*.log spec/dummy/tmp/ tags + +.byebug_history diff --git a/Changes.md b/Changes.md index cb4fdd8..b7af0c1 100644 --- a/Changes.md +++ b/Changes.md @@ -1,3 +1,29 @@ +1.2.2 +----------- + +- Remove duplicated href key from config template #146 [nfilzi] +- Replace deprecated .any? with .present? #143 [AakLak] +- Development environment update #140 [mizinsky] +- Fix sanitize_params method #137 [mizinsky] +- Enable to configure global remote option and it to affects sortable helper #131 [kitabatake] +- Kaminari update [mizinsky] +- Update Readme for Rails >= 5.1 Users [mizinsky] + +1.2.1 +----------- + +- Allow to render outside of controllers [bval] +- Documentation fixes [blackcofla] +- Use id.to_json so integers and uuids will both work [sevgibson] +- Fix popover in bootstrap 4 [sevgibson] +- Fix Kaminari #num_pages deprecation warning [tylerhunt] +- Add support for Turbolinks 5 [wynksaiddestroy] +- Use #empty? for AC::Params [phoffer] +- Fix indentation in some files [boy-papan] + +1.2.0 +----------- + - Rails 5 support and Kaminari update [akostadinov] - Better handling of nested controls params - Fix controls not fading out list. Related to #51 @@ -6,6 +32,7 @@ 1.1.2 ----------- + - Some bugfixing: #20, #46, #58 1.1.0 diff --git a/Gemfile.lock b/Gemfile.lock index bf9b436..33e050e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,136 +1,216 @@ PATH remote: . specs: - smart_listing (1.1.2) + smart_listing (1.2.1) coffee-rails jquery-rails - kaminari (~> 0.17) + kaminari (>= 0.17) rails (>= 3.2) GEM remote: https://rubygems.org/ specs: - actionmailer (4.1.6) - actionpack (= 4.1.6) - actionview (= 4.1.6) + actioncable (5.1.4) + actionpack (= 5.1.4) + nio4r (~> 2.0) + websocket-driver (~> 0.6.1) + actionmailer (5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) mail (~> 2.5, >= 2.5.4) - actionpack (4.1.6) - actionview (= 4.1.6) - activesupport (= 4.1.6) - rack (~> 1.5.2) - rack-test (~> 0.6.2) - actionview (4.1.6) - activesupport (= 4.1.6) + rails-dom-testing (~> 2.0) + actionpack (5.1.4) + actionview (= 5.1.4) + activesupport (= 5.1.4) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.1.4) + activesupport (= 5.1.4) builder (~> 3.1) - erubis (~> 2.7.0) - activemodel (4.1.6) - activesupport (= 4.1.6) - builder (~> 3.1) - activerecord (4.1.6) - activemodel (= 4.1.6) - activesupport (= 4.1.6) - arel (~> 5.0.0) - activesupport (4.1.6) - i18n (~> 0.6, >= 0.6.9) - json (~> 1.7, >= 1.7.7) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.1.4) + activesupport (= 5.1.4) + globalid (>= 0.3.6) + activemodel (5.1.4) + activesupport (= 5.1.4) + activerecord (5.1.4) + activemodel (= 5.1.4) + activesupport (= 5.1.4) + arel (~> 8.0) + activesupport (5.1.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) minitest (~> 5.1) - thread_safe (~> 0.1) tzinfo (~> 1.1) - arel (5.0.1.20140414130214) - bootstrap-sass (3.3.0.1) - sass (~> 3.2) - builder (3.2.2) - capybara (2.4.4) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + arel (8.0.0) + autoprefixer-rails (7.2.5) + execjs + bootstrap-sass (3.3.7) + autoprefixer-rails (>= 5.2.1) + sass (>= 3.3.4) + builder (3.2.3) + byebug (9.1.0) + capybara (2.13.0) + addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - capybara-webkit (1.3.1) - capybara (>= 2.0.2, < 2.5.0) + capybara-webkit (1.14.0) + capybara (>= 2.3.0, < 2.14.0) json - coffee-rails (4.1.0) + coderay (1.1.2) + coffee-rails (4.2.2) coffee-script (>= 2.2.0) - railties (>= 4.0.0, < 5.0) - coffee-script (2.3.0) + railties (>= 4.0.0) + coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.8.0) - database_cleaner (1.3.0) - diff-lcs (1.2.5) - erubis (2.7.0) - execjs (2.2.2) - hike (1.2.3) - i18n (0.6.11) - jquery-rails (3.1.2) - railties (>= 3.0, < 5.0) + coffee-script-source (1.12.2) + concurrent-ruby (1.0.5) + crass (1.0.3) + database_cleaner (1.6.2) + diff-lcs (1.3) + erubi (1.7.0) + execjs (2.7.0) + ffi (1.9.18) + formatador (0.2.5) + globalid (0.4.1) + activesupport (>= 4.2.0) + guard (2.14.2) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.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.3) + guard (~> 2.1) + guard-compat (~> 1.1) + rspec (>= 2.99.0, < 4.0) + i18n (0.9.3) + concurrent-ruby (~> 1.0) + jquery-rails (4.3.1) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (1.8.1) + json (2.1.0) kaminari (0.17.0) actionpack (>= 3.0.0) activesupport (>= 3.0.0) - mail (2.6.3) - mime-types (>= 1.16, < 3) - mime-types (2.4.3) - mini_portile2 (2.1.0) - minitest (5.4.2) - multi_json (1.10.1) - nokogiri (1.6.8) - mini_portile2 (~> 2.1.0) - pkg-config (~> 1.1.7) - pkg-config (1.1.7) - rack (1.5.2) - rack-test (0.6.2) - rack (>= 1.0) - rails (4.1.6) - actionmailer (= 4.1.6) - actionpack (= 4.1.6) - actionview (= 4.1.6) - activemodel (= 4.1.6) - activerecord (= 4.1.6) - activesupport (= 4.1.6) - bundler (>= 1.3.0, < 2.0) - railties (= 4.1.6) - sprockets-rails (~> 2.0) - railties (4.1.6) - actionpack (= 4.1.6) - activesupport (= 4.1.6) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + loofah (2.1.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + lumberjack (1.0.12) + mail (2.7.0) + mini_mime (>= 0.1.1) + method_source (0.9.0) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_mime (1.0.0) + mini_portile2 (2.3.0) + minitest (5.11.2) + nenv (0.3.0) + nio4r (2.2.0) + nokogiri (1.8.1) + mini_portile2 (~> 2.3.0) + notiffany (0.1.1) + nenv (~> 0.1) + shellany (~> 0.0) + pry (0.11.3) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + public_suffix (3.0.1) + rack (2.0.3) + rack-test (0.8.2) + rack (>= 1.0, < 3) + rails (5.1.4) + actioncable (= 5.1.4) + actionmailer (= 5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) + activemodel (= 5.1.4) + activerecord (= 5.1.4) + activesupport (= 5.1.4) + bundler (>= 1.3.0) + railties (= 5.1.4) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + railties (5.1.4) + actionpack (= 5.1.4) + activesupport (= 5.1.4) + method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (10.3.2) - rspec-core (3.1.7) - rspec-support (~> 3.1.0) - rspec-expectations (3.1.2) + rake (12.3.0) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + rspec (3.7.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-core (3.7.1) + rspec-support (~> 3.7.0) + rspec-expectations (3.7.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.1.0) - rspec-mocks (3.1.3) - rspec-support (~> 3.1.0) - rspec-rails (3.1.0) + rspec-support (~> 3.7.0) + rspec-mocks (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-rails (3.7.2) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.1.0) - rspec-expectations (~> 3.1.0) - rspec-mocks (~> 3.1.0) - rspec-support (~> 3.1.0) - rspec-support (3.1.2) - sass (3.4.7) - sprockets (2.12.3) - hike (~> 1.2) - multi_json (~> 1.0) - rack (~> 1.0) - tilt (~> 1.1, != 1.3.0) - sprockets-rails (2.2.0) - actionpack (>= 3.0) - activesupport (>= 3.0) - sprockets (>= 2.8, < 4.0) - sqlite3 (1.3.9) - thor (0.19.1) - thread_safe (0.3.4) - tilt (1.4.1) - tzinfo (1.2.2) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-support (~> 3.7.0) + rspec-support (3.7.0) + ruby_dep (1.5.0) + sass (3.5.5) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + shellany (0.0.1) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.3.13) + thor (0.20.0) + thread_safe (0.3.6) + tzinfo (1.2.4) thread_safe (~> 0.1) - xpath (2.0.0) + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + xpath (2.1.0) nokogiri (~> 1.3) PLATFORMS @@ -138,12 +218,14 @@ PLATFORMS DEPENDENCIES bootstrap-sass - capybara (~> 2.4.4) - capybara-webkit (~> 1.3.1) + byebug + capybara (< 2.14) + capybara-webkit (~> 1.14) database_cleaner + guard-rspec rspec-rails smart_listing! sqlite3 BUNDLED WITH - 1.12.5 + 1.16.1 diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..3215f01 --- /dev/null +++ b/Guardfile @@ -0,0 +1,70 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +## Uncomment and set this to only include directories you want to watch +# directories %w(app lib config test spec features) \ +# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")} + +## Note: if you are using the `directories` clause above and you are not +## watching the project directory ('.'), then you will want to move +## the Guardfile to a watched dir and symlink it back, e.g. +# +# $ mkdir config +# $ mv Guardfile config/ +# $ ln -s config/Guardfile . +# +# and, you'll have to watch "config/Guardfile" instead of "Guardfile" + +# Note: The cmd option is now required due to the increasing number of ways +# rspec may be run, below are examples of the most common uses. +# * bundler: 'bundle exec rspec' +# * bundler binstubs: 'bin/rspec' +# * spring: 'bin/rspec' (This will use spring if running and you have +# installed the spring binstubs per the docs) +# * zeus: 'zeus rspec' (requires the server to be started separately) +# * 'just' rspec: 'rspec' + +guard :rspec, cmd: "bundle exec rspec" do + require "guard/rspec/dsl" + dsl = Guard::RSpec::Dsl.new(self) + + # Feel free to open issues for suggestions and improvements + + # RSpec files + rspec = dsl.rspec + watch(rspec.spec_helper) { rspec.spec_dir } + watch(rspec.spec_support) { rspec.spec_dir } + watch(rspec.spec_files) + + # Ruby files + ruby = dsl.ruby + dsl.watch_spec_files_for(ruby.lib_files) + + # Rails files + rails = dsl.rails(view_extensions: %w(erb haml slim)) + dsl.watch_spec_files_for(rails.app_files) + dsl.watch_spec_files_for(rails.views) + + watch(rails.controllers) do |m| + [ + rspec.spec.call("routing/#{m[1]}_routing"), + rspec.spec.call("controllers/#{m[1]}_controller"), + rspec.spec.call("acceptance/#{m[1]}") + ] + end + + # Rails config changes + watch(rails.spec_helper) { rspec.spec_dir } + watch(rails.routes) { "#{rspec.spec_dir}/routing" } + watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" } + + # Capybara features specs + watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") } + watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") } + + # Turnip features and steps + watch(%r{^spec/acceptance/(.+)\.feature$}) + watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m| + Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance" + end +end diff --git a/README.md b/README.md index 0eeed43..8774147 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,12 @@ Also, you need to add SmartListing to your asset pipeline: //= require smart_listing ``` +__Rails >= 5.1 users__: Rails 5.1 has dropped jQuery dependency from the default stack in favour of `rails-ujs`. SmartListing still requires jQuery so make sure that you use `jquery_ujs` from `jquery-rails` gem and have following requires in your asset pipeline before `smart_listing`: +``` +//= require jquery +//= require jquery_ujs +``` + ### Initializer Optionally you can also install some configuration initializer: @@ -73,7 +79,7 @@ smart_listing_render(:users) - unless smart_listing.empty? %table %thead - %tr + %tr %th User name %th Email %tbody @@ -82,7 +88,7 @@ smart_listing_render(:users) %td= user.name %td= user.email - = smart_listing.paginate + = smart_listing.paginate - else %p.warning No records! ``` @@ -112,7 +118,7 @@ SmartListing supports two modes of sorting: implicit and explicit. Implicit mode - unless smart_listing.empty? %table %thead - %tr + %tr %th= smart_listing.sortable "User name", :name %th= smart_listing.sortable "Email", :email %tbody @@ -121,12 +127,12 @@ SmartListing supports two modes of sorting: implicit and explicit. Implicit mode %td= user.name %td= user.email - = smart_listing.paginate + = smart_listing.paginate - else %p.warning No records! ``` -In this case `:name` and `:email` are sorting column names. `Builder#sortable` renders special link containing column name and sort order (either `asc`, `desc`, or empty value). +In this case `:name` and `:email` are sorting column names. `Builder#sortable` renders special link containing column name and sort order (either `asc`, `desc`, or empty value). You can also specify default sort order in the controller: @@ -136,7 +142,7 @@ You can also specify default sort order in the controller: Implicit mode is convenient with simple data sets. In case you want to sort by joined column names, we advise you to use explicit sorting: ```ruby -@users = smart_listing_create :users, User.active.joins(:stats), partial: "users/listing", +@users = smart_listing_create :users, User.active.joins(:stats), partial: "users/listing", sort_attributes: [[:last_signin, "stats.last_signin_at"]], default_sort: {last_signin: "desc"} ``` @@ -153,7 +159,7 @@ In order to allow managing and editing list items, we need to reorganize our vie - unless smart_listing.empty? %table %thead - %tr + %tr %th= smart_listing.sortable "User name", "name" %th= smart_listing.sortable "Email", "email" %th @@ -161,9 +167,9 @@ In order to allow managing and editing list items, we need to reorganize our vie - smart_listing.collection.each do |user| %tr.editable{data: {id: user.id}} = smart_listing.render partial: 'users/user', locals: {user: user} - = smart_listing.item_new colspan: 3, link: new_user_path + = smart_listing.item_new colspan: 3, link: new_user_path - = smart_listing.paginate + = smart_listing.paginate - else %p.warning No records! ``` @@ -174,7 +180,7 @@ In order to allow managing and editing list items, we need to reorganize our vie <%= smart_listing_item :users, :new, @new_user, "users/form" %> ``` -Note that `new` action does not need to create SmartListing (via `smart_listing_create`). It just initializes `@new_user` and renders JS view. +Note that `new` action does not need to create SmartListing (via `smart_listing_create`). It just initializes `@new_user` and renders JS view. New partial for user (`users/user`) may look like this: ```haml @@ -204,10 +210,10 @@ Partial name supplied to `smart_listing_item` (`users/form`) references `@user` = form_for object, url: object.new_record? ? users_path : user_path(object), remote: true do |f| %p - Name: + Name: = f.text_field :name %p - Email: + Email: = f.text_field :email %p= f.submit "Save" ``` @@ -228,7 +234,7 @@ SmartListing controls allow you to change somehow presented data. This is typica .filter.input-append = text_field_tag :filter, '', class: "search", placeholder: "Type name here", autocomplete: "off" %button.btn.disabled{type: "submit"} - %i.icon.icon-search + %span.glyphicon.glyphicon-search ``` This gives you nice Bootstrap-enabled filter field with keychange handler. Of course you can use any other form fields in controls too. @@ -262,7 +268,7 @@ SmartListing.configure(:awesome_profile) do |config| end ``` -In order to use this profile, create helper method named `smart_listing_config_profile` returning profile name and put into your JS `SmartListing.config.merge()` function call. `merge()` function expects parameter with config attributes hash or reads body data-attribute named `smart-listing-config`. Hash of config attributes can be obtained by using helper method `SmartListing.config(:awesome_profile).to_json`. +In order to use this profile, create helper method named `smart_listing_config_profile` returning profile name and put into your JS `SmartListing.config.merge()` function call. `merge()` function expects parameter with config attributes hash or reads body data-attribute named `smart-listing-config`. Hash of config attributes can be obtained by using helper method `SmartListing.config(:awesome_profile).to_json`. ## Not enough? diff --git a/app/assets/javascripts/smart_listing.coffee.erb b/app/assets/javascripts/smart_listing.coffee.erb index 040a8dc..26313e0 100644 --- a/app/assets/javascripts/smart_listing.coffee.erb +++ b/app/assets/javascripts/smart_listing.coffee.erb @@ -1,3 +1,10 @@ +# endsWith polyfill +if !String::endsWith + String::endsWith = (search, this_len) -> + if this_len == undefined or this_len > @length + this_len = @length + @substring(this_len - (search.length), this_len) == search + # Useful when SmartListing target url is different than current one $.rails.href = (element) -> element.attr("href") || element.data("<%= SmartListing.config.data_attributes(:href) %>") || window.location.pathname @@ -24,6 +31,9 @@ class window.SmartListing @element_template: (name)-> @options["constants"]["element_templates"][name] + @bootstrap_commands: (name)-> + @options["constants"]["bootstrap_commands"][name] + @config: Config @@ -319,8 +329,8 @@ $.fn.smart_listing.observeField = (field, opts = {}) -> , 400) $.fn.smart_listing.showPopover = (elem, body) -> - elem.popover("destroy") - elem.popover(content: body, html: true, trigger: "manual", title: null) + elem.popover(SmartListing.config.bootstrap_commands("popover_destroy")) + elem.popover(content: body, html: true, trigger: "manual") elem.popover("show") $.fn.smart_listing.showConfirmation = (confirmation_elem, msg, confirm_callback) -> @@ -333,12 +343,12 @@ $.fn.smart_listing.showConfirmation = (confirmation_elem, msg, confirm_callback) editable = $(event.currentTarget).closest(SmartListing.config.class_name("editable")) confirm_callback(confirmation_elem) $(confirmation_elem).click() - $(confirmation_elem).popover("destroy") + $(confirmation_elem).popover(SmartListing.config.bootstrap_commands("popover_destroy")) ) .append(" ") .append($(" +<% end %> + <%= smart_listing_render %> diff --git a/spec/dummy/config/environments/test.rb b/spec/dummy/config/environments/test.rb index 053f5b6..82ca386 100644 --- a/spec/dummy/config/environments/test.rb +++ b/spec/dummy/config/environments/test.rb @@ -5,7 +5,7 @@ # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true + config.cache_classes = false # Do not eager load code on boot. This avoids loading your whole application # just for the purpose of running a single test. If you are using a tool that diff --git a/spec/dummy/config/initializers/smart_listing.rb b/spec/dummy/config/initializers/smart_listing.rb index da8b46b..c5bff54 100644 --- a/spec/dummy/config/initializers/smart_listing.rb +++ b/spec/dummy/config/initializers/smart_listing.rb @@ -10,7 +10,7 @@ #:unlimited_per_page => false, # allow infinite page size #:paginate => true, # allow pagination #:memorize_per_page => false, # save per page settings in the cookie - #:page_sizes => DEFAULT_PAGE_SIZES, # set available page sizes array + :page_sizes => [3, 10], # set available page sizes array #:kaminari_options => {:theme => "smart_listing"}, # Kaminari's paginate helper options #:sort_dirs => [nil, "asc", "desc"], # Default sorting directions cycle of sortables }) diff --git a/spec/dummy/db/migrate/20141028214800_user.rb b/spec/dummy/db/migrate/20141028214800_user.rb deleted file mode 100644 index 895bd36..0000000 --- a/spec/dummy/db/migrate/20141028214800_user.rb +++ /dev/null @@ -1,4 +0,0 @@ -class User < ActiveRecord::Migration - def change - end -end diff --git a/spec/dummy/db/migrate/20180126065408_create_user.rb b/spec/dummy/db/migrate/20180126065408_create_user.rb new file mode 100644 index 0000000..1832a64 --- /dev/null +++ b/spec/dummy/db/migrate/20180126065408_create_user.rb @@ -0,0 +1,9 @@ +class CreateUser < ActiveRecord::Migration[5.1] + def change + create_table :users do |t| + t.string :name + t.string :email + t.boolean :boolean + end + end +end diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb index 30d31d6..187761d 100644 --- a/spec/dummy/db/schema.rb +++ b/spec/dummy/db/schema.rb @@ -1,4 +1,3 @@ -# encoding: UTF-8 # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -11,11 +10,12 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141028214800) do +ActiveRecord::Schema.define(version: 20180126065408) do - create_table "users", force: true do |t| + create_table "users", force: :cascade do |t| t.string "name" t.string "email" + t.boolean "boolean" end end diff --git a/spec/dummy/db/seeds.rb b/spec/dummy/db/seeds.rb new file mode 100644 index 0000000..e632b37 --- /dev/null +++ b/spec/dummy/db/seeds.rb @@ -0,0 +1,8 @@ +User.find_or_create_by(id: 1, name: "Betty", email: "betty@email.com", boolean: false) +User.find_or_create_by(id: 2, name: "Aaron", email: "aaron@email.com", boolean: true) +User.find_or_create_by(id: 3, name: "Jane", email: "jane@test.eu", boolean: false) +User.find_or_create_by(id: 4, name: "Edward", email: "edward@test.eu", boolean: true) +User.find_or_create_by(id: 5, name: "Nicholas", email: "salohcin@email.com", boolean: false) +User.find_or_create_by(id: 6, name: "Lisa", email: "asil@email.com", boolean: true) +User.find_or_create_by(id: 7, name: "Sara", email: "aras@test.eu", boolean: false) +User.find_or_create_by(id: 8, name: "Robin", email: "nibor@test.eu", boolean: true) diff --git a/spec/dummy/fixtures/users.yml b/spec/dummy/fixtures/users.yml new file mode 100644 index 0000000..d332125 --- /dev/null +++ b/spec/dummy/fixtures/users.yml @@ -0,0 +1,40 @@ +user1: + id: 1 + name: "Betty" + email: "betty@email.com" + boolean: false +user2: + id: 2 + name: "Aaron" + email: "aaron@email.com" + boolean: true +user3: + id: 3 + name: "Jane" + email: "jane@test.eu" + boolean: false +user4: + id: 4 + name: "Edward" + email: "edward@test.eu" + boolean: true +user5: + id: 5 + name: "Nicholas" + email: "salohcin@email.com" + boolean: false +user6: + id: 6 + name: "Lisa" + email: "asil@email.com" + boolean: true +user7: + id: 7 + name: "Sara" + email: "aras@test.eu" + boolean: false +user8: + id: 8 + name: "Robin" + email: "nibor@test.eu" + boolean: true diff --git a/spec/features/custom_filters_spec.rb b/spec/features/custom_filters_spec.rb new file mode 100644 index 0000000..d54e041 --- /dev/null +++ b/spec/features/custom_filters_spec.rb @@ -0,0 +1,69 @@ +require 'rails_helper' + +feature 'Combine custom filtering' do + fixtures :users + + scenario 'The user search user, change pagination and change page', js: true do + + visit admin_users_path + #page_sizes => [3, 10] + within(".pagination-per-page") { click_on "10" } + expect(page).to have_selector('tr.editable', count: 8) + fill_in "filter", with: "test" + expect(page).to have_selector('tr.editable', count: 4) + within(".pagination-per-page") { click_on "3" } + within(".pagination") { click_on "2" } + expect(page).to have_selector('tr.editable', count: 1) + + end + + scenario 'The user sort users and change page', js: true do + + visit admin_users_path + find('.name a.sortable').click + expect(page).to have_content("Aaron") + expect(page).to_not have_content("Jane") + within(".pagination") { click_on "2" } + expect(page).to have_content("Jane") + expect(page).to_not have_content("Aaron") + + end + + scenario 'The user combine filters', js: true do + + visit admin_users_path + fill_in "filter", with: "email" + find('input#boolean').click + expect(page).to have_selector('tr.editable', count: 2) + + end + + scenario 'The user combine filters and sort users', js: true do + + visit admin_users_path + fill_in "filter", with: "test" + find('input#boolean').click + wait_for_ajax + expect(page).to have_selector('tr.editable', count: 2) + click_link 'Name' + expect(page).to have_selector('tr.editable', count: 2) + expect(page.find(:css, "tbody > tr:nth-child(1)")).to have_content("Edward") + expect(page.find(:css, "tbody > tr:nth-child(2)")).to have_content("Robin") + + end + + scenario 'The user combine filters, sort and change page', js: true do + + visit admin_users_path + check 'boolean' + wait_for_ajax + expect(find(:css, '.email a.sortable')[:href]).to include("boolean") + click_link 'Email' + expect(page.find(:css, "tbody > tr:nth-child(2)")).to have_content("Lisa") + within(".pagination") { click_on "2" } + expect(page.find(:css, "tbody > tr:nth-child(1)")).to have_content("Robin") + expect(page.find(:css, '.count')).to have_content("4") + + end + +end diff --git a/spec/features/manage_items_spec.rb b/spec/features/manage_items_spec.rb index 1fea7ae..3607173 100644 --- a/spec/features/manage_items_spec.rb +++ b/spec/features/manage_items_spec.rb @@ -41,6 +41,6 @@ visit admin_users_path find('.change_name').click - expect(page).to_not have_content("Changed Name") + expect(page).to have_content("Changed Name") end end diff --git a/spec/features/view_items_spec.rb b/spec/features/view_items_spec.rb index c0b4442..00e2fb4 100644 --- a/spec/features/view_items_spec.rb +++ b/spec/features/view_items_spec.rb @@ -1,49 +1,44 @@ require 'rails_helper' feature 'View a list of items' do + fixtures :users scenario 'The user navigate through users', js: true do - 11.times { |i| User.create!(name: "Name#{i}", email: "Email#{i}") } visit root_path - - expect(page).to have_content("Name0") - expect(page).to_not have_content("Name10") + #page_sizes => [3, 10] + expect(page).to have_content("Betty") + expect(page).to_not have_content("Edward") within(".pagination") { click_on "2" } - expect(page).to have_content("Name10") - expect(page).to_not have_content("Name0") + expect(page).to have_content("Edward") + expect(page).to_not have_content("Betty") end scenario "The user sort users", js: true do - User.create(name: "aaaName", email: "bbbEmail") - User.create(name: "bbbName", email: "aaaEmail") visit sortable_users_path - expect(find(:xpath, "//table/tbody/tr[1]")).to have_content("bbbName") - expect(find(:xpath, "//table/tbody/tr[2]")).to have_content("aaaName") - find('.name a').click + expect(find(:xpath, "//table/tbody/tr[1]")).to have_content("Aaron") + expect(find(:xpath, "//table/tbody/tr[2]")).to have_content("Betty") - expect(find(:xpath, "//table/tbody/tr[1]")).to have_content("aaaName") - expect(find(:xpath, "//table/tbody/tr[2]")).to have_content("bbbName") + find('.name a').click + expect(find(:xpath, "//table/tbody/tr[1]")).to have_content("Sara") + expect(find(:xpath, "//table/tbody/tr[2]")).to have_content("Robin") end scenario "The user search user", js: true do - User.create(name: "Name1", email: "Email1") - User.create(name: "Name2", email: "Email2") - - visit searchable_users_path + visit admin_users_path - fill_in "filter", with: "1" + fill_in "filter", with: "ja" - expect(page).to have_content("Name1") - expect(page).to_not have_content("Name2") + expect(page).to have_content("Jane") + expect(page).to_not have_content("Aaron") - fill_in "filter", with: "3" + fill_in "filter", with: "ni" - expect(page).to_not have_content("Name1") - expect(page).to_not have_content("Name2") + expect(page).to_not have_content("Nicholas") + expect(page).to_not have_content("Jane") end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 4c69e00..11a1850 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -12,7 +12,8 @@ # run twice. It is recommended that you do not name files matching this glob to # end with _spec.rb. You can configure this pattern with the --pattern # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. -Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } + +Dir[Rails.root.join("../support/**/*.rb")].each { |f| require f } # Checks for pending migrations before tests are run. # If you are not using ActiveRecord, you can remove this line. @@ -20,7 +21,7 @@ RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.fixture_path = "#{::Rails.root}/fixtures" # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false @@ -42,6 +43,8 @@ # https://relishapp.com/rspec/rspec-rails/docs config.infer_spec_type_from_file_location! + config.include WaitForAjax, type: :feature + config.before :each do DatabaseCleaner.start end diff --git a/spec/support/capybara/wait_for_ajax.rb b/spec/support/capybara/wait_for_ajax.rb new file mode 100644 index 0000000..b90fc11 --- /dev/null +++ b/spec/support/capybara/wait_for_ajax.rb @@ -0,0 +1,11 @@ +module WaitForAjax + def wait_for_ajax + Timeout.timeout(Capybara.default_max_wait_time) do + loop until finished_all_ajax_requests? + end + end + + def finished_all_ajax_requests? + page.evaluate_script('jQuery.active').zero? + end +end