diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..7f69394c
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,84 @@
+---
+name: CI
+
+on:
+ push:
+ branches:
+ - '**'
+ pull_request:
+ branches:
+ - '**'
+ schedule:
+ - cron: '0 4 1 * *'
+
+jobs:
+ rubocop:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Setup Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: '3.0'
+
+ - name: Bundler
+ run: bundle install
+
+ - name: Rubocop
+ run: bin/rubocop
+
+ rspec:
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ ruby:
+ - '4.0'
+ - '3.4'
+ - '3.3'
+ - '3.2'
+ - '3.1'
+ - '3.0'
+ rails:
+ - rails_8.1
+ - rails_8.0
+ - rails_7.2
+ - rails_7.1
+ - rails_7.0
+ - rails_6.1
+
+ exclude:
+ - ruby: '3.0'
+ rails: 'rails_7.2'
+ - ruby: '3.0'
+ rails: 'rails_8.0'
+ - ruby: '3.0'
+ rails: 'rails_8.1'
+
+ - ruby: '3.1'
+ rails: 'rails_8.0'
+ - ruby: '3.1'
+ rails: 'rails_8.1'
+
+ env:
+ # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
+ BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.rails }}.gemfile
+ # Check for frozen strings
+ RUBYOPT: "--enable=frozen-string-literal --debug=frozen-string-literal"
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Setup Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: true
+
+ - name: RSpec
+ run: bin/rspec
diff --git a/.rspec b/.rspec
index 1892c522..ce0f67a2 100644
--- a/.rspec
+++ b/.rspec
@@ -1,3 +1,2 @@
---color
---format=documentation
--require spec_helper
+--warnings
diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 00000000..6cd43a2c
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,49 @@
+---
+plugins:
+ - rubocop-capybara
+ - rubocop-performance
+ - rubocop-rake
+ - rubocop-rspec
+
+inherit_from:
+ - .rubocop_todo.yml
+
+AllCops:
+ NewCops: enable
+ SuggestExtensions: true
+ TargetRubyVersion: 3.0
+ Exclude:
+ - bin/*
+ - gemfiles/*
+
+Gemspec/RequireMFA:
+ Enabled: false
+
+Style/Documentation:
+ Enabled: false
+
+Naming/FileName:
+ Exclude:
+ - lib/simple-navigation.rb
+
+###########
+# METRICS #
+###########
+
+Metrics/ClassLength:
+ Exclude:
+ - spec/**/*
+
+Metrics/MethodLength:
+ Exclude:
+ - spec/**/*
+
+#########
+# RSPEC #
+#########
+
+RSpec/NestedGroups:
+ Max: 6
+
+RSpec/MultipleMemoizedHelpers:
+ Max: 8
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
new file mode 100644
index 00000000..252b05b5
--- /dev/null
+++ b/.rubocop_todo.yml
@@ -0,0 +1,39 @@
+---
+
+Layout/LineLength:
+ Enabled: false
+
+Naming/VariableNumber:
+ Enabled: false
+
+Style/BlockDelimiters:
+ Enabled: false
+
+#########
+# RSPEC #
+#########
+
+RSpec/SubjectStub:
+ Enabled: false
+
+RSpec/NamedSubject:
+ Enabled: false
+
+RSpec/VerifiedDoubles:
+ Enabled: false
+
+RSpec/ContextWording:
+ Enabled: false
+
+RSpec/MessageSpies:
+ Enabled: false
+
+RSpec/IndexedLet:
+ Enabled: false
+
+############
+# CAPYBARA #
+############
+
+Capybara/NegationMatcher:
+ Enabled: false
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 73ad5af5..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-before_install:
- - gem install bundler
-
-matrix:
- include:
- - rvm: 2.5.8
- gemfile: gemfiles/rails-6-1-stable.gemfile
- - rvm: 2.6.7
- gemfile: gemfiles/rails-6-1-stable.gemfile
- - rvm: 2.7.3
- gemfile: gemfiles/rails-6-1-stable.gemfile
- - rvm: 2.5.3
- gemfile: gemfiles/rails-6-0-stable.gemfile
- - rvm: 2.6.0
- gemfile: gemfiles/rails-6-0-stable.gemfile
- - rvm: 2.5.1
- gemfile: gemfiles/rails-5-2-stable.gemfile
- - rvm: 2.4.5
- gemfile: gemfiles/rails-4-2-stable.gemfile
- - rvm: 2.3.3
- gemfile: gemfiles/rails-4-1-stable.gemfile
- - rvm: 2.3.3
- gemfile: gemfiles/rails-3-2-stable.gemfile
diff --git a/Appraisals b/Appraisals
new file mode 100644
index 00000000..dcdd1cb2
--- /dev/null
+++ b/Appraisals
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+# To update files in gemfiles/ directory:
+# rm gemfiles/*
+# bin/appraisal generate
+
+# To run tests:
+# bin/appraisal rails_8.1 bundle install
+# bin/appraisal rails_8.1 rake
+# bin/appraisal rails_8.1 rspec
+
+appraise 'rails_6.1' do
+ gem 'railties', '~> 6.1.0'
+ gem 'rspec-rails'
+ gem 'concurrent-ruby', '1.3.4'
+
+ # Fix:
+ # warning: drb was loaded from the standard library, but is not part of the default gems starting from Ruby 3.4.0.
+ # You can add drb to your Gemfile or gemspec to silence this warning.
+ install_if '-> { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0") }' do
+ gem 'base64'
+ gem 'bigdecimal'
+ gem 'drb'
+ gem 'mutex_m'
+ end
+
+ install_if '-> { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("4.0.0") }' do
+ gem 'benchmark'
+ end
+end
+
+appraise 'rails_7.0' do
+ gem 'railties', '~> 7.0.0'
+ gem 'rspec-rails'
+end
+
+appraise 'rails_7.1' do
+ gem 'railties', '~> 7.1.0'
+ gem 'rspec-rails'
+end
+
+appraise 'rails_7.2' do
+ gem 'railties', '~> 7.2.0'
+ gem 'rspec-rails'
+end
+
+appraise 'rails_8.0' do
+ gem 'railties', '~> 8.0.0'
+ gem 'rspec-rails'
+end
+
+appraise 'rails_8.1' do
+ gem 'railties', '~> 8.1.0'
+ gem 'rspec-rails'
+end
diff --git a/Gemfile b/Gemfile
index fa75df15..ad06fe67 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,24 @@
+# frozen_string_literal: true
+
source 'https://rubygems.org'
gemspec
+
+# Dev libs
+gem 'appraisal', git: 'https://github.com/thoughtbot/appraisal.git'
+gem 'capybara'
+gem 'memfs', git: 'https://github.com/simonc/memfs.git'
+gem 'rake'
+gem 'rdoc'
+gem 'rspec'
+gem 'simplecov'
+gem 'tzinfo'
+gem 'warning'
+
+# Dev tools / linter
+gem 'guard-rspec', require: false
+gem 'rubocop', require: false
+gem 'rubocop-capybara', require: false
+gem 'rubocop-performance', require: false
+gem 'rubocop-rake', require: false
+gem 'rubocop-rspec', require: false
diff --git a/Guardfile b/Guardfile
index f4357e62..881f7b62 100644
--- a/Guardfile
+++ b/Guardfile
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
guard :rspec, all_after_pass: true, failed_mode: :none do
watch(%r{^spec/.+_spec\.rb$})
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^spec/fake_app/.+\.rb$}) { 'spec/integration' }
- watch('spec/spec_helper.rb') { 'spec' }
+ watch('spec/spec_helper.rb') { 'spec' }
end
diff --git a/README.md b/README.md
index a12b96b4..422c587b 100644
--- a/README.md
+++ b/README.md
@@ -31,30 +31,19 @@ Fork, fix, then send a Pull Request.
To run the test suite locally against all supported frameworks:
- % bundle install
- % rake spec:all
+```sh
+bundle install
+bin/appraisal bundle install
+bin/appraisal rspec
+bin/appraisal rspec ./spec/requests/users_spec.rb
+```
To target the test suite against one framework:
- % rake spec:rails-4-2-stable
-
-You can find a list of supported spec tasks by running rake -T. You may also find it useful to run a specific test for a specific framework. To do so, you'll have to first make sure you have bundled everything for that configuration, then you can run the specific test:
-
-% BUNDLE_GEMFILE='gemfiles/rails-4-2-stable.gemfile' bundle install -j 4
-% BUNDLE_GEMFILE='gemfiles/rails-4-2-stable.gemfile' bundle exec rspec ./spec/requests/users_spec.rb
-
-### Rake and Bundler
-
-If you use a shell plugin (like oh-my-zsh:bundler) that auto-prefixes commands with `bundle exec` using the `rake` command will fail.
-
-Get the original command with `type -a rake`:
-
- % type -a rake
- rake is an alias for bundled_rake
- rake is /Users/username/.rubies/ruby-2.2.3/bin/rake
- rake is /usr/bin/rake
-
-In this situation `/Users/username/.rubies/ruby-2.2.3/bin/rake` is the command you should use.
+```sh
+bin/appraisal rails_8.1 rspec
+bin/appraisal rails_8.1 rspec ./spec/requests/users_spec.rb
+```
## License
diff --git a/Rakefile b/Rakefile
index feeb7998..1a7ff9b6 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,37 +1,12 @@
-require 'bundler'
-Bundler::GemHelper.install_tasks
+# frozen_string_literal: true
-require 'rspec/core'
+require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
-
require 'rdoc/task'
RSpec::Core::RakeTask.new(:spec)
-
task default: 'spec'
-namespace :spec do
- mappers = %w[
- rails-3-2-stable
- rails-4-1-stable
- rails-4-2-stable
- rails-5-2-stable
- rails-6-0-stable
- rails-6-1-stable
- ]
-
- mappers.each do |gemfile|
- desc "Run Tests against #{gemfile}"
- task gemfile do
- sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle -j 4 --quiet"
- sh "BUNDLE_GEMFILE='gemfiles/#{gemfile}.gemfile' bundle exec rake -t spec"
- end
- end
-
- desc 'Run Tests against all ORMs'
- task all: mappers
-end
-
RDoc::Task.new do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'SimpleNavigation'
diff --git a/bin/_guard-core b/bin/_guard-core
new file mode 100755
index 00000000..3b368e69
--- /dev/null
+++ b/bin/_guard-core
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+#
+# This file was generated by Bundler.
+#
+# The application '_guard-core' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
+
+require "rubygems"
+require "bundler/setup"
+
+load Gem.bin_path("guard", "_guard-core")
diff --git a/bin/appraisal b/bin/appraisal
new file mode 100755
index 00000000..620da794
--- /dev/null
+++ b/bin/appraisal
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+#
+# This file was generated by Bundler.
+#
+# The application 'appraisal' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
+
+require "rubygems"
+require "bundler/setup"
+
+load Gem.bin_path("appraisal", "appraisal")
diff --git a/bin/guard b/bin/guard
new file mode 100755
index 00000000..643c81f6
--- /dev/null
+++ b/bin/guard
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+#
+# This file was generated by Bundler.
+#
+# The application 'guard' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
+
+require "rubygems"
+require "bundler/setup"
+
+load Gem.bin_path("guard", "guard")
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 00000000..9efbee99
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+#
+# This file was generated by Bundler.
+#
+# The application 'rake' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
+
+require "rubygems"
+require "bundler/setup"
+
+load Gem.bin_path("rake", "rake")
diff --git a/bin/rspec b/bin/rspec
new file mode 100755
index 00000000..93e191c2
--- /dev/null
+++ b/bin/rspec
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+#
+# This file was generated by Bundler.
+#
+# The application 'rspec' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
+
+require "rubygems"
+require "bundler/setup"
+
+load Gem.bin_path("rspec-core", "rspec")
diff --git a/bin/rubocop b/bin/rubocop
new file mode 100755
index 00000000..d73598dc
--- /dev/null
+++ b/bin/rubocop
@@ -0,0 +1,16 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+#
+# This file was generated by Bundler.
+#
+# The application 'rubocop' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
+
+require "rubygems"
+require "bundler/setup"
+
+load Gem.bin_path("rubocop", "rubocop")
diff --git a/gemfiles/rails-3-2-stable.gemfile b/gemfiles/rails-3-2-stable.gemfile
deleted file mode 100644
index 5b62ac4b..00000000
--- a/gemfiles/rails-3-2-stable.gemfile
+++ /dev/null
@@ -1,11 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'rake', '< 11.0'
-gem 'railties', '~> 3.2.0'
-gem 'rspec-rails', '~> 3.2.1'
-
-if RUBY_VERSION >= '2.2.0'
- gem 'test-unit', '~> 3.0'
-end
-
-gemspec path: '../'
diff --git a/gemfiles/rails-4-1-stable.gemfile b/gemfiles/rails-4-1-stable.gemfile
deleted file mode 100644
index 57c4af92..00000000
--- a/gemfiles/rails-4-1-stable.gemfile
+++ /dev/null
@@ -1,7 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'rake', '< 11.0'
-gem 'railties', '~> 4.1.0'
-gem 'rspec-rails', '~> 3.2.1'
-
-gemspec path: '../'
diff --git a/gemfiles/rails-4-2-stable.gemfile b/gemfiles/rails-4-2-stable.gemfile
deleted file mode 100644
index 98206291..00000000
--- a/gemfiles/rails-4-2-stable.gemfile
+++ /dev/null
@@ -1,7 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'rake', '< 11.0'
-gem 'railties', '~> 4.2.0'
-gem 'rspec-rails', '~> 3.2.1'
-
-gemspec path: '../'
diff --git a/gemfiles/rails-5-2-stable.gemfile b/gemfiles/rails-5-2-stable.gemfile
deleted file mode 100644
index a5fb0470..00000000
--- a/gemfiles/rails-5-2-stable.gemfile
+++ /dev/null
@@ -1,7 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'rake', '< 11.0'
-gem 'railties', '~> 5.2.0'
-gem 'rspec-rails', '~> 3.8.2'
-
-gemspec path: '../'
diff --git a/gemfiles/rails-6-0-stable.gemfile b/gemfiles/rails-6-0-stable.gemfile
deleted file mode 100644
index 095cb349..00000000
--- a/gemfiles/rails-6-0-stable.gemfile
+++ /dev/null
@@ -1,9 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'rake', '< 11.0'
-
-# not yet
-gem 'railties', '~> 6.0.0'
-gem 'rspec-rails', '~> 3.8.2'
-
-gemspec path: '../'
diff --git a/gemfiles/rails-6-1-stable.gemfile b/gemfiles/rails-6-1-stable.gemfile
deleted file mode 100644
index c2024a32..00000000
--- a/gemfiles/rails-6-1-stable.gemfile
+++ /dev/null
@@ -1,9 +0,0 @@
-source 'https://rubygems.org'
-
-gem 'rake', '< 11.0'
-
-# not yet
-gem 'railties', '~> 6.1.0'
-gem 'rspec-rails', '~> 3.8.2'
-
-gemspec path: '../'
diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_6.1.gemfile
new file mode 100644
index 00000000..6a8fd9aa
--- /dev/null
+++ b/gemfiles/rails_6.1.gemfile
@@ -0,0 +1,35 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
+gem "capybara"
+gem "memfs", git: "https://github.com/simonc/memfs.git"
+gem "rake"
+gem "rdoc"
+gem "rspec"
+gem "simplecov"
+gem "tzinfo"
+gem "warning"
+gem "guard-rspec", require: false
+gem "rubocop", require: false
+gem "rubocop-capybara", require: false
+gem "rubocop-performance", require: false
+gem "rubocop-rake", require: false
+gem "rubocop-rspec", require: false
+gem "railties", "~> 6.1.0"
+gem "rspec-rails"
+gem "concurrent-ruby", "1.3.4"
+
+install_if -> { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0") } do
+ gem "base64"
+ gem "bigdecimal"
+ gem "drb"
+ gem "mutex_m"
+end
+
+install_if -> { Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("4.0.0") } do
+ gem "benchmark"
+end
+
+gemspec path: "../"
diff --git a/gemfiles/rails_7.0.gemfile b/gemfiles/rails_7.0.gemfile
new file mode 100644
index 00000000..6ce788a9
--- /dev/null
+++ b/gemfiles/rails_7.0.gemfile
@@ -0,0 +1,23 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
+gem "capybara"
+gem "memfs", git: "https://github.com/simonc/memfs.git"
+gem "rake"
+gem "rdoc"
+gem "rspec"
+gem "simplecov"
+gem "tzinfo"
+gem "warning"
+gem "guard-rspec", require: false
+gem "rubocop", require: false
+gem "rubocop-capybara", require: false
+gem "rubocop-performance", require: false
+gem "rubocop-rake", require: false
+gem "rubocop-rspec", require: false
+gem "railties", "~> 7.0.0"
+gem "rspec-rails"
+
+gemspec path: "../"
diff --git a/gemfiles/rails_7.1.gemfile b/gemfiles/rails_7.1.gemfile
new file mode 100644
index 00000000..fefba441
--- /dev/null
+++ b/gemfiles/rails_7.1.gemfile
@@ -0,0 +1,23 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
+gem "capybara"
+gem "memfs", git: "https://github.com/simonc/memfs.git"
+gem "rake"
+gem "rdoc"
+gem "rspec"
+gem "simplecov"
+gem "tzinfo"
+gem "warning"
+gem "guard-rspec", require: false
+gem "rubocop", require: false
+gem "rubocop-capybara", require: false
+gem "rubocop-performance", require: false
+gem "rubocop-rake", require: false
+gem "rubocop-rspec", require: false
+gem "railties", "~> 7.1.0"
+gem "rspec-rails"
+
+gemspec path: "../"
diff --git a/gemfiles/rails_7.2.gemfile b/gemfiles/rails_7.2.gemfile
new file mode 100644
index 00000000..bc5f4ab6
--- /dev/null
+++ b/gemfiles/rails_7.2.gemfile
@@ -0,0 +1,23 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
+gem "capybara"
+gem "memfs", git: "https://github.com/simonc/memfs.git"
+gem "rake"
+gem "rdoc"
+gem "rspec"
+gem "simplecov"
+gem "tzinfo"
+gem "warning"
+gem "guard-rspec", require: false
+gem "rubocop", require: false
+gem "rubocop-capybara", require: false
+gem "rubocop-performance", require: false
+gem "rubocop-rake", require: false
+gem "rubocop-rspec", require: false
+gem "railties", "~> 7.2.0"
+gem "rspec-rails"
+
+gemspec path: "../"
diff --git a/gemfiles/rails_8.0.gemfile b/gemfiles/rails_8.0.gemfile
new file mode 100644
index 00000000..7869e509
--- /dev/null
+++ b/gemfiles/rails_8.0.gemfile
@@ -0,0 +1,23 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
+gem "capybara"
+gem "memfs", git: "https://github.com/simonc/memfs.git"
+gem "rake"
+gem "rdoc"
+gem "rspec"
+gem "simplecov"
+gem "tzinfo"
+gem "warning"
+gem "guard-rspec", require: false
+gem "rubocop", require: false
+gem "rubocop-capybara", require: false
+gem "rubocop-performance", require: false
+gem "rubocop-rake", require: false
+gem "rubocop-rspec", require: false
+gem "railties", "~> 8.0.0"
+gem "rspec-rails"
+
+gemspec path: "../"
diff --git a/gemfiles/rails_8.1.gemfile b/gemfiles/rails_8.1.gemfile
new file mode 100644
index 00000000..f9b31152
--- /dev/null
+++ b/gemfiles/rails_8.1.gemfile
@@ -0,0 +1,23 @@
+# This file was generated by Appraisal
+
+source "https://rubygems.org"
+
+gem "appraisal", git: "https://github.com/thoughtbot/appraisal.git"
+gem "capybara"
+gem "memfs", git: "https://github.com/simonc/memfs.git"
+gem "rake"
+gem "rdoc"
+gem "rspec"
+gem "simplecov"
+gem "tzinfo"
+gem "warning"
+gem "guard-rspec", require: false
+gem "rubocop", require: false
+gem "rubocop-capybara", require: false
+gem "rubocop-performance", require: false
+gem "rubocop-rake", require: false
+gem "rubocop-rspec", require: false
+gem "railties", "~> 8.1.0"
+gem "rspec-rails"
+
+gemspec path: "../"
diff --git a/generators/navigation_config/navigation_config_generator.rb b/generators/navigation_config/navigation_config_generator.rb
index be81087f..449cb454 100644
--- a/generators/navigation_config/navigation_config_generator.rb
+++ b/generators/navigation_config/navigation_config_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class NavigationConfigGenerator < Rails::Generator::Base
def manifest
record do |m|
diff --git a/generators/navigation_config/templates/config/navigation.rb b/generators/navigation_config/templates/config/navigation.rb
index 2a11b180..48589406 100644
--- a/generators/navigation_config/templates/config/navigation.rb
+++ b/generators/navigation_config/templates/config/navigation.rb
@@ -1,41 +1,42 @@
-# -*- coding: utf-8 -*-
+# frozen_string_literal: true
+
# Configures your navigation
SimpleNavigation::Configuration.run do |navigation|
# Specify a custom renderer if needed.
# The default renderer is SimpleNavigation::Renderer::List which renders HTML lists.
# The renderer can also be specified as option in the render_navigation call.
- #navigation.renderer = Your::Custom::Renderer
+ # navigation.renderer = Your::Custom::Renderer
- # Specify the class that will be applied to active navigation items. Defaults to 'selected'
- #navigation.selected_class = 'selected'
+ # Specify the class that will be applied to active navigation items. Defaults to 'selected'
+ # navigation.selected_class = 'selected'
# Specify the class that will be applied to the current leaf of
# active navigation items. Defaults to 'simple-navigation-active-leaf'
- #navigation.active_leaf_class = 'simple-navigation-active-leaf'
+ # navigation.active_leaf_class = 'simple-navigation-active-leaf'
# Specify if item keys are added to navigation items as id. Defaults to true
- #navigation.autogenerate_item_ids = true
+ # navigation.autogenerate_item_ids = true
# You can override the default logic that is used to autogenerate the item ids.
# To do this, define a Proc which takes the key of the current item as argument.
# The example below would add a prefix to each key.
- #navigation.id_generator = Proc.new {|key| "my-prefix-#{key}"}
+ # navigation.id_generator = Proc.new {|key| "my-prefix-#{key}"}
# If you need to add custom html around item names, you can define a proc that
# will be called with the name you pass in to the navigation.
# The example below shows how to wrap items spans.
- #navigation.name_generator = Proc.new {|name, item| tag.span(name) }
+ # navigation.name_generator = Proc.new {|name, item| tag.span(name) }
# Specify if the auto highlight feature is turned on (globally, for the whole navigation). Defaults to true
- #navigation.auto_highlight = true
-
- # Specifies whether auto highlight should ignore query params and/or anchors when
- # comparing the navigation items with the current URL. Defaults to true
- #navigation.ignore_query_params_on_auto_highlight = true
- #navigation.ignore_anchors_on_auto_highlight = true
-
+ # navigation.auto_highlight = true
+
+ # Specifies whether auto highlight should ignore query params and/or anchors when
+ # comparing the navigation items with the current URL. Defaults to true
+ # navigation.ignore_query_params_on_auto_highlight = true
+ # navigation.ignore_anchors_on_auto_highlight = true
+
# If this option is set to true, all item names will be considered as safe (passed through html_safe). Defaults to false.
- #navigation.consider_item_names_as_safe = false
+ # navigation.consider_item_names_as_safe = false
# Define the primary navigation
navigation.items do |primary|
@@ -73,9 +74,9 @@
# you can also specify html attributes to attach to this particular level
# works for all levels of the menu
- #primary.dom_attributes = {id: 'menu-id', class: 'menu-class'}
+ # primary.dom_attributes = {id: 'menu-id', class: 'menu-class'}
# You can turn off auto highlighting for a specific level
- #primary.auto_highlight = false
+ # primary.auto_highlight = false
end
end
diff --git a/init.rb b/init.rb
deleted file mode 100644
index 470d4902..00000000
--- a/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-require File.dirname(__FILE__) + '/rails/init'
diff --git a/install.rb b/install.rb
deleted file mode 100644
index a62f1560..00000000
--- a/install.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-begin
- puts IO.read(File.join(File.dirname(__FILE__), 'README'))
-rescue Exception => e
- puts "The following error ocurred while installing the plugin: #{e.message}"
-end
diff --git a/lib/generators/navigation_config/navigation_config_generator.rb b/lib/generators/navigation_config/navigation_config_generator.rb
index f56ddf4d..c3004d9a 100644
--- a/lib/generators/navigation_config/navigation_config_generator.rb
+++ b/lib/generators/navigation_config/navigation_config_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class NavigationConfigGenerator < Rails::Generators::Base
def self.source_root
@source_root ||= begin
diff --git a/lib/simple-navigation.rb b/lib/simple-navigation.rb
index dc7685de..4a0f8b31 100644
--- a/lib/simple-navigation.rb
+++ b/lib/simple-navigation.rb
@@ -1 +1,3 @@
-require 'simple_navigation'
+# frozen_string_literal: true
+
+require_relative 'simple_navigation'
diff --git a/lib/simple_navigation.rb b/lib/simple_navigation.rb
index 1522fb20..eaf57fe9 100644
--- a/lib/simple_navigation.rb
+++ b/lib/simple_navigation.rb
@@ -1,24 +1,30 @@
-# cherry picking active_support stuff
+# frozen_string_literal: true
+
+# require ruby dependencies
+require 'cgi/escape'
+require 'forwardable'
+require 'json'
+require 'singleton'
+
+# require external dependencies
require 'active_support/core_ext/array'
require 'active_support/core_ext/hash'
+require 'active_support/core_ext/string'
require 'active_support/core_ext/module/attribute_accessors'
+require 'zeitwerk'
-require 'simple_navigation/version'
-require 'simple_navigation/configuration'
-require 'simple_navigation/item_adapter'
-require 'simple_navigation/item'
-require 'simple_navigation/item_container'
-require 'simple_navigation/items_provider'
-require 'simple_navigation/renderer'
-require 'simple_navigation/adapters'
-require 'simple_navigation/config_file_finder'
-require 'simple_navigation/railtie' if defined?(::Rails::Railtie)
-
-require 'forwardable'
+# load zeitwerk
+Zeitwerk::Loader.for_gem.tap do |loader|
+ loader.ignore("#{__dir__}/generators")
+ loader.ignore("#{__dir__}/simple-navigation.rb")
+ loader.setup
+end
# A plugin for generating a simple navigation. See README for resources on
# usage instructions.
module SimpleNavigation
+ require_relative 'simple_navigation/railtie' if defined?(Rails::Railtie)
+
mattr_accessor :adapter,
:adapter_class,
:config_files,
@@ -38,21 +44,21 @@ module SimpleNavigation
# Maps renderer keys to classes. The keys serve as shortcut in the
# render_navigation calls (renderer: :list)
self.registered_renderers = {
- list: SimpleNavigation::Renderer::List,
- links: SimpleNavigation::Renderer::Links,
+ list: SimpleNavigation::Renderer::List,
+ links: SimpleNavigation::Renderer::Links,
breadcrumbs: SimpleNavigation::Renderer::Breadcrumbs,
- text: SimpleNavigation::Renderer::Text,
- json: SimpleNavigation::Renderer::Json
+ text: SimpleNavigation::Renderer::Text,
+ json: SimpleNavigation::Renderer::Json
}
class << self
extend Forwardable
def_delegators :adapter, :context_for_eval,
- :current_page?,
- :request,
- :request_path,
- :request_uri
+ :current_page?,
+ :request,
+ :request_path,
+ :request_uri
def_delegators :adapter_class, :register
@@ -70,8 +76,8 @@ def framework
return :padrino if defined?(Padrino)
return :sinatra if defined?(Sinatra)
return :nanoc if defined?(Nanoc3)
- fail 'simple_navigation currently only works for Rails, Sinatra and ' \
- 'Padrino apps'
+
+ raise 'simple_navigation currently only works for Rails, Sinatra and Padrino apps'
end
# Loads the adapter for the current framework
@@ -138,7 +144,7 @@ def active_item_container_for(level)
when Integer then primary_navigation.active_item_container_for(level)
when Range then primary_navigation.active_item_container_for(level.min)
else
- fail ArgumentError, "Invalid navigation level: #{level}"
+ raise ArgumentError, "Invalid navigation level: #{level}"
end
end
diff --git a/lib/simple_navigation/adapters.rb b/lib/simple_navigation/adapters.rb
deleted file mode 100644
index 84764597..00000000
--- a/lib/simple_navigation/adapters.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'simple_navigation/adapters/base'
-
-module SimpleNavigation
- module Adapters
- autoload :Rails, 'simple_navigation/adapters/rails'
- autoload :Padrino, 'simple_navigation/adapters/padrino'
- autoload :Sinatra, 'simple_navigation/adapters/sinatra'
- autoload :Nanoc, 'simple_navigation/adapters/nanoc'
- end
-end
diff --git a/lib/simple_navigation/adapters/base.rb b/lib/simple_navigation/adapters/base.rb
index 7ff57798..e8324861 100644
--- a/lib/simple_navigation/adapters/base.rb
+++ b/lib/simple_navigation/adapters/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
module Adapters
# This is the base class for all adapters.
diff --git a/lib/simple_navigation/adapters/nanoc.rb b/lib/simple_navigation/adapters/nanoc.rb
index a3b83682..ba7811fb 100644
--- a/lib/simple_navigation/adapters/nanoc.rb
+++ b/lib/simple_navigation/adapters/nanoc.rb
@@ -1,14 +1,16 @@
+# frozen_string_literal: true
+
module SimpleNavigation
module Adapters
class Nanoc < Base
class << self
def register(root)
SimpleNavigation.set_env(root, 'development')
- Nanoc3::Context.send(:include, SimpleNavigation::Helpers)
+ Nanoc3::Context.include SimpleNavigation::Helpers
end
end
- def initialize(ctx)
+ def initialize(ctx) # rubocop:disable Lint/MissingSuper
@context = ctx
end
@@ -39,7 +41,7 @@ def content_tag(type, content, options = {})
private
def to_attributes(options)
- options.map { |k, v| v.nil? ? nil : "#{k}='#{v}'" }.compact.join(' ')
+ options.filter_map { |k, v| v.nil? ? nil : "#{k}='#{v}'" }.join(' ')
end
end
end
diff --git a/lib/simple_navigation/adapters/padrino.rb b/lib/simple_navigation/adapters/padrino.rb
index 4dd7359d..28b0e4b9 100644
--- a/lib/simple_navigation/adapters/padrino.rb
+++ b/lib/simple_navigation/adapters/padrino.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
module SimpleNavigation
module Adapters
class Padrino < Sinatra
- def self.register(app)
+ def self.register(_app)
SimpleNavigation.set_env(::Padrino.root, ::Padrino.env)
::Padrino::Application.send(:helpers, SimpleNavigation::Helpers)
end
diff --git a/lib/simple_navigation/adapters/rails.rb b/lib/simple_navigation/adapters/rails.rb
index 7b513da7..b809a247 100644
--- a/lib/simple_navigation/adapters/rails.rb
+++ b/lib/simple_navigation/adapters/rails.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
module Adapters
class Rails < Base
@@ -10,23 +12,19 @@ def self.register
# This delays the hook initialization using the on_load
# hooks, but does not change behaviour for existing
# rails versions.
- if ::Rails::VERSION::MAJOR >= 6
- ActiveSupport.on_load(:action_controller_base) do
- SimpleNavigation::Adapters::Rails.register_controller_helpers
- end
- else
- register_controller_helpers
+ ActiveSupport.on_load(:action_controller_base) do
+ SimpleNavigation::Adapters::Rails.register_controller_helpers
end
end
def self.register_controller_helpers
- ActionController::Base.send(:include, SimpleNavigation::Helpers)
+ ActionController::Base.include SimpleNavigation::Helpers
SimpleNavigation::Helpers.instance_methods.each do |m|
ActionController::Base.send(:helper_method, m.to_sym)
end
end
- def initialize(context)
+ def initialize(context) # rubocop:disable Lint/MissingSuper
@controller = extract_controller_from context
@template = template_from @controller
@request = @template.request if @template
@@ -47,21 +45,21 @@ def request_path
end
def context_for_eval
- template ||
- controller ||
- fail('no context set for evaluation the config file')
+ template ||
+ controller ||
+ raise('no context set for evaluation the config file')
end
def current_page?(url)
- template && template.current_page?(url)
+ template&.current_page?(url)
end
def link_to(name, url, options = {})
- template && template.link_to(link_title(name), url, options)
+ template&.link_to(link_title(name), url, options)
end
def content_tag(type, content, options = {})
- template && template.content_tag(type, html_safe(content), options)
+ template&.content_tag(type, html_safe(content), options)
end
protected
diff --git a/lib/simple_navigation/adapters/sinatra.rb b/lib/simple_navigation/adapters/sinatra.rb
index 44f04689..1d65ccd7 100644
--- a/lib/simple_navigation/adapters/sinatra.rb
+++ b/lib/simple_navigation/adapters/sinatra.rb
@@ -1,4 +1,4 @@
-require 'cgi'
+# frozen_string_literal: true
module SimpleNavigation
module Adapters
@@ -7,13 +7,13 @@ def self.register(app)
SimpleNavigation.set_env(app.root, app.environment)
end
- def initialize(context)
+ def initialize(context) # rubocop:disable Lint/MissingSuper
@context = context
@request = context.request
end
def context_for_eval
- context || fail('no context set for evaluation the config file')
+ context || raise('no context set for evaluation the config file')
end
def request_uri
@@ -32,9 +32,7 @@ def current_page?(url)
request_uri.split('?').first
end
- if url_string =~ %r(^\w+://)
- uri = "#{request.scheme}://#{request.host_with_port}#{uri}"
- end
+ uri = "#{request.scheme}://#{request.host_with_port}#{uri}" if %r{^\w+://}.match?(url_string)
url_string == CGI.unescape(uri)
end
diff --git a/lib/simple_navigation/config_file.rb b/lib/simple_navigation/config_file.rb
index a392a9b7..92de1bd0 100644
--- a/lib/simple_navigation/config_file.rb
+++ b/lib/simple_navigation/config_file.rb
@@ -1,4 +1,4 @@
-require 'active_support/core_ext/string'
+# frozen_string_literal: true
module SimpleNavigation
# Internal: Encapsulates the config file naming knowledge.
diff --git a/lib/simple_navigation/config_file_finder.rb b/lib/simple_navigation/config_file_finder.rb
index a82965f5..1004f92e 100644
--- a/lib/simple_navigation/config_file_finder.rb
+++ b/lib/simple_navigation/config_file_finder.rb
@@ -1,4 +1,4 @@
-require 'simple_navigation/config_file'
+# frozen_string_literal: true
module SimpleNavigation
# Internal: Encapsulates the configuration file finding logic.
@@ -22,8 +22,8 @@ def find(context)
config_file_name = config_file_name_for_context(context)
find_config_file(config_file_name) ||
- fail("Config file '#{config_file_name}' not found in " \
- "path(s) #{paths.join(', ')}!")
+ raise("Config file '#{config_file_name}' not found in " \
+ "path(s) #{paths.join(', ')}!")
end
private
diff --git a/lib/simple_navigation/configuration.rb b/lib/simple_navigation/configuration.rb
index 3126dab7..b0478bca 100644
--- a/lib/simple_navigation/configuration.rb
+++ b/lib/simple_navigation/configuration.rb
@@ -1,4 +1,4 @@
-require 'singleton'
+# frozen_string_literal: true
module SimpleNavigation
# Responsible for evaluating and handling the config/navigation.rb file.
@@ -27,8 +27,8 @@ def self.eval_config(navigation_context = :default)
end
# Starts processing the configuration
- def self.run(&block)
- block.call Configuration.instance
+ def self.run
+ yield Configuration.instance
end
# Sets the config's default-settings
@@ -74,14 +74,12 @@ def id_generator
# See SimpleNavigation::ItemAdapter for more details.
#
def items(items_provider = nil, &block)
- if (items_provider && block) || (items_provider.nil? && block.nil?)
- fail('please specify either items_provider or block, but not both')
- end
+ raise('please specify either items_provider or block, but not both') if (items_provider && block) || (items_provider.nil? && block.nil?)
self.primary_navigation = ItemContainer.new
if block
- block.call primary_navigation
+ yield primary_navigation
else
primary_navigation.items = ItemsProvider.new(items_provider).items
end
diff --git a/lib/simple_navigation/helpers.rb b/lib/simple_navigation/helpers.rb
index 8f5454db..fc13341f 100644
--- a/lib/simple_navigation/helpers.rb
+++ b/lib/simple_navigation/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
# View helpers to render the navigation.
#
@@ -30,14 +32,12 @@ def self.load_config(options, includer, &block)
SimpleNavigation.load_config context
SimpleNavigation::Configuration.eval_config context
- if block_given? || options[:items]
- SimpleNavigation.config.items(options[:items], &block)
- end
+ SimpleNavigation.config.items(options[:items], &block) if block_given? || options[:items]
- unless SimpleNavigation.primary_navigation
- fail 'no primary navigation defined, either use a navigation config ' \
- 'file or pass items directly to render_navigation'
- end
+ return if SimpleNavigation.primary_navigation
+
+ raise 'no primary navigation defined, either use a navigation config ' \
+ 'file or pass items directly to render_navigation'
end
def self.apply_defaults(options)
@@ -85,7 +85,7 @@ def self.apply_defaults(options)
#
def render_navigation(options = {}, &block)
container = active_navigation_item_container(options, &block)
- container && container.render(options)
+ container&.render(options)
end
# Returns the name of the currently active navigation item belonging to the
@@ -138,9 +138,7 @@ def active_navigation_item_key(options = {})
# by default) if no active item can be found for the specified
# options
def active_navigation_item(options = {}, value_for_nil = nil)
- if options[:level].nil? || options[:level] == :all
- options[:level] = :leaves
- end
+ options[:level] = :leaves if options[:level].nil? || options[:level] == :all
container = active_navigation_item_container(options)
if container && (item = container.selected_item)
block_given? ? yield(item) : item
diff --git a/lib/simple_navigation/item.rb b/lib/simple_navigation/item.rb
index 49235406..580428f3 100644
--- a/lib/simple_navigation/item.rb
+++ b/lib/simple_navigation/item.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
module SimpleNavigation
# Represents an item in your navigation.
# Gets generated by the item method in the config-file.
- class Item
+ class Item # rubocop:disable Metrics/ClassLength
attr_reader :key,
:name,
:sub_navigation,
@@ -27,7 +29,7 @@ def initialize(container, key, name, url = nil, opts = {}, &sub_nav_block)
# the name will be passed to the name_generator specified
# in the configuration.
#
- def name(options = {})
+ def name(options = {}) # rubocop:disable Lint/DuplicateMethods
options = { apply_generator: true }.merge(options)
if options[:apply_generator]
config.name_generator.call(@name, self)
@@ -50,7 +52,7 @@ def selected?
# for this item in the config-file.
# It also adds the 'selected' class to the list of classes if necessary.
def html_options
- html_opts = options.fetch(:html) { Hash.new }
+ html_opts = options.fetch(:html) { {} }
html_opts[:id] ||= autogenerated_item_id
classes = [html_opts[:class], selected_class, active_leaf_class]
@@ -63,17 +65,17 @@ def html_options
# Returns the configured active_leaf_class if the item is the selected leaf,
# nil otherwise
def active_leaf_class
- if !selected_by_subnav? && selected_by_condition?
- config.active_leaf_class
- end
+ return unless !selected_by_subnav? && selected_by_condition?
+
+ config.active_leaf_class
end
# Returns the configured selected_class if the item is selected,
# nil otherwise
def selected_class
- if selected?
- container.selected_class || config.selected_class
- end
+ return unless selected?
+
+ container.selected_class || config.selected_class
end
# Returns the :highlights_on option as set at initialization
@@ -97,7 +99,7 @@ def link_html_options
# Returns true if item has a subnavigation and
# the sub_navigation is selected
def selected_by_subnav?
- sub_navigation && sub_navigation.selected?
+ sub_navigation&.selected?
end
# Returns true if the item's url matches the request's current url.
@@ -139,26 +141,26 @@ def request_uri
end
def remove_anchors(url_with_anchors)
- url_with_anchors && url_with_anchors.split('#').first
+ url_with_anchors&.split('#')&.first
end
def remove_query_params(url_with_params)
- url_with_params && url_with_params.split('?').first
+ url_with_params&.split('?')&.first
end
def url_for_autohighlight
- relevant_url = remove_anchors(self.url) if config.ignore_anchors_on_auto_highlight
+ relevant_url = remove_anchors(url) if config.ignore_anchors_on_auto_highlight
relevant_url = remove_query_params(relevant_url) if config.ignore_query_params_on_auto_highlight
relevant_url
end
def selected_by_autohighlight?
return false unless auto_highlight?
- return false unless self.url
+ return false unless url
root_path_match? ||
- (url_for_autohighlight && SimpleNavigation.current_page?(url_for_autohighlight)) ||
- autohighlight_by_subpath?
+ (url_for_autohighlight && SimpleNavigation.current_page?(url_for_autohighlight)) ||
+ autohighlight_by_subpath?
end
def autohighlight_by_subpath?
@@ -171,13 +173,13 @@ def selected_by_highlights_on?
when Proc then highlights_on.call
when :subpath then selected_by_subpath?
else
- fail ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath'
+ raise ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath'
end
end
def selected_by_subpath?
escaped_url = Regexp.escape(url_for_autohighlight)
- !!(request_uri =~ /^#{escaped_url}(\/|$||\?)/i)
+ !!(request_uri =~ %r{^#{escaped_url}(/|$||\?)}i)
end
def setup_sub_navigation(items = nil, &sub_nav_block)
@@ -186,7 +188,7 @@ def setup_sub_navigation(items = nil, &sub_nav_block)
self.sub_navigation = ItemContainer.new(container.level + 1)
if sub_nav_block
- sub_nav_block.call sub_navigation
+ yield sub_navigation
else
sub_navigation.items = items
end
diff --git a/lib/simple_navigation/item_adapter.rb b/lib/simple_navigation/item_adapter.rb
index 0593a8a8..7a0c6000 100644
--- a/lib/simple_navigation/item_adapter.rb
+++ b/lib/simple_navigation/item_adapter.rb
@@ -1,5 +1,4 @@
-require 'forwardable'
-require 'ostruct'
+# frozen_string_literal: true
module SimpleNavigation
# This class acts as an adapter to items that are not defined using the DSL
@@ -30,20 +29,32 @@ class ItemAdapter
attr_reader :item
+ class Item
+ attr_reader :key, :name, :url, :options, :items
+
+ def initialize(item)
+ @key = item[:key]
+ @name = item[:name]
+ @url = item[:url]
+ @options = item[:options] || {}
+ @items = item[:items] || []
+ end
+ end
+
def initialize(item)
- @item = item.is_a?(Hash) ? OpenStruct.new(item) : item
+ @item = item.is_a?(Hash) ? Item.new(item) : item
end
# Returns the options for this item. If the wrapped item does not implement
# an options method, an empty hash is returned.
def options
- item.respond_to?(:options) ? item.options : {}
+ item.options
end
# Returns the items (subnavigation) for this item if it responds to :items
# and the items-collection is not empty. Returns nil otherwise.
def items
- item.items if item.respond_to?(:items) && item.items && item.items.any?
+ item.items if item.items&.any?
end
# Converts this Item into a SimpleNavigation::Item
diff --git a/lib/simple_navigation/item_container.rb b/lib/simple_navigation/item_container.rb
index eebfde3c..0e9a3b39 100644
--- a/lib/simple_navigation/item_container.rb
+++ b/lib/simple_navigation/item_container.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
module SimpleNavigation
# Holds the Items for a navigation 'level'.
- class ItemContainer
+ class ItemContainer # rubocop:disable Metrics/ClassLength
attr_accessor :auto_highlight,
:dom_class,
:dom_id,
@@ -11,7 +13,7 @@ class ItemContainer
attr_writer :dom_attributes
- def initialize(level = 1) #:nodoc:
+ def initialize(level = 1) # :nodoc:
@level = level
@items ||= []
@renderer = SimpleNavigation.config.renderer
@@ -24,7 +26,7 @@ def dom_attributes
dom_id_and_class = {
id: dom_id,
class: dom_class
- }.reject { |_, v| v.nil? }
+ }.compact
@dom_attributes.merge(dom_id_and_class)
end
@@ -63,6 +65,7 @@ def dom_attributes
# The block - if specified - will hold the item's sub_navigation.
def item(key, name, url = nil, options = {}, &block)
return unless should_add_item?(options)
+
item = Item.new(self, key, name, url, options, &block)
add_item item, options
end
@@ -71,6 +74,7 @@ def items=(new_items)
new_items.each do |item|
item_adapter = ItemAdapter.new(item)
next unless should_add_item?(item_adapter.options)
+
add_item item_adapter.to_simple_navigation_item(self), item_adapter.options
end
end
@@ -91,10 +95,11 @@ def level_for_item(navi_key)
items.each do |item|
next unless item.sub_navigation
+
level = item.sub_navigation.level_for_item(navi_key)
return level if level
end
- return nil
+ nil
end
# Renders the items in this ItemContainer using the configured renderer.
@@ -152,7 +157,8 @@ def add_item(item, options)
end
def modify_dom_attributes(options)
- return unless container_options = options[:container]
+ return unless (container_options = options[:container])
+
self.dom_attributes = container_options.fetch(:attributes) { dom_attributes }
self.dom_class = container_options.fetch(:class) { dom_class }
self.dom_id = container_options.fetch(:id) { dom_id }
@@ -178,13 +184,13 @@ def selected_sub_navigation?
def should_add_item?(options)
[options[:if]].flatten.compact.all? { |m| evaluate_method(m) } &&
- [options[:unless]].flatten.compact.none? { |m| evaluate_method(m) }
+ [options[:unless]].flatten.compact.none? { |m| evaluate_method(m) }
end
def evaluate_method(method)
case method
when Proc, Method then method.call
- else fail(ArgumentError, ':if or :unless must be procs or lambdas')
+ else raise(ArgumentError, ':if or :unless must be procs or lambdas')
end
end
end
diff --git a/lib/simple_navigation/items_provider.rb b/lib/simple_navigation/items_provider.rb
index 30d56c90..3de1eaa3 100644
--- a/lib/simple_navigation/items_provider.rb
+++ b/lib/simple_navigation/items_provider.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
# Acts as a proxy to navigation items that are passed into the
# SimpleNavigation::Configuration#items method.
@@ -20,7 +22,7 @@ def initialize(provider)
end
# Returns the navigation items
- def items
+ def items # rubocop:disable Metrics/MethodLength
if provider.is_a?(Symbol)
SimpleNavigation.context_for_eval.send(provider)
elsif provider.respond_to?(:items)
@@ -28,9 +30,9 @@ def items
elsif provider.respond_to?(:each)
provider
else
- fail('items_provider either must be a symbol specifying the ' \
- 'helper-method to call, an object with an items-method defined ' \
- 'or an enumerable representing the items')
+ raise('items_provider either must be a symbol specifying the ' \
+ 'helper-method to call, an object with an items-method defined ' \
+ 'or an enumerable representing the items')
end
end
end
diff --git a/lib/simple_navigation/railtie.rb b/lib/simple_navigation/railtie.rb
index 473a2cf5..5a50b49c 100644
--- a/lib/simple_navigation/railtie.rb
+++ b/lib/simple_navigation/railtie.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
module SimpleNavigation
class Railtie < ::Rails::Railtie
- initializer 'simple_navigation.register' do |app|
+ initializer 'simple_navigation.register' do |_app|
SimpleNavigation.register
end
end
diff --git a/lib/simple_navigation/renderer.rb b/lib/simple_navigation/renderer.rb
deleted file mode 100644
index ebbe3207..00000000
--- a/lib/simple_navigation/renderer.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'simple_navigation/helpers'
-require 'simple_navigation/renderer/base'
-
-module SimpleNavigation
- module Renderer
- autoload :List, 'simple_navigation/renderer/list'
- autoload :Links, 'simple_navigation/renderer/links'
- autoload :Breadcrumbs, 'simple_navigation/renderer/breadcrumbs'
- autoload :Text, 'simple_navigation/renderer/text'
- autoload :Json, 'simple_navigation/renderer/json'
- end
-end
diff --git a/lib/simple_navigation/renderer/base.rb b/lib/simple_navigation/renderer/base.rb
index 85625fef..5d3ce7d3 100644
--- a/lib/simple_navigation/renderer/base.rb
+++ b/lib/simple_navigation/renderer/base.rb
@@ -1,4 +1,4 @@
-require 'forwardable'
+# frozen_string_literal: true
module SimpleNavigation
module Renderer
@@ -13,7 +13,7 @@ class Base
def_delegators :adapter, :link_to, :content_tag
- def initialize(options) #:nodoc:
+ def initialize(options) # :nodoc:
@options = options
@adapter = SimpleNavigation.adapter
end
@@ -44,7 +44,7 @@ def render_sub_navigation_for(item)
# include_sub_navigation? to determine whether an item's sub_navigation
# should be rendered or not.
def render(item_container)
- fail NotImplementedError, 'subclass responsibility'
+ raise NotImplementedError, 'subclass responsibility'
end
protected
@@ -89,11 +89,11 @@ def options_for(item)
end
# Extracts the options relevant for the generated link
- def link_options_for(item)
+ def link_options_for(item) # rubocop:disable Metrics/MethodLength
special_options = {
method: item.method,
class: item.selected_class
- }.reject { |_, v| v.nil? }
+ }.compact
link_options = item.link_html_options
diff --git a/lib/simple_navigation/renderer/breadcrumbs.rb b/lib/simple_navigation/renderer/breadcrumbs.rb
index c2e64800..3537411b 100644
--- a/lib/simple_navigation/renderer/breadcrumbs.rb
+++ b/lib/simple_navigation/renderer/breadcrumbs.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
module Renderer
# Renders an ItemContainer as a
element and its containing items as
@@ -25,11 +27,10 @@ def render(item_container)
def a_tags(item_container)
item_container.items.each_with_object([]) do |item, list|
next unless item.selected?
+
list << tag_for(item)
- if include_sub_navigation?(item)
- list.concat a_tags(item.sub_navigation)
- end
+ list.concat a_tags(item.sub_navigation) if include_sub_navigation?(item)
end
end
diff --git a/lib/simple_navigation/renderer/json.rb b/lib/simple_navigation/renderer/json.rb
index 31dba364..d546bfd7 100644
--- a/lib/simple_navigation/renderer/json.rb
+++ b/lib/simple_navigation/renderer/json.rb
@@ -1,4 +1,4 @@
-require 'json'
+# frozen_string_literal: true
module SimpleNavigation
module Renderer
diff --git a/lib/simple_navigation/renderer/links.rb b/lib/simple_navigation/renderer/links.rb
index 0dbc8f42..281739a5 100644
--- a/lib/simple_navigation/renderer/links.rb
+++ b/lib/simple_navigation/renderer/links.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
module Renderer
# Renders an ItemContainer as a
element and its containing items as
diff --git a/lib/simple_navigation/renderer/list.rb b/lib/simple_navigation/renderer/list.rb
index f37bbe7a..a681c9c2 100644
--- a/lib/simple_navigation/renderer/list.rb
+++ b/lib/simple_navigation/renderer/list.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
module Renderer
# Renders an ItemContainer as a
element and its containing items as
@@ -28,14 +30,12 @@ def render(item_container)
private
def list_content(item_container)
- item_container.items.map { |item|
+ item_container.items.map do |item|
li_options = item.html_options.except(:link)
li_content = tag_for(item)
- if include_sub_navigation?(item)
- li_content << render_sub_navigation_for(item)
- end
+ li_content << render_sub_navigation_for(item) if include_sub_navigation?(item)
content_tag(:li, li_content, li_options)
- }.join
+ end.join
end
end
end
diff --git a/lib/simple_navigation/renderer/text.rb b/lib/simple_navigation/renderer/text.rb
index bdf55b3d..731849e4 100644
--- a/lib/simple_navigation/renderer/text.rb
+++ b/lib/simple_navigation/renderer/text.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
module Renderer
# Renders the 'chain' of selected navigation items as simple text items,
@@ -13,7 +15,7 @@ def render(item_container)
def list(item_container)
item_container.items.keep_if(&:selected?).map do |item|
[item.name(apply_generator: false)] +
- (include_sub_navigation?(item) ? list(item.sub_navigation) : [])
+ (include_sub_navigation?(item) ? list(item.sub_navigation) : [])
end
end
end
diff --git a/lib/simple_navigation/version.rb b/lib/simple_navigation/version.rb
index 21c96a15..1daeac5d 100644
--- a/lib/simple_navigation/version.rb
+++ b/lib/simple_navigation/version.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SimpleNavigation
VERSION = '4.4.1'
end
diff --git a/simple-navigation.gemspec b/simple-navigation.gemspec
index aa4e3f2d..938fcb2a 100644
--- a/simple-navigation.gemspec
+++ b/simple-navigation.gemspec
@@ -1,42 +1,31 @@
-# coding: utf-8
-lib = File.expand_path('../lib', __FILE__)
-$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
-require 'simple_navigation/version'
+# frozen_string_literal: true
+
+require_relative 'lib/simple_navigation/version'
Gem::Specification.new do |spec|
spec.name = 'simple-navigation'
spec.version = SimpleNavigation::VERSION
spec.authors = ['Andi Schacke', 'Mark J. Titorenko', 'Simon Courtois']
spec.email = ['andi@codeplant.ch']
- spec.description = "With the simple-navigation gem installed you can easily " \
- "create multilevel navigations for your Rails, Sinatra or "\
- "Padrino applications. The navigation is defined in a " \
- "single configuration file. It supports automatic as well "\
- "as explicit highlighting of the currently active " \
- "navigation through regular expressions."
- spec.summary = "simple-navigation is a ruby library for creating navigations "\
- "(with multiple levels) for your Rails, Sinatra or " \
- "Padrino application."
+ spec.description = 'With the simple-navigation gem installed you can easily ' \
+ 'create multilevel navigations for your Rails, Sinatra or ' \
+ 'Padrino applications. The navigation is defined in a ' \
+ 'single configuration file. It supports automatic as well ' \
+ 'as explicit highlighting of the currently active ' \
+ 'navigation through regular expressions.'
+ spec.summary = 'simple-navigation is a ruby library for creating navigations ' \
+ '(with multiple levels) for your Rails, Sinatra or ' \
+ 'Padrino application.'
spec.homepage = 'http://github.com/codeplant/simple-navigation'
spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0")
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
- spec.require_paths = ['lib']
spec.rdoc_options = ['--inline-source', '--charset=UTF-8']
- spec.add_runtime_dependency 'activesupport', '>= 2.3.2'
- spec.add_runtime_dependency 'ostruct'
+ spec.required_ruby_version = '>= 3.0.0'
- spec.add_development_dependency 'bundler'
- spec.add_development_dependency 'capybara'
- spec.add_development_dependency 'coveralls', '~> 0.7'
- spec.add_development_dependency 'guard-rspec', '~> 4.2'
- spec.add_development_dependency 'memfs', '~> 0.4.1'
- spec.add_development_dependency 'rake'
- spec.add_development_dependency 'rdoc'
- spec.add_development_dependency 'rspec', '~> 3.0'
- spec.add_development_dependency 'tzinfo', '>= 0'
+ spec.add_dependency 'activesupport', '>= 6.1.0'
+ spec.add_dependency 'json'
+ spec.add_dependency 'zeitwerk'
end
diff --git a/spec/fake_app/config/navigation.rb b/spec/fake_app/config/navigation.rb
index 417d1d49..2c138969 100644
--- a/spec/fake_app/config/navigation.rb
+++ b/spec/fake_app/config/navigation.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
SimpleNavigation::Configuration.run do |navigation|
navigation.items do |nav|
- nav.item :item_1, 'Item 1', '/item_1', html: {class: 'item_1'}, link_html: {id: 'link_1'}
- nav.item :item_2, 'Item 2', '/item_2', html: {class: 'item_2'}, link_html: {id: 'link_2'}
+ nav.item :item_1, 'Item 1', '/item_1', html: { class: 'item_1' }, link_html: { id: 'link_1' }
+ nav.item :item_2, 'Item 2', '/item_2', html: { class: 'item_2' }, link_html: { id: 'link_2' }
end
end
diff --git a/spec/fake_app/rails_app.rb b/spec/fake_app/rails_app.rb
index 7f074c5c..a0d514b8 100644
--- a/spec/fake_app/rails_app.rb
+++ b/spec/fake_app/rails_app.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
ENV['RAILS_ENV'] ||= 'test'
require 'action_controller/railtie'
@@ -9,20 +11,20 @@ class Application < Rails::Application
config.cache_classes = true
config.eager_load = false
config.root = __dir__
- config.secret_token = 'x'*100
+ config.secret_token = 'x' * 100
config.session_store :cookie_store, key: '_myapp_session'
end
class TestsController < ActionController::Base
def base
- render inline: <<-END
+ render inline: <<-HTML
<%= render_navigation %>
- END
+ HTML
end
end
end
diff --git a/spec/initializers/coveralls.rb b/spec/initializers/coveralls.rb
deleted file mode 100644
index fe39ae25..00000000
--- a/spec/initializers/coveralls.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-require 'coveralls'
-
-Coveralls.wear!
diff --git a/spec/initializers/have_css_matcher.rb b/spec/initializers/have_css_matcher.rb
deleted file mode 100644
index ed60041a..00000000
--- a/spec/initializers/have_css_matcher.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-RSpec::Matchers.define :have_css do |expected, times|
- match do |actual|
- selector = Nokogiri::HTML(actual).css(expected)
-
- if times
- expect(selector.size).to eq times
- else
- expect(selector.size).to be >= 1
- end
- end
-
- failure_message do |actual|
- "expected #{actual.to_s} to have #{times || 1} elements matching '#{expected}'"
- end
-
- failure_message_when_negated do |actual|
- "expected #{actual.to_s} not to have #{times || 1} elements matching '#{expected}'"
- end
-end
diff --git a/spec/initializers/memfs.rb b/spec/initializers/memfs.rb
deleted file mode 100644
index 6369794c..00000000
--- a/spec/initializers/memfs.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require 'memfs'
-
-RSpec.configure do |config|
- config.around(memfs: true) do |example|
- MemFs.activate { example.run }
- end
-end
diff --git a/spec/initializers/rails.rb b/spec/initializers/rails.rb
deleted file mode 100644
index 59201bb3..00000000
--- a/spec/initializers/rails.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-begin
- require 'rails'
-rescue LoadError
-end
diff --git a/spec/initializers/rspec.rb b/spec/initializers/rspec.rb
deleted file mode 100644
index fe69bb29..00000000
--- a/spec/initializers/rspec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-RSpec.configure do |config|
- config.expect_with(:rspec) do |c|
- c.syntax = :expect
- end
-
- config.order = :random
-end
diff --git a/spec/integration/rendering_navigation_spec.rb b/spec/integration/rendering_navigation_spec.rb
index 1cf76ed3..4d6cc5ec 100644
--- a/spec/integration/rendering_navigation_spec.rb
+++ b/spec/integration/rendering_navigation_spec.rb
@@ -1,14 +1,16 @@
+# frozen_string_literal: true
+
RSpec.feature 'Rendering navigation' do
background do
SimpleNavigation.set_env(RailsApp::Application.root, 'test')
end
- scenario 'Rendering basic navigation', type: :feature do
+ scenario 'Rendering basic navigation', type: :feature do # rubocop:disable RSpec/MultipleExpectations
visit '/base_spec'
expect(page).to have_content('Item 1')
expect(page).to have_content('Item 2')
- expect(page).to have_selector('li.item_1 a#link_1')
- expect(page).to have_selector('li.item_2 a#link_2')
+ expect(page).to have_css('li.item_1 a#link_1')
+ expect(page).to have_css('li.item_2 a#link_2')
end
end
diff --git a/spec/simple_navigation/adapters/padrino_spec.rb b/spec/simple_navigation/adapters/padrino_spec.rb
index db668cb1..0c07a21b 100644
--- a/spec/simple_navigation/adapters/padrino_spec.rb
+++ b/spec/simple_navigation/adapters/padrino_spec.rb
@@ -1,27 +1,23 @@
-module SimpleNavigation
- module Adapters
- describe Padrino do
- let(:adapter) { SimpleNavigation::Adapters::Padrino.new(context) }
- let(:content) { double(:content) }
- let(:context) { double(:context, request: request) }
- let(:request) { double(:request) }
+# frozen_string_literal: true
- describe '#link_to' do
- it 'delegates to context' do
- expect(context).to receive(:link_to)
- .with('name', 'url', :my_option => true)
- adapter.link_to('name', 'url', :my_option => true)
- end
- end
+RSpec.describe SimpleNavigation::Adapters::Padrino do
+ let(:adapter) { described_class.new(context) }
+ let(:content) { double(:content) }
+ let(:context) { double(:context, request: request) }
+ let(:request) { double(:request) }
- describe '#content_tag' do
- it 'delegates to context' do
- expect(content).to receive(:html_safe).and_return('content')
- expect(context).to receive(:content_tag)
- .with('type', 'content', my_option: true)
- adapter.content_tag('type', content, my_option: true)
- end
- end
+ describe '#link_to' do
+ it 'delegates to context' do
+ expect(context).to receive(:link_to).with('name', 'url', { my_option: true })
+ adapter.link_to('name', 'url', my_option: true)
+ end
+ end
+
+ describe '#content_tag' do
+ it 'delegates to context' do # rubocop:disable RSpec/MultipleExpectations
+ expect(content).to receive(:html_safe).and_return('content') # rubocop:disable RSpec/StubbedMock
+ expect(context).to receive(:content_tag).with('type', 'content', { my_option: true })
+ adapter.content_tag('type', content, my_option: true)
end
end
end
diff --git a/spec/simple_navigation/adapters/rails_spec.rb b/spec/simple_navigation/adapters/rails_spec.rb
index 3dcb3c50..52340a6c 100644
--- a/spec/simple_navigation/adapters/rails_spec.rb
+++ b/spec/simple_navigation/adapters/rails_spec.rb
@@ -1,281 +1,272 @@
-module SimpleNavigation
- module Adapters
- describe Rails do
- let(:action_controller) { ActionController::Base }
- let(:adapter) { Rails.new(context) }
- let(:context) { double(:context, controller: controller) }
- let(:controller) { double(:controller) }
- let(:request) { double(:request) }
- let(:simple_navigation) { SimpleNavigation }
- let(:template) { double(:template, request: request) }
-
- describe '.register' do
- before { allow(action_controller).to receive(:include) }
-
- it 'calls set_env' do
- app_path = RailsApp::Application.root
- expect(simple_navigation).to receive(:set_env).with(app_path, 'test')
- simple_navigation.register
- end
+# frozen_string_literal: true
+
+RSpec.describe SimpleNavigation::Adapters::Rails do
+ let(:action_controller) { ActionController::Base }
+ let(:adapter) { described_class.new(context) }
+ let(:context) { double(:context, controller: controller) }
+ let(:controller) { double(:controller) }
+ let(:request) { double(:request) }
+ let(:simple_navigation) { SimpleNavigation }
+ let(:template) { double(:template, request: request) }
+
+ describe '.register' do
+ before { allow(action_controller).to receive(:include) }
+
+ it 'calls set_env' do
+ app_path = RailsApp::Application.root
+ expect(simple_navigation).to receive(:set_env).with(app_path, 'test')
+ simple_navigation.register
+ end
- it 'extends the ActionController::Base with the Helpers' do
- expect(action_controller).to receive(:include)
- .with(SimpleNavigation::Helpers)
- simple_navigation.register
- end
+ it 'extends the ActionController::Base with the Helpers' do
+ expect(action_controller).to receive(:include).with(SimpleNavigation::Helpers)
+ simple_navigation.register
+ end
- shared_examples 'installing helper method' do |method|
- it "installs the #{method} method as helper method" do
- simple_navigation.register
+ shared_examples 'installing helper method' do |method|
+ it "installs the #{method} method as helper method" do
+ simple_navigation.register
- helper_methods = action_controller.send(:_helper_methods)
- expect(helper_methods).to include(method)
- end
- end
-
- it_behaves_like 'installing helper method', :render_navigation
- it_behaves_like 'installing helper method', :active_navigation_item_name
- it_behaves_like 'installing helper method', :active_navigation_item_key
- it_behaves_like 'installing helper method', :active_navigation_item
- it_behaves_like 'installing helper method', :active_navigation_item_container
+ helper_methods = action_controller.send(:_helper_methods)
+ expect(helper_methods).to include(method)
end
+ end
- describe '#initialize' do
- context "when the controller's template is set" do
- before { allow(controller).to receive_messages(instance_variable_get: template) }
-
- it "sets the adapter's request accordingly" do
- expect(adapter.request).to be request
- end
- end
+ it_behaves_like 'installing helper method', :render_navigation
+ it_behaves_like 'installing helper method', :active_navigation_item_name
+ it_behaves_like 'installing helper method', :active_navigation_item_key
+ it_behaves_like 'installing helper method', :active_navigation_item
+ it_behaves_like 'installing helper method', :active_navigation_item_container
+ end
- context "when the controller's template is not set" do
- before { allow(controller).to receive_messages(instance_variable_get: nil) }
+ describe '#initialize' do
+ context "when the controller's template is set" do
+ before { allow(controller).to receive_messages(instance_variable_get: template) }
- it "sets the adapter's request to nil" do
- expect(adapter.request).to be_nil
- end
- end
+ it "sets the adapter's request accordingly" do
+ expect(adapter.request).to be request
+ end
+ end
- it "sets the adapter's controller to the context's controller" do
- expect(adapter.controller).to be controller
- end
+ context "when the controller's template is not set" do
+ before { allow(controller).to receive_messages(instance_variable_get: nil) }
- context "when the controller's template is stored as instance var (Rails2)" do
- context "when the controller's template is set" do
- before { allow(controller).to receive_messages(instance_variable_get: template) }
+ it "sets the adapter's request to nil" do
+ expect(adapter.request).to be_nil
+ end
+ end
- it "sets the adapter's template accordingly" do
- expect(adapter.template).to be template
- end
- end
+ it "sets the adapter's controller to the context's controller" do
+ expect(adapter.controller).to be controller
+ end
- context "when the controller's template is not set" do
- before { allow(controller).to receive_messages(instance_variable_get: nil) }
+ context "when the controller's template is stored as instance var (Rails2)" do
+ context "when the controller's template is set" do
+ before { allow(controller).to receive_messages(instance_variable_get: template) }
- it "set the adapter's template to nil" do
- expect(adapter.template).to be_nil
- end
- end
+ it "sets the adapter's template accordingly" do
+ expect(adapter.template).to be template
end
+ end
- context "when the controller's template is stored as view_context (Rails3)" do
- context 'and the template is set' do
- before { allow(controller).to receive_messages(view_context: template) }
+ context "when the controller's template is not set" do
+ before { allow(controller).to receive_messages(instance_variable_get: nil) }
- it "sets the adapter's template accordingly" do
- expect(adapter.template).to be template
- end
- end
+ it "set the adapter's template to nil" do
+ expect(adapter.template).to be_nil
+ end
+ end
+ end
- context 'and the template is not set' do
- before { allow(controller).to receive_messages(view_context: nil) }
+ context "when the controller's template is stored as view_context (Rails3)" do
+ context 'and the template is set' do
+ before { allow(controller).to receive_messages(view_context: template) }
- it "sets the adapter's template to nil" do
- expect(adapter.template).to be_nil
- end
- end
+ it "sets the adapter's template accordingly" do
+ expect(adapter.template).to be template
end
end
- describe '#request_uri' do
- context "when the adapter's request is set" do
- before { allow(adapter).to receive_messages(request: request) }
+ context 'and the template is not set' do
+ before { allow(controller).to receive_messages(view_context: nil) }
- context 'and request.fullpath is defined' do
- let(:request) { double(:request, fullpath: '/fullpath') }
-
- it "sets the adapter's request_uri to the request.fullpath" do
- expect(adapter.request_uri).to eq '/fullpath'
- end
- end
+ it "sets the adapter's template to nil" do
+ expect(adapter.template).to be_nil
+ end
+ end
+ end
+ end
- context 'and request.fullpath is not defined' do
- let(:request) { double(:request, request_uri: '/request_uri') }
+ describe '#request_uri' do
+ context "when the adapter's request is set" do
+ before { allow(adapter).to receive_messages(request: request) }
- before { allow(adapter).to receive_messages(request: request) }
+ context 'and request.fullpath is defined' do
+ let(:request) { double(:request, fullpath: '/fullpath') }
- it "sets the adapter's request_uri to the request.request_uri" do
- expect(adapter.request_uri).to eq '/request_uri'
- end
- end
+ it "sets the adapter's request_uri to the request.fullpath" do
+ expect(adapter.request_uri).to eq '/fullpath'
end
+ end
- context "when the adapter's request is not set" do
- before { allow(adapter).to receive_messages(request: nil) }
+ context 'and request.fullpath is not defined' do
+ let(:request) { double(:request, request_uri: '/request_uri') }
- it "sets the adapter's request_uri to an empty string" do
- expect(adapter.request_uri).to eq ''
- end
+ before { allow(adapter).to receive_messages(request: request) }
+
+ it "sets the adapter's request_uri to the request.request_uri" do
+ expect(adapter.request_uri).to eq '/request_uri'
end
end
+ end
- describe '#request_path' do
- context "when the adapter's request is set" do
- let(:request) { double(:request, path: '/request_path') }
+ context "when the adapter's request is not set" do
+ before { allow(adapter).to receive_messages(request: nil) }
- before { allow(adapter).to receive_messages(request: request) }
+ it "sets the adapter's request_uri to an empty string" do
+ expect(adapter.request_uri).to eq ''
+ end
+ end
+ end
- it "sets the adapter's request_path to the request.path" do
- expect(adapter.request_path).to eq '/request_path'
- end
- end
+ describe '#request_path' do
+ context "when the adapter's request is set" do
+ let(:request) { double(:request, path: '/request_path') }
- context "when the adapter's request is not set" do
- before { allow(adapter).to receive_messages(request: nil) }
+ before { allow(adapter).to receive_messages(request: request) }
- it "sets the adapter's request_path to an empty string" do
- expect(adapter.request_path).to eq ''
- end
- end
+ it "sets the adapter's request_path to the request.path" do
+ expect(adapter.request_path).to eq '/request_path'
end
+ end
- describe '#context_for_eval' do
- context "when the adapter's controller is set" do
- before { adapter.instance_variable_set(:@controller, controller) }
+ context "when the adapter's request is not set" do
+ before { allow(adapter).to receive_messages(request: nil) }
- context "and the adapter's template is set" do
- before { adapter.instance_variable_set(:@template, template) }
+ it "sets the adapter's request_path to an empty string" do
+ expect(adapter.request_path).to eq ''
+ end
+ end
+ end
- it "sets the adapter's context_for_eval to the template" do
- expect(adapter.context_for_eval).to be template
- end
- end
+ describe '#context_for_eval' do
+ context "when the adapter's controller is set" do
+ before { adapter.instance_variable_set(:@controller, controller) }
- context "and the adapter's template is not set" do
- before { adapter.instance_variable_set(:@template, nil) }
+ context "and the adapter's template is set" do
+ before { adapter.instance_variable_set(:@template, template) }
- it "sets the adapter's context_for_eval to the controller" do
- expect(adapter.context_for_eval).to be controller
- end
- end
+ it "sets the adapter's context_for_eval to the template" do
+ expect(adapter.context_for_eval).to be template
end
+ end
- context "when the adapter's controller is not set" do
- before { adapter.instance_variable_set(:@controller, nil) }
+ context "and the adapter's template is not set" do
+ before { adapter.instance_variable_set(:@template, nil) }
- context "and the adapter's template is set" do
- before { adapter.instance_variable_set(:@template, template) }
+ it "sets the adapter's context_for_eval to the controller" do
+ expect(adapter.context_for_eval).to be controller
+ end
+ end
+ end
- it "sets the adapter's context_for_eval to the template" do
- expect(adapter.context_for_eval).to be template
- end
- end
+ context "when the adapter's controller is not set" do
+ before { adapter.instance_variable_set(:@controller, nil) }
- context "and the adapter's template is not set" do
- before { adapter.instance_variable_set(:@template, nil) }
+ context "and the adapter's template is set" do
+ before { adapter.instance_variable_set(:@template, template) }
- it 'raises an exception' do
- expect{ adapter.context_for_eval }.to raise_error(RuntimeError, 'no context set for evaluation the config file')
- end
- end
+ it "sets the adapter's context_for_eval to the template" do
+ expect(adapter.context_for_eval).to be template
end
end
- describe '#current_page?' do
- context "when the adapter's template is set" do
- before { allow(adapter).to receive_messages(template: template) }
+ context "and the adapter's template is not set" do
+ before { adapter.instance_variable_set(:@template, nil) }
- it 'delegates the call to the template' do
- expect(template).to receive(:current_page?).with(:page)
- adapter.current_page?(:page)
- end
+ it 'raises an exception' do
+ expect { adapter.context_for_eval }.to raise_error(RuntimeError, 'no context set for evaluation the config file')
end
+ end
+ end
+ end
- context "when the adapter's template is not set" do
- before { allow(adapter).to receive_messages(template: nil) }
-
- it 'returns false' do
- expect(adapter.current_page?(:page)).to be_falsey
- end
- end
+ describe '#current_page?' do
+ context "when the adapter's template is set" do
+ before { allow(adapter).to receive_messages(template: template) }
- context 'when the given url is nil' do
- it 'returns false' do
- expect(adapter.current_page?(nil)).to be_falsey
- end
- end
+ it 'delegates the call to the template' do
+ expect(template).to receive(:current_page?).with(:page)
+ adapter.current_page?(:page)
end
+ end
- describe '#link_to' do
- let(:options) { double(:options) }
+ context "when the adapter's template is not set" do
+ before { allow(adapter).to receive_messages(template: nil) }
- context "when the adapter's template is set" do
- before { allow(adapter).to receive_messages(template: template, html_safe: 'safe_text') }
+ it 'returns false' do
+ expect(adapter).not_to be_current_page(:page)
+ end
+ end
- context 'with considering item names as safe' do
- before { SimpleNavigation.config.consider_item_names_as_safe = true }
- after { SimpleNavigation.config.consider_item_names_as_safe = false }
+ context 'when the given url is nil' do
+ it 'returns false' do
+ expect(adapter).not_to be_current_page(nil)
+ end
+ end
+ end
- it 'delegates the call to the template (with html_safe text)' do
- expect(template).to receive(:link_to)
- .with('safe_text', 'url', options)
- adapter.link_to('text', 'url', options)
- end
- end
+ describe '#link_to' do
+ let(:options) { double(:options) }
- context 'with considering item names as UNsafe (default)' do
+ context "when the adapter's template is set" do
+ before { allow(adapter).to receive_messages(template: template, html_safe: 'safe_text') }
- it 'delegates the call to the template (with html_safe text)' do
- expect(template).to receive(:link_to)
- .with('text', 'url', options)
- adapter.link_to('text', 'url', options)
- end
- end
+ context 'with considering item names as safe' do
+ before { SimpleNavigation.config.consider_item_names_as_safe = true }
+ after { SimpleNavigation.config.consider_item_names_as_safe = false }
+ it 'delegates the call to the template (with html_safe text)' do
+ expect(template).to receive(:link_to).with('safe_text', 'url', options)
+ adapter.link_to('text', 'url', options)
end
+ end
- context "when the adapter's template is not set" do
- before { allow(adapter).to receive_messages(template: nil) }
-
- it 'returns nil' do
- expect(adapter.link_to('text', 'url', options)).to be_nil
- end
+ context 'with considering item names as UNsafe (default)' do
+ it 'delegates the call to the template (with html_safe text)' do
+ expect(template).to receive(:link_to).with('text', 'url', options)
+ adapter.link_to('text', 'url', options)
end
end
+ end
- describe '#content_tag' do
- let(:options) { double(:options) }
+ context "when the adapter's template is not set" do
+ before { allow(adapter).to receive_messages(template: nil) }
- context "when the adapter's template is set" do
- before { allow(adapter).to receive_messages(template: template, html_safe: 'safe_text') }
+ it 'returns nil' do
+ expect(adapter.link_to('text', 'url', options)).to be_nil
+ end
+ end
+ end
- it 'delegates the call to the template (with html_safe text)' do
- expect(template).to receive(:content_tag)
- .with(:div, 'safe_text', options)
- adapter.content_tag(:div, 'text', options)
- end
- end
+ describe '#content_tag' do
+ let(:options) { double(:options) }
- context "when the adapter's template is not set" do
- before { allow(adapter).to receive_messages(template: nil) }
+ context "when the adapter's template is set" do
+ before { allow(adapter).to receive_messages(template: template, html_safe: 'safe_text') }
- it 'returns nil' do
- expect(adapter.content_tag(:div, 'text', options)).to be_nil
- end
- end
+ it 'delegates the call to the template (with html_safe text)' do
+ expect(template).to receive(:content_tag).with(:div, 'safe_text', options)
+ adapter.content_tag(:div, 'text', options)
end
+ end
+ context "when the adapter's template is not set" do
+ before { allow(adapter).to receive_messages(template: nil) }
+
+ it 'returns nil' do
+ expect(adapter.content_tag(:div, 'text', options)).to be_nil
+ end
end
end
end
diff --git a/spec/simple_navigation/adapters/sinatra_spec.rb b/spec/simple_navigation/adapters/sinatra_spec.rb
index c587f105..1a014790 100644
--- a/spec/simple_navigation/adapters/sinatra_spec.rb
+++ b/spec/simple_navigation/adapters/sinatra_spec.rb
@@ -1,5 +1,7 @@
-describe SimpleNavigation::Adapters::Sinatra do
- let(:adapter) { SimpleNavigation::Adapters::Sinatra.new(context) }
+# frozen_string_literal: true
+
+RSpec.describe SimpleNavigation::Adapters::Sinatra do
+ let(:adapter) { described_class.new(context) }
let(:context) { double(:context) }
let(:request) { double(:request, fullpath: '/full?param=true', path: '/full') }
@@ -9,7 +11,7 @@
context "when adapter's context is not set" do
it 'raises an exception' do
allow(adapter).to receive_messages(context: nil)
- expect{ adapter.context_for_eval }.to raise_error(RuntimeError, 'no context set for evaluation the config file')
+ expect { adapter.context_for_eval }.to raise_error(RuntimeError, 'no context set for evaluation the config file')
end
end
@@ -57,8 +59,7 @@
context 'when URL is encoded' do
before do
- allow(request).to receive_messages(fullpath: '/full%20with%20spaces?param=true',
- path: '/full%20with%20spaces')
+ allow(request).to receive_messages(fullpath: '/full%20with%20spaces?param=true', path: '/full%20with%20spaces')
end
it_behaves_like 'detecting current page', '/full%20with%20spaces?param=true', true
diff --git a/spec/simple_navigation/config_file_finder_spec.rb b/spec/simple_navigation/config_file_finder_spec.rb
index 6b4581be..de992fcd 100644
--- a/spec/simple_navigation/config_file_finder_spec.rb
+++ b/spec/simple_navigation/config_file_finder_spec.rb
@@ -1,48 +1,48 @@
+# frozen_string_literal: true
+
require 'fileutils'
require 'simple_navigation/config_file_finder'
-module SimpleNavigation
- describe ConfigFileFinder do
- subject(:finder) { ConfigFileFinder.new(paths) }
+RSpec.describe SimpleNavigation::ConfigFileFinder do
+ subject(:finder) { described_class.new(paths) }
- let(:paths) { ['/path/one', '/path/two'] }
+ let(:paths) { ['/path/one', '/path/two'] }
- describe '#find', memfs: true do
- before { FileUtils.mkdir_p(paths) }
+ describe '#find', :memfs do
+ before { FileUtils.mkdir_p(paths) }
- context 'when the context is :default' do
- let(:context) { :default }
+ context 'when the context is :default' do
+ let(:context) { :default }
- context 'and a navigation.rb file is found in one of the paths' do
- before { FileUtils.touch('/path/one/navigation.rb') }
+ context 'and a navigation.rb file is found in one of the paths' do
+ before { FileUtils.touch('/path/one/navigation.rb') }
- it 'returns its full path' do
- expect(finder.find(context)).to eq '/path/one/navigation.rb'
- end
+ it 'returns its full path' do
+ expect(finder.find(context)).to eq '/path/one/navigation.rb'
end
+ end
- context 'and no navigation.rb file is found in the paths' do
- it 'raises an exception' do
- expect { finder.find(context) }.to raise_error(RuntimeError, /Config file 'navigation.rb' not found in path\(s\)/)
- end
+ context 'and no navigation.rb file is found in the paths' do
+ it 'raises an exception' do
+ expect { finder.find(context) }.to raise_error(RuntimeError, /Config file 'navigation.rb' not found in path\(s\)/)
end
end
+ end
- context 'when the context is :other' do
- let(:context) { :other }
+ context 'when the context is :other' do
+ let(:context) { :other }
- context 'and a other_navigation.rb file is found in one of the paths' do
- before { FileUtils.touch('/path/two/other_navigation.rb') }
+ context 'and a other_navigation.rb file is found in one of the paths' do
+ before { FileUtils.touch('/path/two/other_navigation.rb') }
- it 'returns its full path' do
- expect(finder.find(context)).to eq '/path/two/other_navigation.rb'
- end
+ it 'returns its full path' do
+ expect(finder.find(context)).to eq '/path/two/other_navigation.rb'
end
+ end
- context 'and no other_navigation.rb file is found in the paths' do
- it 'raise an exception' do
- expect{ finder.find(context) }.to raise_error(RuntimeError, /Config file 'other_navigation.rb' not found in path\(s\)/)
- end
+ context 'and no other_navigation.rb file is found in the paths' do
+ it 'raise an exception' do
+ expect { finder.find(context) }.to raise_error(RuntimeError, /Config file 'other_navigation.rb' not found in path\(s\)/)
end
end
end
diff --git a/spec/simple_navigation/config_file_spec.rb b/spec/simple_navigation/config_file_spec.rb
index 56d481e3..54ec7037 100644
--- a/spec/simple_navigation/config_file_spec.rb
+++ b/spec/simple_navigation/config_file_spec.rb
@@ -1,24 +1,24 @@
+# frozen_string_literal: true
+
require 'simple_navigation/config_file'
-module SimpleNavigation
- describe ConfigFile do
- subject(:config_file) { ConfigFile.new(context) }
+RSpec.describe SimpleNavigation::ConfigFile do
+ subject(:config_file) { described_class.new(context) }
- let(:context) { :default }
+ let(:context) { :default }
- describe '#name' do
- context 'when the context is :default' do
- it 'returns navigation.rb' do
- expect(config_file.name).to eq 'navigation.rb'
- end
+ describe '#name' do
+ context 'when the context is :default' do
+ it 'returns navigation.rb' do
+ expect(config_file.name).to eq 'navigation.rb'
end
+ end
- context 'when the context is different from :default' do
- let(:context) { :HelloWorld }
+ context 'when the context is different from :default' do
+ let(:context) { :HelloWorld }
- it 'returns UNDERSCORED_CONTEXT_navigation.rb' do
- expect(config_file.name).to eq 'hello_world_navigation.rb'
- end
+ it 'returns UNDERSCORED_CONTEXT_navigation.rb' do
+ expect(config_file.name).to eq 'hello_world_navigation.rb'
end
end
end
diff --git a/spec/simple_navigation/configuration_spec.rb b/spec/simple_navigation/configuration_spec.rb
index da4790f4..29aea865 100644
--- a/spec/simple_navigation/configuration_spec.rb
+++ b/spec/simple_navigation/configuration_spec.rb
@@ -1,164 +1,164 @@
-module SimpleNavigation
- describe Configuration do
- subject(:config) { Configuration.instance }
+# frozen_string_literal: true
- describe '.run' do
- it "yields the singleton Configuration object" do
- expect{ |blk| Configuration.run(&blk) }.to yield_with_args(config)
- end
+RSpec.describe SimpleNavigation::Configuration do
+ subject(:config) { described_class.instance }
+
+ describe '.run' do
+ it 'yields the singleton Configuration object' do
+ expect { |blk| described_class.run(&blk) }.to yield_with_args(config)
end
+ end
- describe '.eval_config' do
- let(:config_files) {{ default: 'default', my_context: 'my_context' }}
- let(:eval_context) { double(:eval_context) }
+ describe '.eval_config' do
+ let(:config_files) { { default: 'default', my_context: 'my_context' } }
+ let(:eval_context) { double(:eval_context) }
- before do
- allow(eval_context).to receive(:instance_eval)
- allow(SimpleNavigation).to \
- receive_messages(context_for_eval: eval_context, config_files: config_files)
- end
+ before do
+ allow(eval_context).to receive(:instance_eval)
+ allow(SimpleNavigation).to \
+ receive_messages(context_for_eval: eval_context, config_files: config_files)
+ end
- context "with default navigation context" do
- it "calls instance_eval with the default config_file-string inside the context" do
- expect(eval_context).to receive(:instance_eval).with('default')
- Configuration.eval_config
- end
+ context 'with default navigation context' do
+ it 'calls instance_eval with the default config_file-string inside the context' do
+ expect(eval_context).to receive(:instance_eval).with('default')
+ described_class.eval_config
end
+ end
- context 'with non default navigation context' do
- it "calls instance_eval with the specified config_file-string inside the context" do
- expect(eval_context).to receive(:instance_eval).with('my_context')
- Configuration.eval_config(:my_context)
- end
+ context 'with non default navigation context' do
+ it 'calls instance_eval with the specified config_file-string inside the context' do
+ expect(eval_context).to receive(:instance_eval).with('my_context')
+ described_class.eval_config(:my_context)
end
end
+ end
- describe '#initialize' do
- it 'sets the List-Renderer as default' do
- expect(config.renderer).to be Renderer::List
- end
+ describe '#initialize' do
+ it 'sets the List-Renderer as default' do
+ expect(config.renderer).to be SimpleNavigation::Renderer::List
+ end
- it 'sets the selected_class to "selected" as default' do
- expect(config.selected_class).to eq 'selected'
- end
+ it 'sets the selected_class to "selected" as default' do
+ expect(config.selected_class).to eq 'selected'
+ end
- it 'sets the active_leaf_class to "simple-navigation-active-leaf" as default' do
- expect(config.active_leaf_class).to eq 'simple-navigation-active-leaf'
- end
+ it 'sets the active_leaf_class to "simple-navigation-active-leaf" as default' do
+ expect(config.active_leaf_class).to eq 'simple-navigation-active-leaf'
+ end
- it 'sets autogenerate_item_ids to true as default' do
- expect(config.autogenerate_item_ids).to be true
- end
+ it 'sets autogenerate_item_ids to true as default' do
+ expect(config.autogenerate_item_ids).to be true
+ end
- it 'sets auto_highlight to true as default' do
- expect(config.auto_highlight).to be true
- end
+ it 'sets auto_highlight to true as default' do
+ expect(config.auto_highlight).to be true
+ end
- it 'sets the id_generator to a callable object' do
- expect(config.id_generator).to respond_to(:call)
- end
+ it 'sets the id_generator to a callable object' do
+ expect(config.id_generator).to respond_to(:call)
+ end
- it 'sets the name_generator to a callable object' do
- expect(config.name_generator).to respond_to(:call)
- end
+ it 'sets the name_generator to a callable object' do
+ expect(config.name_generator).to respond_to(:call)
+ end
- it 'sets the consider_item_names_as_safe to false' do
- expect(config.consider_item_names_as_safe).to be false
- end
+ it 'sets the consider_item_names_as_safe to false' do
+ expect(config.consider_item_names_as_safe).to be false
+ end
- it 'sets highlights_on_subpath to false as default' do
- expect(config.highlight_on_subpath).to be false
- end
-
- it 'sets ignore_query_params_on_auto_highlight to true as default' do
- expect(config.ignore_query_params_on_auto_highlight).to be true
- end
+ it 'sets highlights_on_subpath to false as default' do
+ expect(config.highlight_on_subpath).to be false
+ end
- it 'sets ignore_anchors_on_auto_highlight to true as default' do
- expect(config.ignore_anchors_on_auto_highlight).to be true
- end
+ it 'sets ignore_query_params_on_auto_highlight to true as default' do
+ expect(config.ignore_query_params_on_auto_highlight).to be true
+ end
+
+ it 'sets ignore_anchors_on_auto_highlight to true as default' do
+ expect(config.ignore_anchors_on_auto_highlight).to be true
end
+ end
- describe '#items' do
- let(:container) { double(:items_container) }
+ describe '#items' do
+ let(:container) { double(:items_container) }
- before { allow(ItemContainer).to receive_messages(new: container) }
+ before { allow(SimpleNavigation::ItemContainer).to receive_messages(new: container) }
- context 'when a block is given' do
- context 'and items_provider is specified' do
- let(:provider) { double(:provider) }
+ context 'when a block is given' do
+ context 'and items_provider is specified' do
+ let(:provider) { double(:provider) }
- it 'raises an exception' do
- expect{ config.items(provider) {} }.to raise_error(RuntimeError, 'please specify either items_provider or block, but not both')
- end
+ it 'raises an exception' do
+ expect { config.items(provider) {} }.to raise_error(RuntimeError, 'please specify either items_provider or block, but not both') # rubocop:disable Lint/EmptyBlock
end
+ end
- context 'when no items_provider is specified' do
- it 'yields an new ItemContainer' do
- expect{ |blk| config.items(&blk) }.to yield_with_args(container)
- end
+ context 'when no items_provider is specified' do
+ it 'yields an new ItemContainer' do
+ expect { |blk| config.items(&blk) }.to yield_with_args(container)
+ end
- it 'assigns the ItemContainer to an instance-var' do
- config.items {}
- expect(config.primary_navigation).to be container
- end
+ it 'assigns the ItemContainer to an instance-var' do
+ config.items {} # rubocop:disable Lint/EmptyBlock
+ expect(config.primary_navigation).to be container
+ end
- it "doesn't set the items on the container" do
- expect(container).not_to receive(:items=)
- config.items {}
- end
+ it "doesn't set the items on the container" do
+ expect(container).not_to receive(:items=)
+ config.items {} # rubocop:disable Lint/EmptyBlock
end
end
+ end
- context 'when no block is given' do
- context 'and items_provider is specified' do
- let(:external_provider) { double(:external_provider) }
- let(:items) { double(:items) }
- let(:items_provider) { double(:items_provider, items: items) }
-
- before do
- allow(SimpleNavigation::ItemsProvider).to receive_messages(new: items_provider)
- allow(container).to receive(:items=)
- end
-
- it 'creates a new Provider object for the specified provider' do
- expect(ItemsProvider).to receive(:new).with(external_provider)
- config.items(external_provider)
- end
-
- it 'calls items on the provider object' do
- expect(items_provider).to receive(:items)
- config.items(external_provider)
- end
-
- it 'sets the items on the container' do
- expect(container).to receive(:items=).with(items)
- config.items(external_provider)
- end
+ context 'when no block is given' do
+ context 'and items_provider is specified' do
+ let(:external_provider) { double(:external_provider) }
+ let(:items) { double(:items) }
+ let(:items_provider) { double(:items_provider, items: items) }
+
+ before do
+ allow(SimpleNavigation::ItemsProvider).to receive_messages(new: items_provider)
+ allow(container).to receive(:items=)
end
- context 'when items_provider is not specified' do
- it "raises an exception" do
- expect{ config.items }.to raise_error(RuntimeError, 'please specify either items_provider or block, but not both')
- end
+ it 'creates a new Provider object for the specified provider' do
+ expect(SimpleNavigation::ItemsProvider).to receive(:new).with(external_provider)
+ config.items(external_provider)
end
- end
- end
- describe '#loaded?' do
- context 'when primary_nav is set' do
- it 'returns true' do
- config.instance_variable_set(:@primary_navigation, :bla)
- expect(config).to be_loaded
+ it 'calls items on the provider object' do
+ expect(items_provider).to receive(:items)
+ config.items(external_provider)
+ end
+
+ it 'sets the items on the container' do
+ expect(container).to receive(:items=).with(items)
+ config.items(external_provider)
end
end
- context 'when primary_nav is not set' do
- it 'returns false if no primary_nav is set' do
- config.instance_variable_set(:@primary_navigation, nil)
- expect(config).not_to be_loaded
+ context 'when items_provider is not specified' do
+ it 'raises an exception' do
+ expect { config.items }.to raise_error(RuntimeError, 'please specify either items_provider or block, but not both')
end
end
end
end
+
+ describe '#loaded?' do
+ context 'when primary_nav is set' do
+ it 'returns true' do
+ config.instance_variable_set(:@primary_navigation, :bla)
+ expect(config).to be_loaded
+ end
+ end
+
+ context 'when primary_nav is not set' do
+ it 'returns false if no primary_nav is set' do
+ config.instance_variable_set(:@primary_navigation, nil)
+ expect(config).not_to be_loaded
+ end
+ end
+ end
end
diff --git a/spec/simple_navigation/helpers_spec.rb b/spec/simple_navigation/helpers_spec.rb
index f6b720dd..802086ce 100644
--- a/spec/simple_navigation/helpers_spec.rb
+++ b/spec/simple_navigation/helpers_spec.rb
@@ -1,34 +1,59 @@
-module SimpleNavigation
- describe Helpers do
- subject(:controller) { test_controller_class.new }
-
- let(:invoices_item) { navigation[:invoices] }
- let(:item) { nil }
- let(:navigation) { setup_navigation('nav_id', 'nav_class') }
- let(:test_controller_class) do
- Class.new { include SimpleNavigation::Helpers }
- end
- let(:unpaid_item) { invoices_item.sub_navigation[:unpaid] }
+# frozen_string_literal: true
+
+RSpec.describe SimpleNavigation::Helpers do
+ subject(:controller) { test_controller_class.new }
+
+ let(:invoices_item) { navigation[:invoices] }
+ let(:item) { nil }
+ let(:navigation) { setup_navigation('nav_id', 'nav_class') }
+ let(:test_controller_class) do
+ Class.new { include SimpleNavigation::Helpers }
+ end
+ let(:unpaid_item) { invoices_item.sub_navigation[:unpaid] }
+
+ before do
+ allow(SimpleNavigation::Configuration).to receive(:eval_config)
+ allow(SimpleNavigation).to receive_messages(load_config: nil,
+ primary_navigation: navigation,
+ config_file?: true,
+ context_for_eval: controller)
+
+ select_an_item(navigation[item]) if item
+ end
+
+ describe '#active_navigation_item_name' do
+ context 'when no item is selected' do
+ it 'returns an empty string for no parameters' do
+ expect(controller.active_navigation_item_name).to eq ''
+ end
+
+ it 'returns an empty string for level: 1' do
+ item_name = controller.active_navigation_item_name(level: 1)
+ expect(item_name).to eq ''
+ end
- before do
- allow(Configuration).to receive(:eval_config)
- allow(SimpleNavigation).to receive_messages(load_config: nil,
- primary_navigation: navigation,
- config_file?: true,
- context_for_eval: controller)
+ it 'returns an empty string for level: 2' do
+ item_name = controller.active_navigation_item_name(level: 2)
+ expect(item_name).to eq ''
+ end
- select_an_item(navigation[item]) if item
+ it 'returns an empty string for level: :all' do
+ item_name = controller.active_navigation_item_name(level: :all)
+ expect(item_name).to eq ''
+ end
end
- describe '#active_navigation_item_name' do
- context 'when no item is selected' do
- it 'returns an empty string for no parameters' do
+ context 'when an item is selected' do
+ context "and it's a primary item" do
+ let(:item) { :invoices }
+
+ it 'returns an empty string' do
expect(controller.active_navigation_item_name).to eq ''
end
- it "returns an empty string for level: 1" do
+ it "returns the selected item's name for level: 1" do
item_name = controller.active_navigation_item_name(level: 1)
- expect(item_name).to eq ''
+ expect(item_name).to eq 'Invoices'
end
it 'returns an empty string for level: 2' do
@@ -42,71 +67,67 @@ module SimpleNavigation
end
end
- context 'when an item is selected' do
- context "and it's a primary item" do
- let(:item) { :invoices }
-
- it 'returns an empty string' do
- expect(controller.active_navigation_item_name).to eq ''
- end
+ context "and it's a sub navigation item" do
+ before do
+ select_an_item(invoices_item)
+ select_an_item(unpaid_item)
+ end
- it "returns the selected item's name for level: 1" do
- item_name = controller.active_navigation_item_name(level: 1)
- expect(item_name).to eq 'Invoices'
- end
+ it "returns the selected item's name" do
+ expect(controller.active_navigation_item_name).to eq 'Unpaid'
+ end
- it 'returns an empty string for level: 2' do
- item_name = controller.active_navigation_item_name(level: 2)
- expect(item_name).to eq ''
- end
+ it "returns the selected item's parent name for level: 1" do
+ item_name = controller.active_navigation_item_name(level: 1)
+ expect(item_name).to eq 'Invoices'
+ end
- it 'returns an empty string for level: :all' do
- item_name = controller.active_navigation_item_name(level: :all)
- expect(item_name).to eq ''
- end
+ it "returns the selected item's name for level: 2" do
+ item_name = controller.active_navigation_item_name(level: 2)
+ expect(item_name).to eq 'Unpaid'
end
- context "and it's a sub navigation item" do
- before do
- select_an_item(invoices_item)
- select_an_item(unpaid_item)
- end
+ it "returns the selected item's name for level: :all" do
+ item_name = controller.active_navigation_item_name(level: :all)
+ expect(item_name).to eq 'Unpaid'
+ end
+ end
+ end
+ end
- it "returns the selected item's name" do
- expect(controller.active_navigation_item_name).to eq 'Unpaid'
- end
+ describe '#active_navigation_item_key' do
+ context 'when no item is selected' do
+ it 'returns nil for no parameters' do
+ expect(controller.active_navigation_item_key).to be_nil
+ end
- it "returns the selected item's parent name for level: 1" do
- item_name = controller.active_navigation_item_name(level: 1)
- expect(item_name).to eq 'Invoices'
- end
+ it 'returns nil for level: 1' do
+ item_key = controller.active_navigation_item_key(level: 1)
+ expect(item_key).to be_nil
+ end
- it "returns the selected item's name for level: 2" do
- item_name = controller.active_navigation_item_name(level: 2)
- expect(item_name).to eq 'Unpaid'
- end
+ it 'returns nil for level: 2' do
+ item_key = controller.active_navigation_item_key(level: 2)
+ expect(item_key).to be_nil
+ end
- it "returns the selected item's name for level: :all" do
- item_name = controller.active_navigation_item_name(level: :all)
- expect(item_name).to eq 'Unpaid'
- end
- end
+ it 'returns nil for level: :all' do
+ item_key = controller.active_navigation_item_key(level: :all)
+ expect(item_key).to be_nil
end
end
- describe '#active_navigation_item_key' do
- context 'when no item is selected' do
- it 'returns nil' do
- expect(controller.active_navigation_item_key).to be_nil
- end
+ context 'when an item is selected' do
+ context "and it's a primary item" do
+ let(:item) { :invoices }
it 'returns nil for no parameters' do
expect(controller.active_navigation_item_key).to be_nil
end
- it "returns nil for level: 1" do
+ it "returns the selected item's name for level: 1" do
item_key = controller.active_navigation_item_key(level: 1)
- expect(item_key).to be_nil
+ expect(item_key).to eq :invoices
end
it 'returns nil for level: 2' do
@@ -120,67 +141,67 @@ module SimpleNavigation
end
end
- context 'when an item is selected' do
- context "and it's a primary item" do
- let(:item) { :invoices }
-
- it 'returns nil for no parameters' do
- expect(controller.active_navigation_item_key).to be_nil
- end
+ context "and it's a sub navigation item" do
+ before do
+ select_an_item(invoices_item)
+ select_an_item(unpaid_item)
+ end
- it "returns the selected item's name for level: 1" do
- item_key = controller.active_navigation_item_key(level: 1)
- expect(item_key).to eq :invoices
- end
+ it "returns the selected item's name" do
+ expect(controller.active_navigation_item_key).to eq :unpaid
+ end
- it 'returns nil for level: 2' do
- item_key = controller.active_navigation_item_key(level: 2)
- expect(item_key).to be_nil
- end
+ it "returns the selected item's parent name for level: 1" do
+ item_key = controller.active_navigation_item_key(level: 1)
+ expect(item_key).to eq :invoices
+ end
- it 'returns nil for level: :all' do
- item_key = controller.active_navigation_item_key(level: :all)
- expect(item_key).to be_nil
- end
+ it "returns the selected item's name for level: 2" do
+ item_key = controller.active_navigation_item_key(level: 2)
+ expect(item_key).to eq :unpaid
end
- context "and it's a sub navigation item" do
- before do
- select_an_item(invoices_item)
- select_an_item(unpaid_item)
- end
+ it "returns the selected item's name for level: :all" do
+ item_key = controller.active_navigation_item_key(level: :all)
+ expect(item_key).to eq :unpaid
+ end
+ end
+ end
+ end
- it "returns the selected item's name" do
- expect(controller.active_navigation_item_key).to eq :unpaid
- end
+ describe '#active_navigation_item' do
+ context 'when no item is selected' do
+ it 'returns nil for no parameters' do
+ expect(controller.active_navigation_item).to be_nil
+ end
- it "returns the selected item's parent name for level: 1" do
- item_key = controller.active_navigation_item_key(level: 1)
- expect(item_key).to eq :invoices
- end
+ it 'returns nil for level: 1' do
+ item_key = controller.active_navigation_item(level: 1)
+ expect(item_key).to be_nil
+ end
- it "returns the selected item's name for level: 2" do
- item_key = controller.active_navigation_item_key(level: 2)
- expect(item_key).to eq :unpaid
- end
+ it 'returns nil for level: 2' do
+ item_key = controller.active_navigation_item(level: 2)
+ expect(item_key).to be_nil
+ end
- it "returns the selected item's name for level: :all" do
- item_key = controller.active_navigation_item_key(level: :all)
- expect(item_key).to eq :unpaid
- end
- end
+ it 'returns nil for level: :all' do
+ item_key = controller.active_navigation_item(level: :all)
+ expect(item_key).to be_nil
end
end
- describe '#active_navigation_item' do
- context 'when no item is selected' do
+ context 'when an item is selected' do
+ context "and it's a primary item" do
+ let(:item) { :invoices }
+
it 'returns nil for no parameters' do
expect(controller.active_navigation_item).to be_nil
end
- it "returns nil for level: 1" do
+ it "returns the selected item's name for level: 1" do
item_key = controller.active_navigation_item(level: 1)
- expect(item_key).to be_nil
+ expect(item_key).to be invoices_item
end
it 'returns nil for level: 2' do
@@ -194,235 +215,210 @@ module SimpleNavigation
end
end
- context 'when an item is selected' do
- context "and it's a primary item" do
- let(:item) { :invoices }
+ context "and it's a sub navigation item" do
+ before do
+ select_an_item(invoices_item)
+ select_an_item(unpaid_item)
+ end
- it 'returns nil for no parameters' do
- expect(controller.active_navigation_item).to be_nil
- end
+ it "returns the selected item's name for no parameters" do
+ expect(controller.active_navigation_item).to be unpaid_item
+ end
- it "returns the selected item's name for level: 1" do
- item_key = controller.active_navigation_item(level: 1)
- expect(item_key).to be invoices_item
- end
+ it "returns the selected item's parent name for level: 1" do
+ item_key = controller.active_navigation_item(level: 1)
+ expect(item_key).to be invoices_item
+ end
- it 'returns nil for level: 2' do
- item_key = controller.active_navigation_item(level: 2)
- expect(item_key).to be_nil
- end
+ it "returns the selected item's name for level: 2" do
+ item_key = controller.active_navigation_item(level: 2)
+ expect(item_key).to eq unpaid_item
+ end
- it 'returns nil for level: :all' do
- item_key = controller.active_navigation_item(level: :all)
- expect(item_key).to be_nil
- end
+ it "returns the selected item's name for level: :all" do
+ item_key = controller.active_navigation_item(level: :all)
+ expect(item_key).to eq unpaid_item
end
+ end
+ end
+ end
- context "and it's a sub navigation item" do
- before do
- select_an_item(invoices_item)
- select_an_item(unpaid_item)
- end
+ describe '#active_navigation_item_container' do
+ shared_examples 'returning items container' do
+ it 'returns the primary navigation for no parameters' do
+ expect(controller.active_navigation_item_container).to be navigation
+ end
- it "returns the selected item's name for no parameters" do
- expect(controller.active_navigation_item).to be unpaid_item
- end
+ it 'returns the primary navigation for level: 1' do
+ item_container = controller.active_navigation_item_container(level: 1)
+ expect(item_container).to be navigation
+ end
- it "returns the selected item's parent name for level: 1" do
- item_key = controller.active_navigation_item(level: 1)
- expect(item_key).to be invoices_item
- end
+ it 'returns the primary navigation level: :all' do
+ item_container =
+ controller.active_navigation_item_container(level: :all)
+ expect(item_container).to be navigation
+ end
+ end
- it "returns the selected item's name for level: 2" do
- item_key = controller.active_navigation_item(level: 2)
- expect(item_key).to eq unpaid_item
- end
+ context 'when no item is selected' do
+ it_behaves_like 'returning items container'
- it "returns the selected item's name for level: :all" do
- item_key = controller.active_navigation_item(level: :all)
- expect(item_key).to eq unpaid_item
- end
- end
+ it 'returns nil for level: 2' do
+ item_container = controller.active_navigation_item_container(level: 2)
+ expect(item_container).to be_nil
end
end
- describe '#active_navigation_item_container' do
- shared_examples 'returning items container' do
- it 'returns the primary navigation for no parameters' do
- expect(controller.active_navigation_item_container).to be navigation
- end
+ context 'when an item is selected' do
+ context "and it's a primary item" do
+ let(:item) { :invoices }
- it "returns the primary navigation for level: 1" do
- item_container = controller.active_navigation_item_container(level: 1)
- expect(item_container).to be navigation
- end
+ it_behaves_like 'returning items container'
- it 'returns the primary navigation level: :all' do
+ it 'returns the invoices items container for level: 2' do
item_container =
- controller.active_navigation_item_container(level: :all)
- expect(item_container).to be navigation
+ controller.active_navigation_item_container(level: 2)
+ expect(item_container).to be invoices_item.sub_navigation
end
end
- context 'when no item is selected' do
- it_behaves_like 'returning items container'
-
- it 'returns nil for level: 2' do
- item_container = controller.active_navigation_item_container(level: 2)
- expect(item_container).to be_nil
+ context "and it's a sub navigation item" do
+ before do
+ select_an_item(invoices_item)
+ select_an_item(unpaid_item)
end
- end
- context 'when an item is selected' do
- context "and it's a primary item" do
- let(:item) { :invoices }
-
- it_behaves_like 'returning items container'
+ it_behaves_like 'returning items container'
- it 'returns the invoices items container for level: 2' do
- item_container =
- controller.active_navigation_item_container(level: 2)
- expect(item_container).to be invoices_item.sub_navigation
- end
+ it 'returns the invoices items container for level: 2' do
+ item_container =
+ controller.active_navigation_item_container(level: 2)
+ expect(item_container).to be invoices_item.sub_navigation
end
+ end
+ end
+ end
- context "and it's a sub navigation item" do
- before do
- select_an_item(invoices_item)
- select_an_item(unpaid_item)
- end
+ describe '#render_navigation' do
+ it 'evaluates the configuration on every request' do
+ expect(SimpleNavigation).to receive(:load_config).twice
+ 2.times { controller.render_navigation }
+ end
- it_behaves_like 'returning items container'
+ it 'loads the :default configuration' do
+ expect(SimpleNavigation).to receive(:load_config).with(:default)
+ controller.render_navigation
+ end
- it 'returns the invoices items container for level: 2' do
- item_container =
- controller.active_navigation_item_container(level: 2)
- expect(item_container).to be invoices_item.sub_navigation
- end
- end
- end
+ it "doesn't set the items directly" do
+ expect(SimpleNavigation.config).not_to receive(:items)
+ controller.render_navigation
end
- describe '#render_navigation' do
- it 'evaluates the configuration on every request' do
- expect(SimpleNavigation).to receive(:load_config).twice
- 2.times { controller.render_navigation }
- end
+ it 'looks up the active_item_container based on the level' do
+ expect(SimpleNavigation).to receive(:active_item_container_for)
+ .with(:all)
+ controller.render_navigation
+ end
- it 'loads the :default configuration' do
- expect(SimpleNavigation).to receive(:load_config).with(:default)
- controller.render_navigation
+ context 'when the :context option is specified' do
+ it 'loads the configuration for the specified context' do
+ expect(SimpleNavigation).to receive(:load_config).with(:my_context)
+ controller.render_navigation(context: :my_context)
end
+ end
- it "doesn't set the items directly" do
- expect(SimpleNavigation.config).not_to receive(:items)
- controller.render_navigation
- end
+ context 'when the :items option is specified' do
+ let(:items) { double(:items) }
- it 'looks up the active_item_container based on the level' do
- expect(SimpleNavigation).to receive(:active_item_container_for)
- .with(:all)
- controller.render_navigation
+ it 'sets the items directly' do
+ expect(SimpleNavigation.config).to receive(:items).with(items)
+ controller.render_navigation(items: items)
end
+ end
- context 'when the :context option is specified' do
- it 'loads the configuration for the specified context' do
- expect(SimpleNavigation).to receive(:load_config).with(:my_context)
- controller.render_navigation(context: :my_context)
+ context 'when the :level option is set' do
+ context 'and its value is 1' do
+ it 'calls render on the primary navigation' do
+ expect(navigation).to receive(:render).with({ level: 1 })
+ controller.render_navigation(level: 1)
end
end
- context 'when the :items option is specified' do
- let(:items) { double(:items) }
+ context 'and its value is 2' do
+ context 'and the active_item_container is set' do
+ let(:item_container) { double(:container).as_null_object }
- it 'sets the items directly' do
- expect(SimpleNavigation.config).to receive(:items).with(items)
- controller.render_navigation(items: items)
- end
- end
-
- context 'when the :level option is set' do
- context 'and its value is 1' do
- it 'calls render on the primary navigation' do
- expect(navigation).to receive(:render).with(level: 1)
- controller.render_navigation(level: 1)
+ before do
+ allow(SimpleNavigation).to receive_messages(active_item_container_for: item_container)
end
- end
-
- context 'and its value is 2' do
- context 'and the active_item_container is set' do
- let(:item_container) { double(:container).as_null_object }
-
- before do
- allow(SimpleNavigation).to receive_messages(active_item_container_for: item_container)
- end
-
- it 'finds the selected sub navigation for the specified level' do
- expect(SimpleNavigation).to receive(:active_item_container_for)
- .with(2)
- controller.render_navigation(level: 2)
- end
- it 'calls render on the active item_container' do
- expect(item_container).to receive(:render).with(level: 2)
- controller.render_navigation(level: 2)
- end
+ it 'finds the selected sub navigation for the specified level' do
+ expect(SimpleNavigation).to receive(:active_item_container_for)
+ .with(2)
+ controller.render_navigation(level: 2)
end
- context "and the active_item_container isn't set" do
- it "doesn't raise an exception" do
- expect{
- controller.render_navigation(level: 2)
- }.not_to raise_error
- end
+ it 'calls render on the active item_container' do
+ expect(item_container).to receive(:render).with({ level: 2 })
+ controller.render_navigation(level: 2)
end
end
- context "and its value isn't a valid level" do
- it 'raises an exception' do
- expect{
- controller.render_navigation(level: :invalid)
- }.to raise_error(ArgumentError, 'Invalid navigation level: invalid')
+ context "and the active_item_container isn't set" do
+ it "doesn't raise an exception" do
+ expect {
+ controller.render_navigation(level: 2)
+ }.not_to raise_error
end
end
end
- context 'when the :levels option is set' do
- before { allow(SimpleNavigation).to receive_messages(active_item_container_for: navigation) }
-
- it 'treats it like the :level option' do
- expect(navigation).to receive(:render).with(level: 2)
- controller.render_navigation(levels: 2)
+ context "and its value isn't a valid level" do
+ it 'raises an exception' do
+ expect {
+ controller.render_navigation(level: :invalid)
+ }.to raise_error(ArgumentError, 'Invalid navigation level: invalid')
end
end
+ end
- context 'when a block is given' do
- it 'calls the block passing it an item container' do
- expect{ |blk|
- controller.render_navigation(&blk)
- }.to yield_with_args(ItemContainer)
- end
+ context 'when the :levels option is set' do
+ before { allow(SimpleNavigation).to receive_messages(active_item_container_for: navigation) }
+
+ it 'treats it like the :level option' do
+ expect(navigation).to receive(:render).with({ level: 2 })
+ controller.render_navigation(levels: 2)
end
+ end
- context 'when no primary configuration is defined' do
- before { allow(SimpleNavigation).to receive_messages(primary_navigation: nil) }
+ context 'when a block is given' do
+ it 'calls the block passing it an item container' do
+ expect { |blk|
+ controller.render_navigation(&blk)
+ }.to yield_with_args(SimpleNavigation::ItemContainer)
+ end
+ end
- it 'raises an exception' do
- expect{controller.render_navigation}.to raise_error(RuntimeError, 'no primary navigation defined, either use a navigation config file or pass items directly to render_navigation')
- end
+ context 'when no primary configuration is defined' do
+ before { allow(SimpleNavigation).to receive_messages(primary_navigation: nil) }
+
+ it 'raises an exception' do
+ expect { controller.render_navigation }.to raise_error(RuntimeError, 'no primary navigation defined, either use a navigation config file or pass items directly to render_navigation')
end
+ end
- context "when active_item_container is set" do
- let(:active_item_container) { double(:container).as_null_object }
+ context 'when active_item_container is set' do
+ let(:active_item_container) { double(:container).as_null_object }
- before do
- allow(SimpleNavigation).to receive_messages(active_item_container_for: active_item_container)
- end
+ before do
+ allow(SimpleNavigation).to receive_messages(active_item_container_for: active_item_container)
+ end
- it 'calls render on the active_item_container' do
- expect(active_item_container).to receive(:render)
- controller.render_navigation
- end
+ it 'calls render on the active_item_container' do
+ expect(active_item_container).to receive(:render)
+ controller.render_navigation
end
end
end
diff --git a/spec/simple_navigation/item_adapter_spec.rb b/spec/simple_navigation/item_adapter_spec.rb
index db672712..9ecbf55f 100644
--- a/spec/simple_navigation/item_adapter_spec.rb
+++ b/spec/simple_navigation/item_adapter_spec.rb
@@ -1,187 +1,172 @@
-module SimpleNavigation
- describe ItemAdapter do
- let(:item_adapter) { ItemAdapter.new(item) }
+# frozen_string_literal: true
- context 'when item is an object' do
- let(:item) { double(:item, key: 'key', name: 'name', url: 'url') }
+RSpec.describe SimpleNavigation::ItemAdapter do
+ let(:item_adapter) { described_class.new(item) }
- shared_examples 'delegating to item' do |meth|
- it "delegates #{meth} to item" do
- expect(item).to receive(meth)
- item_adapter.public_send(meth)
- end
+ context 'when item is an object' do
+ let(:item) { double(:item, key: 'key', name: 'name', url: 'url') }
+
+ shared_examples 'delegating to item' do |meth|
+ it "delegates #{meth} to item" do
+ expect(item).to receive(meth)
+ item_adapter.public_send(meth)
end
+ end
- it_behaves_like 'delegating to item', :key
- it_behaves_like 'delegating to item', :url
- it_behaves_like 'delegating to item', :name
+ it_behaves_like 'delegating to item', :key
+ it_behaves_like 'delegating to item', :url
+ it_behaves_like 'delegating to item', :name
- describe '#initialize' do
- it 'sets the item' do
- expect(item_adapter.item).to be item
- end
+ describe '#initialize' do
+ it 'sets the item' do
+ expect(item_adapter.item).to be item
end
+ end
- describe '#options' do
- context 'when item responds to options' do
- let(:options) { double(:options) }
+ describe '#options' do
+ context 'when item responds to options' do
+ let(:options) { double(:options) }
- before { allow(item).to receive_messages(options: options) }
+ before { allow(item).to receive_messages(options: options) }
- it "returns the item's options" do
- expect(item_adapter.options).to be options
- end
+ it "returns the item's options" do
+ expect(item_adapter.options).to be options
end
+ end
+ end
+
+ describe '#items' do
+ context 'when item responds to items' do
+ context 'and items is nil' do
+ before { allow(item).to receive_messages(items: nil) }
- context 'item does not respond to options' do
- it 'returns an empty hash' do
- expect(item_adapter.options).to eq({})
+ it 'returns nil' do
+ expect(item_adapter.items).to be_nil
end
end
- end
- describe '#items' do
- context 'when item responds to items' do
- context 'and items is nil' do
- before { allow(item).to receive_messages(items: nil) }
+ context 'when items is not nil' do
+ context 'and items is empty' do
+ before { allow(item).to receive_messages(items: []) }
it 'returns nil' do
expect(item_adapter.items).to be_nil
end
end
- context 'when items is not nil' do
- context 'and items is empty' do
- before { allow(item).to receive_messages(items: []) }
+ context 'and items is not empty' do
+ let(:items) { [true] }
- it 'returns nil' do
- expect(item_adapter.items).to be_nil
- end
- end
+ before { allow(item).to receive_messages(items: items) }
- context 'and items is not empty' do
- let(:items) { [true] }
-
- before { allow(item).to receive_messages(items: items) }
-
- it 'returns the items' do
- expect(item_adapter.items).to eq items
- end
+ it 'returns the items' do
+ expect(item_adapter.items).to eq items
end
end
end
-
- context "when item doesn't respond to items" do
- it 'returns nil' do
- expect(item_adapter.items).to be_nil
- end
- end
end
+ end
- describe '#to_simple_navigation_item' do
- let(:container) { double(:container) }
+ describe '#to_simple_navigation_item' do
+ let(:container) { double(:container) }
- before { allow(item).to receive_messages(items: [], options: {}) }
+ before { allow(item).to receive_messages(items: [], options: {}) }
- it 'creates an Item' do
- expect(Item).to receive(:new)
- .with(container, 'key', 'name', 'url', {})
- item_adapter.to_simple_navigation_item(container)
- end
+ it 'creates an Item' do
+ expect(SimpleNavigation::Item).to receive(:new)
+ .with(container, 'key', 'name', 'url', {})
+ item_adapter.to_simple_navigation_item(container)
end
end
+ end
- context 'when item is a kind of hash' do
- class ModifiedHash < Hash; end
-
- let(:item) { ModifiedHash[key: 'key', url: 'url', name: 'name'] }
+ context 'when item is a kind of hash' do
+ let(:item) { ModifiedHash[key: 'key', url: 'url', name: 'name'] }
- shared_examples 'delegating to item' do |meth|
- it "delegates #{meth} to item" do
- expect(item_adapter.item).to receive(meth)
- item_adapter.public_send(meth)
- end
+ shared_examples 'delegating to item' do |meth|
+ it "delegates #{meth} to item" do
+ expect(item_adapter.item).to receive(meth)
+ item_adapter.public_send(meth)
end
+ end
- it_behaves_like 'delegating to item', :key
- it_behaves_like 'delegating to item', :url
- it_behaves_like 'delegating to item', :name
+ it_behaves_like 'delegating to item', :key
+ it_behaves_like 'delegating to item', :url
+ it_behaves_like 'delegating to item', :name
- describe '#initialize' do
- it 'sets the item' do
- expect(item_adapter.item).not_to be_nil
- end
+ describe '#initialize' do
+ it 'sets the item' do
+ expect(item_adapter.item).not_to be_nil
+ end
- it 'converts the item into an object' do
- expect(item_adapter.item).to respond_to(:url)
- end
+ it 'converts the item into an object' do
+ expect(item_adapter.item).to respond_to(:url)
end
+ end
- describe '#options' do
- context 'when item responds to options' do
- before { item[:options] = { my: :options } }
+ describe '#options' do
+ context 'when item responds to options' do
+ before { item[:options] = { my: :options } }
- it "returns the item's options" do
- expect(item_adapter.options).to eq({ my: :options })
- end
+ it "returns the item's options" do
+ expect(item_adapter.options).to eq({ my: :options })
end
+ end
- context 'when item does not respond to options' do
- it 'returns an empty hash' do
- expect(item_adapter.options).to eq({})
- end
+ context 'when item does not respond to options' do
+ it 'returns an empty hash' do
+ expect(item_adapter.options).to eq({})
end
end
+ end
- describe '#items' do
- context 'when item responds to items' do
- context 'and items is nil' do
- before { item[:items] = nil }
+ describe '#items' do
+ context 'when item responds to items' do
+ context 'and items is nil' do
+ before { item[:items] = nil }
+
+ it 'returns nil' do
+ expect(item_adapter.items).to be_nil
+ end
+ end
+ context 'when items is not nil' do
+ context 'and items is empty' do
it 'returns nil' do
expect(item_adapter.items).to be_nil
end
end
- context 'when items is not nil' do
- context 'and items is empty' do
- it 'returns nil' do
- expect(item_adapter.items).to be_nil
- end
- end
-
- context 'and items is not empty' do
- before { item[:items] = ['not', 'empty'] }
+ context 'and items is not empty' do
+ before { item[:items] = %w[not empty] }
- it 'returns the items' do
- expect(item_adapter.items).to eq ['not', 'empty']
- end
+ it 'returns the items' do
+ expect(item_adapter.items).to eq %w[not empty]
end
end
end
+ end
- context 'when item does not respond to items' do
- it 'returns nil' do
- expect(item_adapter.items).to be_nil
- end
+ context 'when item does not respond to items' do
+ it 'returns nil' do
+ expect(item_adapter.items).to be_nil
end
end
+ end
- describe '#to_simple_navigation_item' do
- let(:container) { double(:container) }
+ describe '#to_simple_navigation_item' do
+ let(:container) { double(:container) }
- before { item.merge(options: {}) }
+ before { item.merge(options: {}) }
- it 'passes the right arguments to Item' do
- expect(Item).to receive(:new)
- .with(container, 'key', 'name', 'url', {})
- item_adapter.to_simple_navigation_item(container)
- end
+ it 'passes the right arguments to Item' do
+ expect(SimpleNavigation::Item).to receive(:new).with(container, 'key', 'name', 'url', {})
+ item_adapter.to_simple_navigation_item(container)
+ end
- it 'creates an Item' do
- created_item = item_adapter.to_simple_navigation_item(container)
- expect(created_item).to be_an(Item)
- end
+ it 'creates an Item' do
+ created_item = item_adapter.to_simple_navigation_item(container)
+ expect(created_item).to be_an(SimpleNavigation::Item)
end
end
end
diff --git a/spec/simple_navigation/item_container_spec.rb b/spec/simple_navigation/item_container_spec.rb
index 863e7ddd..f7f23e0d 100644
--- a/spec/simple_navigation/item_container_spec.rb
+++ b/spec/simple_navigation/item_container_spec.rb
@@ -1,599 +1,598 @@
-module SimpleNavigation
- describe ItemContainer do
- subject(:item_container) { ItemContainer.new }
-
- shared_examples 'adding the item to the list' do
- it 'adds the item to the list' do
- allow(Item).to receive_messages(new: item)
- item_container.item(*args)
- expect(item_container.items).to include(item)
- end
+# frozen_string_literal: true
+
+RSpec.describe SimpleNavigation::ItemContainer do
+ subject(:item_container) { described_class.new }
+
+ shared_examples 'adding the item to the list' do
+ it 'adds the item to the list' do
+ allow(SimpleNavigation::Item).to receive_messages(new: item)
+ item_container.item(*args)
+ expect(item_container.items).to include(item)
end
+ end
- shared_examples 'not adding the item to the list' do
- it "doesn't add the item to the list" do
- allow(Item).to receive_messages(new: item)
- item_container.item(*args)
- expect(item_container.items).not_to include(item)
- end
+ shared_examples 'not adding the item to the list' do
+ it "doesn't add the item to the list" do
+ allow(SimpleNavigation::Item).to receive_messages(new: item)
+ item_container.item(*args)
+ expect(item_container.items).not_to include(item)
end
+ end
- describe '#initialize' do
- it 'sets an empty items array' do
- expect(item_container.items).to be_empty
- end
+ describe '#initialize' do
+ it 'sets an empty items array' do
+ expect(item_container.items).to be_empty
end
+ end
- describe '#dom_attributes' do
- let(:dom_attributes) {{ id: 'test_id', class: 'test_class' }}
+ describe '#dom_attributes' do
+ let(:dom_attributes) { { id: 'test_id', class: 'test_class' } }
- before { item_container.dom_attributes = dom_attributes }
+ before { item_container.dom_attributes = dom_attributes }
- it "returns the container's dom_attributes" do
- expect(item_container.dom_attributes).to eq dom_attributes
- end
+ it "returns the container's dom_attributes" do
+ expect(item_container.dom_attributes).to eq dom_attributes
+ end
- context 'when the dom_attributes do not contain any id or class' do
- let(:dom_attributes) {{ test: 'test' }}
+ context 'when the dom_attributes do not contain any id or class' do
+ let(:dom_attributes) { { test: 'test' } }
- context "and the container hasn't any dom_id" do
- it "returns the contaier's dom_attributes without any id" do
- expect(item_container.dom_attributes).not_to include(:id)
- end
+ context "and the container hasn't any dom_id" do
+ it "returns the contaier's dom_attributes without any id" do
+ expect(item_container.dom_attributes).not_to include(:id)
end
+ end
- context 'and the container has a dom_id' do
- before { item_container.dom_id = 'test_id' }
+ context 'and the container has a dom_id' do
+ before { item_container.dom_id = 'test_id' }
- it "returns the contaier's dom_attributes including the #dom_id" do
- expect(item_container.dom_attributes).to include(id: 'test_id')
- end
+ it "returns the contaier's dom_attributes including the #dom_id" do
+ expect(item_container.dom_attributes).to include(id: 'test_id')
end
+ end
- context "and the container hasn't any dom_class" do
- it "returns the contaier's dom_attributes without any class" do
- expect(item_container.dom_attributes).not_to include(:class)
- end
+ context "and the container hasn't any dom_class" do
+ it "returns the contaier's dom_attributes without any class" do
+ expect(item_container.dom_attributes).not_to include(:class)
end
+ end
- context 'and the container has a dom_class' do
- before { item_container.dom_class = 'test_class' }
+ context 'and the container has a dom_class' do
+ before { item_container.dom_class = 'test_class' }
- it "returns the contaier's dom_attributes including the #dom_class" do
- expect(item_container.dom_attributes).to include(class: 'test_class')
- end
+ it "returns the contaier's dom_attributes including the #dom_class" do
+ expect(item_container.dom_attributes).to include(class: 'test_class')
end
end
end
+ end
- describe '#items=' do
- let(:item) {{ key: :my_key, name: 'test', url: '/' }}
- let(:items) { [item] }
- let(:item_adapter) { double(:item_adapter).as_null_object }
- let(:real_item) { double(:real_item) }
-
- before do
- allow(ItemAdapter).to receive_messages(new: item_adapter)
- allow(item_adapter).to receive(:to_simple_navigation_item)
- .with(item_container)
- .and_return(real_item)
- end
+ describe '#items=' do
+ let(:item) { { key: :my_key, name: 'test', url: '/' } }
+ let(:items) { [item] }
+ let(:item_adapter) { double(:item_adapter).as_null_object }
+ let(:real_item) { double(:real_item) }
+
+ before do
+ allow(SimpleNavigation::ItemAdapter).to receive_messages(new: item_adapter)
+ allow(item_adapter).to receive(:to_simple_navigation_item)
+ .with(item_container)
+ .and_return(real_item)
+ end
- context 'when the item should be added' do
- before { allow(item_container).to receive_messages(should_add_item?: true) }
+ context 'when the item should be added' do
+ before { allow(item_container).to receive_messages(should_add_item?: true) }
- it 'converts it to an Item and adds it to the items collection' do
- item_container.items = items
- expect(item_container.items).to include(real_item)
- end
+ it 'converts it to an Item and adds it to the items collection' do
+ item_container.items = items
+ expect(item_container.items).to include(real_item)
end
+ end
- context 'when the item should not be added' do
- before { allow(item_container).to receive_messages(should_add_item?: false) }
+ context 'when the item should not be added' do
+ before { allow(item_container).to receive_messages(should_add_item?: false) }
- it "doesn't add it to the items collection" do
- item_container.items = items
- expect(item_container.items).not_to include(real_item)
- end
+ it "doesn't add it to the items collection" do
+ item_container.items = items
+ expect(item_container.items).not_to include(real_item)
end
end
+ end
- describe '#selected?' do
- let(:item_1) { double(:item, selected?: false) }
- let(:item_2) { double(:item, selected?: false) }
+ describe '#selected?' do
+ let(:item_1) { double(:item, selected?: false) }
+ let(:item_2) { double(:item, selected?: false) }
- before do
- item_container.instance_variable_set(:@items, [item_1, item_2])
- end
+ before do
+ item_container.instance_variable_set(:@items, [item_1, item_2])
+ end
- context 'when no item is selected' do
- it 'returns nil' do
- expect(item_container).not_to be_selected
- end
+ context 'when no item is selected' do
+ it 'returns nil' do
+ expect(item_container).not_to be_selected
end
+ end
- context 'when an item is selected' do
- it 'returns true' do
- allow(item_1).to receive_messages(selected?: true)
- expect(item_container).to be_selected
- end
+ context 'when an item is selected' do
+ it 'returns true' do
+ allow(item_1).to receive_messages(selected?: true)
+ expect(item_container).to be_selected
end
end
+ end
- describe '#selected_item' do
- let(:item_1) { double(:item, selected?: false) }
- let(:item_2) { double(:item, selected?: false) }
+ describe '#selected_item' do
+ let(:item_1) { double(:item, selected?: false) }
+ let(:item_2) { double(:item, selected?: false) }
- before(:each) do
- allow(SimpleNavigation).to receive_messages(current_navigation_for: :nav)
- allow(item_container).to receive_messages(:[] => nil)
- item_container.instance_variable_set(:@items, [item_1, item_2])
- end
+ before do
+ allow(SimpleNavigation).to receive_messages(current_navigation_for: :nav)
+ allow(item_container).to receive_messages(:[] => nil)
+ item_container.instance_variable_set(:@items, [item_1, item_2])
+ end
- context "when navigation isn't explicitely set" do
- context 'and no item is selected' do
- it 'returns nil' do
- expect(item_container.selected_item).to be_nil
- end
+ context "when navigation isn't explicitely set" do
+ context 'and no item is selected' do
+ it 'returns nil' do
+ expect(item_container.selected_item).to be_nil
end
+ end
- context 'and an item selected' do
- before { allow(item_1).to receive_messages(selected?: true) }
+ context 'and an item selected' do
+ before { allow(item_1).to receive_messages(selected?: true) }
- it 'returns the selected item' do
- expect(item_container.selected_item).to be item_1
- end
+ it 'returns the selected item' do
+ expect(item_container.selected_item).to be item_1
end
end
end
+ end
- describe '#active_item_container_for' do
- context "when the desired level is the same as the container's" do
- it 'returns the container itself' do
- expect(item_container.active_item_container_for(1)).to be item_container
- end
+ describe '#active_item_container_for' do
+ context "when the desired level is the same as the container's" do
+ it 'returns the container itself' do
+ expect(item_container.active_item_container_for(1)).to be item_container
end
+ end
- context "when the desired level is different than the container's" do
- context 'and no subnavigation is selected' do
- before { allow(item_container).to receive_messages(selected_sub_navigation?: false) }
-
- it 'returns nil' do
- expect(item_container.active_item_container_for(2)).to be_nil
- end
- end
-
- context 'and a subnavigation is selected' do
- let(:sub_navigation) { double(:sub_navigation) }
- let(:selected_item) { double(:selected_item) }
-
- before do
- allow(item_container).to \
- receive_messages(selected_sub_navigation?: true, selected_item: selected_item)
- allow(selected_item).to receive_messages(sub_navigation: sub_navigation)
- end
+ context "when the desired level is different than the container's" do
+ context 'and no subnavigation is selected' do
+ before { allow(item_container).to receive_messages(selected_sub_navigation?: false) }
- it 'calls recursively on the sub_navigation' do
- expect(sub_navigation).to receive(:active_item_container_for)
- .with(2)
- item_container.active_item_container_for(2)
- end
+ it 'returns nil' do
+ expect(item_container.active_item_container_for(2)).to be_nil
end
end
- end
- describe '#active_leaf_container' do
- context 'when the current container has a selected subnavigation' do
+ context 'and a subnavigation is selected' do
let(:sub_navigation) { double(:sub_navigation) }
let(:selected_item) { double(:selected_item) }
before do
- allow(item_container).to receive_messages(selected_sub_navigation?: true,
- selected_item: selected_item)
+ allow(item_container).to \
+ receive_messages(selected_sub_navigation?: true, selected_item: selected_item)
allow(selected_item).to receive_messages(sub_navigation: sub_navigation)
end
it 'calls recursively on the sub_navigation' do
- expect(sub_navigation).to receive(:active_leaf_container)
- item_container.active_leaf_container
+ expect(sub_navigation).to receive(:active_item_container_for)
+ .with(2)
+ item_container.active_item_container_for(2)
end
end
+ end
+ end
- context 'when the current container is the leaf already' do
- before { allow(item_container).to receive_messages(selected_sub_navigation?: false) }
+ describe '#active_leaf_container' do
+ context 'when the current container has a selected subnavigation' do
+ let(:sub_navigation) { double(:sub_navigation) }
+ let(:selected_item) { double(:selected_item) }
- it 'returns itsself' do
- expect(item_container.active_leaf_container).to be item_container
- end
+ before do
+ allow(item_container).to receive_messages(selected_sub_navigation?: true,
+ selected_item: selected_item)
+ allow(selected_item).to receive_messages(sub_navigation: sub_navigation)
+ end
+
+ it 'calls recursively on the sub_navigation' do
+ expect(sub_navigation).to receive(:active_leaf_container)
+ item_container.active_leaf_container
+ end
+ end
+
+ context 'when the current container is the leaf already' do
+ before { allow(item_container).to receive_messages(selected_sub_navigation?: false) }
+
+ it 'returns itsself' do
+ expect(item_container.active_leaf_container).to be item_container
end
end
+ end
- describe '#item' do
- let(:options) { Hash.new }
- let(:item) { double(:item) }
+ describe '#item' do
+ let(:options) { {} }
+ let(:item) { double(:item) }
- context 'when a block is given' do
- let(:block) { proc{} }
- let(:sub_container) { double(:sub_container) }
+ context 'when a block is given' do
+ let(:block) { proc {} }
+ let(:sub_container) { double(:sub_container) }
- it 'yields a new ItemContainer' do
- allow_any_instance_of(Item).to \
- receive_messages(sub_navigation: sub_container)
+ it 'yields a new ItemContainer' do
+ allow_any_instance_of(SimpleNavigation::Item).to receive_messages(sub_navigation: sub_container) # rubocop:disable RSpec/AnyInstance
- expect{ |blk|
- item_container.item('key', 'name', 'url', options, &blk)
- }.to yield_with_args(sub_container)
- end
+ expect { |blk|
+ item_container.item('key', 'name', 'url', options, &blk)
+ }.to yield_with_args(sub_container)
+ end
- it "creates a new Item with the given params and block" do
- allow(Item).to receive(:new)
- .with(item_container, 'key', 'name', 'url', options, &block)
- .and_return(item)
- item_container.item('key', 'name', 'url', options, &block)
- expect(item_container.items).to include(item)
- end
+ it 'creates a new Item with the given params and block' do
+ allow(SimpleNavigation::Item).to receive(:new)
+ .with(item_container, 'key', 'name', 'url', options, &block)
+ .and_return(item)
+ item_container.item('key', 'name', 'url', options, &block)
+ expect(item_container.items).to include(item)
+ end
- it 'adds the created item to the list of items' do
- item_container.item('key', 'name', 'url', options) {}
- expect(item_container.items).not_to include(item)
- end
+ it 'adds the created item to the list of items' do
+ item_container.item('key', 'name', 'url', options) {} # rubocop:disable Lint/EmptyBlock
+ expect(item_container.items).not_to include(item)
end
+ end
- context 'when no block is given' do
- it 'creates a new Item with the given params and no sub navigation' do
- allow(Item).to receive(:new)
- .with(item_container, 'key', 'name', 'url', options)
- .and_return(item)
- item_container.item('key', 'name', 'url', options)
- expect(item_container.items).to include(item)
- end
+ context 'when no block is given' do
+ it 'creates a new Item with the given params and no sub navigation' do
+ allow(SimpleNavigation::Item).to receive(:new)
+ .with(item_container, 'key', 'name', 'url', options)
+ .and_return(item)
+ item_container.item('key', 'name', 'url', options)
+ expect(item_container.items).to include(item)
+ end
+
+ it 'adds the created item to the list of items' do
+ allow(SimpleNavigation::Item).to receive_messages(new: item)
+ item_container.item('key', 'name', 'url', options) {} # rubocop:disable Lint/EmptyBlock
+ expect(item_container.items).to include(item)
+ end
+ end
- it 'adds the created item to the list of items' do
- allow(Item).to receive_messages(new: item)
- item_container.item('key', 'name', 'url', options) {}
- expect(item_container.items).to include(item)
+ describe 'Optional url and optional options' do
+ context 'when item specifed without url or options' do
+ it_behaves_like 'adding the item to the list' do
+ let(:args) { %w[key name] }
end
end
- describe 'Optional url and optional options' do
- context 'when item specifed without url or options' do
- it_behaves_like 'adding the item to the list' do
- let(:args) { ['key', 'name'] }
- end
+ context 'when item is specified with only a url' do
+ it_behaves_like 'adding the item to the list' do
+ let(:args) { %w[key name url] }
end
+ end
- context 'when item is specified with only a url' do
+ context 'when item is specified with only options' do
+ context 'and options do not contain any condition' do
it_behaves_like 'adding the item to the list' do
- let(:args) { ['key', 'name', 'url'] }
+ let(:args) { ['key', 'name', { option: true }] }
end
end
- context 'when item is specified with only options' do
- context 'and options do not contain any condition' do
- it_behaves_like 'adding the item to the list' do
- let(:args) { ['key', 'name', { option: true }] }
- end
- end
-
- context 'and options contains a negative condition' do
- it_behaves_like 'not adding the item to the list' do
- let(:args) { ['key', 'name', nil, { if: ->{ false }, option: true }] }
- end
+ context 'and options contains a negative condition' do
+ it_behaves_like 'not adding the item to the list' do
+ let(:args) { ['key', 'name', nil, { if: -> { false }, option: true }] }
end
+ end
- context 'and options contains a positive condition' do
- it_behaves_like 'adding the item to the list' do
- let(:args) { ['key', 'name', nil, { if: ->{ true }, option: true }] }
- end
+ context 'and options contains a positive condition' do
+ it_behaves_like 'adding the item to the list' do
+ let(:args) { ['key', 'name', nil, { if: -> { true }, option: true }] }
end
end
+ end
- context 'when item is specified with a url and options' do
- context 'and options do not contain any condition' do
- it_behaves_like 'adding the item to the list' do
- let(:args) { ['key', 'name', 'url', { option: true }] }
- end
+ context 'when item is specified with a url and options' do
+ context 'and options do not contain any condition' do
+ it_behaves_like 'adding the item to the list' do
+ let(:args) { ['key', 'name', 'url', { option: true }] }
end
+ end
- context 'and options contains a negative condition' do
- it_behaves_like 'not adding the item to the list' do
- let(:args) { ['key', 'name', 'url', { if: ->{ false }, option: true }] }
- end
+ context 'and options contains a negative condition' do
+ it_behaves_like 'not adding the item to the list' do
+ let(:args) { ['key', 'name', 'url', { if: -> { false }, option: true }] }
end
+ end
- context 'and options contains a positive condition' do
- it_behaves_like 'adding the item to the list' do
- let(:args) { ['key', 'name', 'url', { if: ->{ true }, option: true }] }
- end
+ context 'and options contains a positive condition' do
+ it_behaves_like 'adding the item to the list' do
+ let(:args) { ['key', 'name', 'url', { if: -> { true }, option: true }] }
end
end
+ end
- context 'when a frozen options hash is given' do
- let(:options) do
- { html: { id: 'test' } }.freeze
- end
+ context 'when a frozen options hash is given' do
+ let(:options) do
+ { html: { id: 'test' } }.freeze
+ end
- it 'does not raise an exception' do
- expect{
- item_container.item('key', 'name', 'url', options)
- }.not_to raise_error
- end
+ it 'does not raise an exception' do
+ expect {
+ item_container.item('key', 'name', 'url', options)
+ }.not_to raise_error
end
+ end
- describe "container options" do
- before do
- allow(item_container).to receive_messages(should_add_item?: add_item)
- item_container.item :key, 'name', 'url', options
- end
+ describe 'container options' do
+ before do
+ allow(item_container).to receive_messages(should_add_item?: add_item)
+ item_container.item :key, 'name', 'url', options
+ end
- context 'when the container :id option is specified' do
- let(:options) {{ container: { id: 'c_id' } }}
+ context 'when the container :id option is specified' do
+ let(:options) { { container: { id: 'c_id' } } }
- context 'and the item should be added' do
- let(:add_item) { true }
+ context 'and the item should be added' do
+ let(:add_item) { true }
- it 'changes its dom_id' do
- expect(item_container.dom_id).to eq 'c_id'
- end
+ it 'changes its dom_id' do
+ expect(item_container.dom_id).to eq 'c_id'
end
+ end
- context "and the item shouldn't be added" do
- let(:add_item) { false }
+ context "and the item shouldn't be added" do
+ let(:add_item) { false }
- it "doesn't change its dom_id" do
- expect(item_container.dom_id).to be_nil
- end
+ it "doesn't change its dom_id" do
+ expect(item_container.dom_id).to be_nil
end
end
+ end
- context 'when the container :class option is specified' do
- let(:options) {{ container: { class: 'c_class' } }}
+ context 'when the container :class option is specified' do
+ let(:options) { { container: { class: 'c_class' } } }
- context 'and the item should be added' do
- let(:add_item) { true }
+ context 'and the item should be added' do
+ let(:add_item) { true }
- it 'changes its dom_class' do
- expect(item_container.dom_class).to eq 'c_class'
- end
+ it 'changes its dom_class' do
+ expect(item_container.dom_class).to eq 'c_class'
end
+ end
- context "and the item shouldn't be added" do
- let(:add_item) { false }
+ context "and the item shouldn't be added" do
+ let(:add_item) { false }
- it "doesn't change its dom_class" do
- expect(item_container.dom_class).to be_nil
- end
+ it "doesn't change its dom_class" do
+ expect(item_container.dom_class).to be_nil
end
end
+ end
- context 'when the container :attributes option is specified' do
- let(:options) {{ container: { attributes: { option: true } } }}
+ context 'when the container :attributes option is specified' do
+ let(:options) { { container: { attributes: { option: true } } } }
- context 'and the item should be added' do
- let(:add_item) { true }
+ context 'and the item should be added' do
+ let(:add_item) { true }
- it 'changes its dom_attributes' do
- expect(item_container.dom_attributes).to eq(option: true)
- end
+ it 'changes its dom_attributes' do
+ expect(item_container.dom_attributes).to eq(option: true)
end
+ end
- context "and the item shouldn't be added" do
- let(:add_item) { false }
+ context "and the item shouldn't be added" do
+ let(:add_item) { false }
- it "doesn't change its dom_attributes" do
- expect(item_container.dom_attributes).to eq({})
- end
+ it "doesn't change its dom_attributes" do
+ expect(item_container.dom_attributes).to eq({})
end
end
+ end
- context 'when the container :selected_class option is specified' do
- let(:options) {{ container: { selected_class: 'sel_class' } }}
+ context 'when the container :selected_class option is specified' do
+ let(:options) { { container: { selected_class: 'sel_class' } } }
- context 'and the item should be added' do
- let(:add_item) { true }
+ context 'and the item should be added' do
+ let(:add_item) { true }
- it 'changes its selected_class' do
- expect(item_container.selected_class).to eq 'sel_class'
- end
+ it 'changes its selected_class' do
+ expect(item_container.selected_class).to eq 'sel_class'
end
+ end
- context "and the item shouldn't be added" do
- let(:add_item) { false }
+ context "and the item shouldn't be added" do
+ let(:add_item) { false }
- it "doesn't change its selected_class" do
- expect(item_container.selected_class).to be_nil
- end
+ it "doesn't change its selected_class" do
+ expect(item_container.selected_class).to be_nil
end
end
end
end
+ end
- describe 'Conditions' do
- context 'when an :if option is given' do
- let(:options) {{ if: proc{condition} }}
- let(:condition) { nil }
+ describe 'Conditions' do
+ context 'when an :if option is given' do
+ let(:options) { { if: proc { condition } } }
+ let(:condition) { nil }
- context 'and it evals to true' do
- let(:condition) { true }
+ context 'and it evals to true' do
+ let(:condition) { true }
- it 'creates a new Item' do
- expect(Item).to receive(:new)
- item_container.item('key', 'name', 'url', options)
- end
+ it 'creates a new Item' do
+ expect(SimpleNavigation::Item).to receive(:new)
+ item_container.item('key', 'name', 'url', options)
end
+ end
- context 'and it evals to false' do
- let(:condition) { false }
+ context 'and it evals to false' do
+ let(:condition) { false }
- it "doesn't create a new Item" do
- expect(Item).not_to receive(:new)
- item_container.item('key', 'name', 'url', options)
- end
+ it "doesn't create a new Item" do
+ expect(SimpleNavigation::Item).not_to receive(:new)
+ item_container.item('key', 'name', 'url', options)
end
+ end
- context 'and it is not a proc or a method' do
- it 'raises an error' do
- expect{
- item_container.item('key', 'name', 'url', { if: 'text' })
- }.to raise_error(ArgumentError, ':if or :unless must be procs or lambdas')
- end
+ context 'and it is not a proc or a method' do
+ it 'raises an error' do
+ expect {
+ item_container.item('key', 'name', 'url', { if: 'text' })
+ }.to raise_error(ArgumentError, ':if or :unless must be procs or lambdas')
end
end
+ end
- context 'when an :unless option is given' do
- let(:options) {{ unless: proc{condition} }}
- let(:condition) { nil }
+ context 'when an :unless option is given' do
+ let(:options) { { unless: proc { condition } } }
+ let(:condition) { nil }
- context 'and it evals to false' do
- let(:condition) { false }
+ context 'and it evals to false' do
+ let(:condition) { false }
- it 'creates a new Navigation-Item' do
- expect(Item).to receive(:new)
- item_container.item('key', 'name', 'url', options)
- end
+ it 'creates a new Navigation-Item' do
+ expect(SimpleNavigation::Item).to receive(:new)
+ item_container.item('key', 'name', 'url', options)
end
+ end
- context 'and it evals to true' do
- let(:condition) { true }
+ context 'and it evals to true' do
+ let(:condition) { true }
- it "doesn't create a new Navigation-Item" do
- expect(Item).not_to receive(:new)
- item_container.item('key', 'name', 'url', options)
- end
+ it "doesn't create a new Navigation-Item" do
+ expect(SimpleNavigation::Item).not_to receive(:new)
+ item_container.item('key', 'name', 'url', options)
end
end
end
end
+ end
- describe '#[]' do
- before do
- item_container.item(:first, 'first', 'bla')
- item_container.item(:second, 'second', 'bla')
- item_container.item(:third, 'third', 'bla')
- end
+ describe '#[]' do
+ before do
+ item_container.item(:first, 'first', 'bla')
+ item_container.item(:second, 'second', 'bla')
+ item_container.item(:third, 'third', 'bla')
+ end
- it 'returns the item with the specified navi_key' do
- expect(item_container[:second].name).to eq 'second'
- end
+ it 'returns the item with the specified navi_key' do
+ expect(item_container[:second].name).to eq 'second'
+ end
- context 'when no item exists for the specified navi_key' do
- it 'returns nil' do
- expect(item_container[:invalid]).to be_nil
- end
+ context 'when no item exists for the specified navi_key' do
+ it 'returns nil' do
+ expect(item_container[:invalid]).to be_nil
end
end
+ end
- describe '#render' do
- # TODO
- let(:renderer_instance) { double(:renderer).as_null_object }
- let(:renderer_class) { double(:renderer_class, new: renderer_instance) }
+ describe '#render' do
+ # TODO
+ let(:renderer_instance) { double(:renderer).as_null_object }
+ let(:renderer_class) { double(:renderer_class, new: renderer_instance) }
- context 'when renderer is specified as an option' do
- context 'and is specified as a class' do
- it 'instantiates the passed renderer_class with the options' do
- expect(renderer_class).to receive(:new)
- .with(renderer: renderer_class)
- item_container.render(renderer: renderer_class)
- end
-
- it 'calls render on the renderer and passes self' do
- expect(renderer_instance).to receive(:render).with(item_container)
- item_container.render(renderer: renderer_class)
- end
+ context 'when renderer is specified as an option' do
+ context 'and is specified as a class' do
+ it 'instantiates the passed renderer_class with the options' do
+ expect(renderer_class).to receive(:new)
+ .with({ renderer: renderer_class })
+ item_container.render(renderer: renderer_class)
end
- context 'and is specified as a symbol' do
- before do
- SimpleNavigation.registered_renderers = {
- my_renderer: renderer_class
- }
- end
-
- it "instantiates the passed renderer_class with the options" do
- expect(renderer_class).to receive(:new).with(renderer: :my_renderer)
- item_container.render(renderer: :my_renderer)
- end
-
- it 'calls render on the renderer and passes self' do
- expect(renderer_instance).to receive(:render).with(item_container)
- item_container.render(renderer: :my_renderer)
- end
+ it 'calls render on the renderer and passes self' do
+ expect(renderer_instance).to receive(:render).with(item_container)
+ item_container.render(renderer: renderer_class)
end
end
- context 'when no renderer is specified' do
- let(:options) { Hash.new }
-
- before { allow(item_container).to receive_messages(renderer: renderer_class) }
+ context 'and is specified as a symbol' do
+ before do
+ SimpleNavigation.registered_renderers = {
+ my_renderer: renderer_class
+ }
+ end
- it "instantiates the container's renderer with the options" do
- expect(renderer_class).to receive(:new).with(options)
- item_container.render(options)
+ it 'instantiates the passed renderer_class with the options' do
+ expect(renderer_class).to receive(:new).with({ renderer: :my_renderer })
+ item_container.render(renderer: :my_renderer)
end
it 'calls render on the renderer and passes self' do
expect(renderer_instance).to receive(:render).with(item_container)
- item_container.render(options)
+ item_container.render(renderer: :my_renderer)
end
end
end
- describe '#renderer' do
- context 'when no renderer is set explicitly' do
- it 'returns globally-configured renderer' do
- expect(item_container.renderer).to be Configuration.instance.renderer
- end
- end
+ context 'when no renderer is specified' do
+ let(:options) { {} }
- context 'when a renderer is set explicitly' do
- let(:renderer) { double(:renderer) }
+ before { allow(item_container).to receive_messages(renderer: renderer_class) }
- before { item_container.renderer = renderer }
+ it "instantiates the container's renderer with the options" do
+ expect(renderer_class).to receive(:new).with(options)
+ item_container.render(options)
+ end
- it 'returns the specified renderer' do
- expect(item_container.renderer).to be renderer
- end
+ it 'calls render on the renderer and passes self' do
+ expect(renderer_instance).to receive(:render).with(item_container)
+ item_container.render(options)
end
end
+ end
- describe '#level_for_item' do
- before(:each) do
- item_container.item(:p1, 'p1', 'p1')
- item_container.item(:p2, 'p2', 'p2') do |p2|
- p2.item(:s1, 's1', 's1')
- p2.item(:s2, 's2', 's2') do |s2|
- s2.item(:ss1, 'ss1', 'ss1')
- s2.item(:ss2, 'ss2', 'ss2')
- end
- p2.item(:s3, 's3', 's3')
- end
- item_container.item(:p3, 'p3', 'p3')
+ describe '#renderer' do
+ context 'when no renderer is set explicitly' do
+ it 'returns globally-configured renderer' do
+ expect(item_container.renderer).to be SimpleNavigation::Configuration.instance.renderer
end
+ end
- shared_examples 'returning the level of an item' do |item, level|
- specify{ expect(item_container.level_for_item(item)).to eq level }
- end
+ context 'when a renderer is set explicitly' do
+ let(:renderer) { double(:renderer) }
- it_behaves_like 'returning the level of an item', :p1, 1
- it_behaves_like 'returning the level of an item', :p3, 1
- it_behaves_like 'returning the level of an item', :s1, 2
- it_behaves_like 'returning the level of an item', :ss1, 3
- it_behaves_like 'returning the level of an item', :x, nil
+ before { item_container.renderer = renderer }
+
+ it 'returns the specified renderer' do
+ expect(item_container.renderer).to be renderer
+ end
end
+ end
- describe '#empty?' do
- context 'when there are no items' do
- it 'returns true' do
- item_container.instance_variable_set(:@items, [])
- expect(item_container).to be_empty
+ describe '#level_for_item' do
+ before do
+ item_container.item(:p1, 'p1', 'p1')
+ item_container.item(:p2, 'p2', 'p2') do |p2|
+ p2.item(:s1, 's1', 's1')
+ p2.item(:s2, 's2', 's2') do |s2|
+ s2.item(:ss1, 'ss1', 'ss1')
+ s2.item(:ss2, 'ss2', 'ss2')
end
+ p2.item(:s3, 's3', 's3')
end
+ item_container.item(:p3, 'p3', 'p3')
+ end
- context 'when there are some items' do
- it 'returns false' do
- item_container.instance_variable_set(:@items, [double(:item)])
- expect(item_container).not_to be_empty
- end
+ shared_examples 'returning the level of an item' do |item, level|
+ specify { expect(item_container.level_for_item(item)).to eq level }
+ end
+
+ it_behaves_like 'returning the level of an item', :p1, 1
+ it_behaves_like 'returning the level of an item', :p3, 1
+ it_behaves_like 'returning the level of an item', :s1, 2
+ it_behaves_like 'returning the level of an item', :ss1, 3
+ it_behaves_like 'returning the level of an item', :x, nil
+ end
+
+ describe '#empty?' do
+ context 'when there are no items' do
+ it 'returns true' do
+ item_container.instance_variable_set(:@items, [])
+ expect(item_container).to be_empty
+ end
+ end
+
+ context 'when there are some items' do
+ it 'returns false' do
+ item_container.instance_variable_set(:@items, [double(:item)])
+ expect(item_container).not_to be_empty
end
end
end
diff --git a/spec/simple_navigation/item_spec.rb b/spec/simple_navigation/item_spec.rb
index 96ac5155..aef7de86 100644
--- a/spec/simple_navigation/item_spec.rb
+++ b/spec/simple_navigation/item_spec.rb
@@ -1,473 +1,473 @@
-module SimpleNavigation
- describe Item do
- let!(:item_container) { ItemContainer.new }
+# frozen_string_literal: true
- let(:adapter) { double(:adapter) }
- let(:item_args) { [item_container, :my_key, 'name', url, options] }
- let(:item) { Item.new(*item_args) }
- let(:options) { Hash.new }
- let(:url) { 'url' }
+RSpec.describe SimpleNavigation::Item do
+ let!(:item_container) { SimpleNavigation::ItemContainer.new }
- before { allow(SimpleNavigation).to receive_messages(adapter: adapter) }
+ let(:adapter) { double(:adapter) }
+ let(:item_args) { [item_container, :my_key, 'name', url, options] }
+ let(:item) { described_class.new(*item_args) }
+ let(:options) { {} }
+ let(:url) { 'url' }
- describe '#highlights_on' do
- let(:options) {{ highlights_on: :test }}
+ before { allow(SimpleNavigation).to receive_messages(adapter: adapter) }
- it "returns the item's highlights_on option" do
- expect(item.highlights_on).to eq :test
- end
+ describe '#highlights_on' do
+ let(:options) { { highlights_on: :test } }
+
+ it "returns the item's highlights_on option" do
+ expect(item.highlights_on).to eq :test
end
+ end
- describe '#initialize' do
- context 'when there is a sub_navigation' do
- let(:subnav_container) { double(:subnav_container).as_null_object }
+ describe '#initialize' do
+ context 'when there is a sub_navigation' do
+ let(:subnav_container) { double(:subnav_container).as_null_object }
- shared_examples 'creating sub navigation container' do
- it 'creates a sub navigation container with a level+1' do
- expect(item.sub_navigation.level).to eq 2
- end
+ shared_examples 'creating sub navigation container' do
+ it 'creates a sub navigation container with a level+1' do
+ expect(item.sub_navigation.level).to eq 2
end
+ end
- context 'when a block is given' do
- it_behaves_like 'creating sub navigation container' do
- let(:item) { Item.new(*item_args) {} }
- end
+ context 'when a block is given' do
+ it_behaves_like 'creating sub navigation container' do
+ let(:item) { described_class.new(*item_args) {} } # rubocop:disable Lint/EmptyBlock
+ end
- it 'calls the block' do
- allow(ItemContainer).to receive_messages(new: subnav_container)
+ it 'calls the block' do
+ allow(SimpleNavigation::ItemContainer).to receive_messages(new: subnav_container)
- expect{ |blk|
- Item.new(*item_args, &blk)
- }.to yield_with_args(subnav_container)
- end
+ expect { |blk|
+ described_class.new(*item_args, &blk)
+ }.to yield_with_args(subnav_container)
end
+ end
- context 'when no block is given' do
- context 'and items are given' do
- let(:items) { [] }
- let(:options) {{ items: items }}
+ context 'when no block is given' do
+ context 'and items are given' do
+ let(:items) { [] }
+ let(:options) { { items: items } }
- it_behaves_like 'creating sub navigation container'
+ it_behaves_like 'creating sub navigation container'
- it "sets the items on the subnav_container" do
- expect(item.sub_navigation.items).to eq items
- end
+ it 'sets the items on the subnav_container' do
+ expect(item.sub_navigation.items).to eq items
end
+ end
- context 'and no items are given' do
- it "doesn't create a new ItemContainer" do
- item = Item.new(*item_args)
- expect(item.sub_navigation).to be_nil
- end
+ context 'and no items are given' do
+ it "doesn't create a new ItemContainer" do
+ item = described_class.new(*item_args)
+ expect(item.sub_navigation).to be_nil
end
end
end
+ end
- context 'when a :method option is given' do
- let(:options) {{ method: :delete }}
+ context 'when a :method option is given' do
+ let(:options) { { method: :delete } }
- it "sets the item's method" do
- expect(item.method).to eq :delete
- end
+ it "sets the item's method" do
+ expect(item.method).to eq :delete
end
+ end
- context 'when no :method option is given' do
- it "sets the item's method to nil" do
- expect(item.method).to be_nil
- end
+ context 'when no :method option is given' do
+ it "sets the item's method to nil" do
+ expect(item.method).to be_nil
end
+ end
- context 'when an :highlights_on option is given' do
- let(:highlights_on) { double(:highlights_on) }
- let(:options) {{ highlights_on: highlights_on }}
+ context 'when an :highlights_on option is given' do
+ let(:highlights_on) { double(:highlights_on) }
+ let(:options) { { highlights_on: highlights_on } }
- it "sets the item's highlights_on" do
- expect(item.highlights_on).to eq highlights_on
- end
+ it "sets the item's highlights_on" do
+ expect(item.highlights_on).to eq highlights_on
end
+ end
- context 'when no :highlights_on option is given' do
- it "sets the item's highlights_on to nil" do
- expect(item.highlights_on).to be_nil
- end
+ context 'when no :highlights_on option is given' do
+ it "sets the item's highlights_on to nil" do
+ expect(item.highlights_on).to be_nil
end
+ end
- context 'when a url is given' do
- context 'and it is a string' do
- it "sets the item's url accordingly" do
- expect(item.url).to eq 'url'
- end
+ context 'when a url is given' do
+ context 'and it is a string' do
+ it "sets the item's url accordingly" do
+ expect(item.url).to eq 'url'
end
+ end
- context 'and it is a proc' do
- let(:url) { proc{ "my_" + "url" } }
+ context 'and it is a proc' do
+ let(:url) { proc { 'my_url' } }
- it "sets the item's url accordingly" do
- expect(item.url).to eq 'my_url'
- end
+ it "sets the item's url accordingly" do
+ expect(item.url).to eq 'my_url'
end
+ end
- context 'and it is nil' do
- let(:url) { nil }
+ context 'and it is nil' do
+ let(:url) { nil }
- it "sets the item's url accordingly" do
- expect(item.url).to be_nil
- end
+ it "sets the item's url accordingly" do
+ expect(item.url).to be_nil
end
end
+ end
- context 'when no url nor options is specified' do
- let(:item_args) { [item_container, :my_key, 'name'] }
+ context 'when no url nor options is specified' do
+ let(:item_args) { [item_container, :my_key, 'name'] }
- it "sets the item's url to nil" do
- expect(item.url).to be_nil
- end
+ it "sets the item's url to nil" do
+ expect(item.url).to be_nil
end
+ end
- context 'when only a url is given' do
- let(:item_args) { [item_container, :my_key, 'name', 'url'] }
+ context 'when only a url is given' do
+ let(:item_args) { [item_container, :my_key, 'name', 'url'] }
- it "set the item's url accordingly" do
- expect(item.url).to eq 'url'
- end
+ it "set the item's url accordingly" do
+ expect(item.url).to eq 'url'
end
+ end
- context 'when url and options are given' do
- let(:options) {{ html: { option: true } }}
+ context 'when url and options are given' do
+ let(:options) { { html: { option: true } } }
- before { allow(adapter).to receive_messages(current_page?: false) }
+ before { allow(adapter).to receive_messages(current_page?: false) }
- it "set the item's url accordingly" do
- expect(item.url).to eq 'url'
- end
+ it "set the item's url accordingly" do
+ expect(item.url).to eq 'url'
+ end
- it "sets the item's html_options accordingly" do
- allow(item).to \
- receive_messages(selected_by_subnav?: false,
- selected_by_condition?: false)
- expect(item.html_options).to include(option: true)
- end
+ it "sets the item's html_options accordingly" do
+ allow(item).to \
+ receive_messages(selected_by_subnav?: false,
+ selected_by_condition?: false)
+ expect(item.html_options).to include(option: true)
end
end
+ end
- describe '#link_html_options' do
- let(:options) {{ link_html: :test }}
+ describe '#link_html_options' do
+ let(:options) { { link_html: :test } }
- it "returns the item's link_html option" do
- expect(item.link_html_options).to eq :test
- end
+ it "returns the item's link_html option" do
+ expect(item.link_html_options).to eq :test
end
+ end
- describe '#method' do
- let(:options) {{ method: :test }}
+ describe '#method' do
+ let(:options) { { method: :test } }
- it "returns the item's method option" do
- expect(item.method).to eq :test
- end
+ it "returns the item's method option" do
+ expect(item.method).to eq :test
end
+ end
- describe '#name' do
- before do
- allow(SimpleNavigation.config).to \
- receive_messages(name_generator: proc{ |name| "#{name}" })
- end
+ describe '#name' do
+ before do
+ allow(SimpleNavigation.config).to \
+ receive_messages(name_generator: proc { |name| "#{name}" })
+ end
- context 'when no option is given' do
- context 'and the name_generator uses only the name' do
- it 'uses the default name_generator' do
- expect(item.name).to eq 'name'
- end
+ context 'when no option is given' do
+ context 'and the name_generator uses only the name' do
+ it 'uses the default name_generator' do
+ expect(item.name).to eq 'name'
end
+ end
- context 'and the name_generator uses only the item itself' do
- before do
- allow(SimpleNavigation.config).to \
- receive_messages(name_generator: proc{ |name, item| "#{item.key}" })
- end
+ context 'and the name_generator uses only the item itself' do
+ before do
+ allow(SimpleNavigation.config).to \
+ receive_messages(name_generator: proc { |_name, item| "#{item.key}" })
+ end
- it 'uses the default name_generator' do
- expect(item.name).to eq 'my_key'
- end
+ it 'uses the default name_generator' do
+ expect(item.name).to eq 'my_key'
end
end
+ end
- context 'when the :apply_generator is false' do
- it "returns the item's name" do
- expect(item.name(apply_generator: false)).to eq 'name'
- end
+ context 'when the :apply_generator is false' do
+ it "returns the item's name" do
+ expect(item.name(apply_generator: false)).to eq 'name'
end
+ end
- context 'when a block is given' do
- let(:item_args) { [item_container, :my_key, -> { 'Name in block' }, url, options] }
+ context 'when a block is given' do
+ let(:item_args) { [item_container, :my_key, -> { 'Name in block' }, url, options] }
- it "returns the item's name that is defined in the block" do
- expect(item.name).to include 'Name in block'
- end
+ it "returns the item's name that is defined in the block" do
+ expect(item.name).to include 'Name in block'
end
end
+ end
- describe '#selected?' do
- context 'when the item has no :highlights_on option' do
- before { allow(SimpleNavigation).to receive_messages(config: config) }
+ describe '#selected?' do
+ context 'when the item has no :highlights_on option' do
+ before { allow(SimpleNavigation).to receive_messages(config: config) }
- context 'and auto highlighting is off' do
- let(:config) { double(:config, auto_highlight: false) }
+ context 'and auto highlighting is off' do
+ let(:config) { double(:config, auto_highlight: false) }
- it 'returns false' do
- expect(item.selected?).to be false
+ it 'returns false' do
+ expect(item.selected?).to be false
+ end
+ end
+
+ context 'and auto highlighting is on' do
+ let(:config) { double(:config, ignore_query_params_on_auto_highlight: true, ignore_anchors_on_auto_highlight: true, auto_highlight: true) }
+
+ context "and the current url matches the item's url" do
+ before { allow(adapter).to receive_messages(current_page?: true) }
+
+ it 'returns true' do
+ expect(item.selected?).to be true
end
end
- context 'and auto highlighting is on' do
- let(:config) { double(:config, ignore_query_params_on_auto_highlight: true, ignore_anchors_on_auto_highlight: true, auto_highlight: true) }
+ context "and the current url does not match the item's url" do
+ let(:config) do
+ double(:config, auto_highlight: false, highlight_on_subpath: false)
+ end
- context "and the current url matches the item's url" do
- before { allow(adapter).to receive_messages(current_page?: true) }
+ before { allow(adapter).to receive_messages(current_page?: false) }
- it 'returns true' do
- expect(item.selected?).to be true
- end
+ it 'returns false' do
+ expect(item.selected?).to be false
end
+ end
- context "and the current url does not match the item's url" do
- let(:config) do
- double(:config, auto_highlight: false, highlight_on_subpath: false)
- end
+ context 'and highlights_on_subpath is on' do
+ let(:config) do
+ double(:config, auto_highlight: true, highlight_on_subpath: true, ignore_query_params_on_auto_highlight: true, ignore_anchors_on_auto_highlight: true)
+ end
- before { allow(adapter).to receive_messages(current_page?: false) }
+ context 'but item has no url' do
+ let(:url) { nil }
it 'returns false' do
expect(item.selected?).to be false
end
end
- context 'and highlights_on_subpath is on' do
- let(:config) do
- double(:config, auto_highlight: true, highlight_on_subpath: true, ignore_query_params_on_auto_highlight: true, ignore_anchors_on_auto_highlight: true)
+ context "and the current url is a sub path of the item's url" do
+ before do
+ allow(adapter).to \
+ receive_messages(current_page?: false, request_uri: 'url/test')
end
- context "but item has no url" do
- let(:url) { nil }
-
- it 'returns false' do
- expect(item.selected?).to be false
- end
+ it 'returns true' do
+ expect(item.selected?).to be true
end
+ end
- context "and the current url is a sub path of the item's url" do
- before do
- allow(adapter).to \
- receive_messages(current_page?: false, request_uri: 'url/test')
- end
-
- it 'returns true' do
- expect(item.selected?).to be true
- end
+ context "and the current url is not a sub path of the item's url" do
+ before do
+ allow(adapter).to \
+ receive_messages(current_page?: false, request_uri: 'other/test')
end
- context "and the current url is not a sub path of the item's url" do
- before do
- allow(adapter).to \
- receive_messages(current_page?: false, request_uri: 'other/test')
- end
-
- it 'returns false' do
- expect(item.selected?).to be false
- end
+ it 'returns false' do
+ expect(item.selected?).to be false
end
end
end
end
+ end
- context 'when the item has a :highlights_on option' do
- context 'and it is a regular expression' do
- before { allow(adapter).to receive_messages(request_uri: '/test') }
+ context 'when the item has a :highlights_on option' do
+ context 'and it is a regular expression' do
+ before { allow(adapter).to receive_messages(request_uri: '/test') }
- context 'and the current url matches the expression' do
- let(:options) {{ highlights_on: /test/ }}
+ context 'and the current url matches the expression' do
+ let(:options) { { highlights_on: /test/ } }
- it 'returns true' do
- expect(item.selected?).to be true
- end
+ it 'returns true' do
+ expect(item.selected?).to be true
end
+ end
- context 'and the current url does not match the expression' do
- let(:options) {{ highlights_on: /other/ }}
+ context 'and the current url does not match the expression' do
+ let(:options) { { highlights_on: /other/ } }
- it 'returns false' do
- expect(item.selected?).to be false
- end
+ it 'returns false' do
+ expect(item.selected?).to be false
end
end
+ end
- context 'and it is a callable object' do
- context 'and the call returns true' do
- let(:options) {{ highlights_on: -> { true } }}
+ context 'and it is a callable object' do
+ context 'and the call returns true' do
+ let(:options) { { highlights_on: -> { true } } }
- it 'returns true' do
- expect(item.selected?).to be true
- end
+ it 'returns true' do
+ expect(item.selected?).to be true
end
+ end
- context 'and the call returns false' do
- let(:options) {{ highlights_on: -> { false } }}
+ context 'and the call returns false' do
+ let(:options) { { highlights_on: -> { false } } }
- it 'returns false' do
- expect(item.selected?).to be false
- end
+ it 'returns false' do
+ expect(item.selected?).to be false
end
end
+ end
- context 'and it is the :subpath symbol' do
- let(:options) {{ highlights_on: :subpath }}
+ context 'and it is the :subpath symbol' do
+ let(:options) { { highlights_on: :subpath } }
- context "and the current url is a sub path of the item's url" do
- before do
- allow(adapter).to receive_messages(request_uri: 'url/test')
- end
+ context "and the current url is a sub path of the item's url" do
+ before do
+ allow(adapter).to receive_messages(request_uri: 'url/test')
+ end
- it 'returns true' do
- expect(item.selected?).to be true
- end
+ it 'returns true' do
+ expect(item.selected?).to be true
end
+ end
- context "and the current url is not a sub path of the item's url" do
- before do
- allow(adapter).to receive_messages(request_uri: 'other/test')
- end
+ context "and the current url is not a sub path of the item's url" do
+ before do
+ allow(adapter).to receive_messages(request_uri: 'other/test')
+ end
- it 'returns false' do
- expect(item.selected?).to be false
- end
+ it 'returns false' do
+ expect(item.selected?).to be false
end
end
+ end
- context 'and it is non usable' do
- let(:options) {{ highlights_on: :hello }}
+ context 'and it is non usable' do
+ let(:options) { { highlights_on: :hello } }
- it 'raises an exception' do
- expect{ item.selected? }.to raise_error(ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath')
- end
+ it 'raises an exception' do
+ expect { item.selected? }.to raise_error(ArgumentError, ':highlights_on must be a Regexp, Proc or :subpath')
end
end
end
+ end
- describe '#selected_class' do
- context 'when the item is selected' do
- before { allow(item).to receive_messages(selected?: true) }
+ describe '#selected_class' do
+ context 'when the item is selected' do
+ before { allow(item).to receive_messages(selected?: true) }
- it 'returns the default selected_class' do
- expect(item.selected_class).to eq 'selected'
- end
+ it 'returns the default selected_class' do
+ expect(item.selected_class).to eq 'selected'
+ end
- context 'and selected_class is defined in the context' do
- before { allow(item_container).to receive_messages(selected_class: 'defined') }
+ context 'and selected_class is defined in the context' do
+ before { allow(item_container).to receive_messages(selected_class: 'defined') }
- it "returns the context's selected_class" do
- expect(item.selected_class).to eq 'defined'
- end
+ it "returns the context's selected_class" do
+ expect(item.selected_class).to eq 'defined'
end
end
+ end
- context 'when the item is not selected' do
- before { allow(item).to receive_messages(selected?: false) }
+ context 'when the item is not selected' do
+ before { allow(item).to receive_messages(selected?: false) }
- it 'returns nil' do
- expect(item.selected_class).to be_nil
- end
+ it 'returns nil' do
+ expect(item.selected_class).to be_nil
end
end
+ end
- describe ':html_options argument' do
- let(:selected_classes) { 'selected simple-navigation-active-leaf' }
+ describe ':html_options argument' do
+ let(:selected_classes) { 'selected simple-navigation-active-leaf' }
- context 'when the :class option is given' do
- let(:options) {{ html: { class: 'my_class' } }}
+ context 'when the :class option is given' do
+ let(:options) { { html: { class: 'my_class' } } }
- context 'and the item is selected' do
- before { allow(item).to receive_messages(selected?: true, selected_by_condition?: true) }
+ context 'and the item is selected' do
+ before { allow(item).to receive_messages(selected?: true, selected_by_condition?: true) }
- it "adds the specified class to the item's html classes" do
- expect(item.html_options[:class]).to include('my_class')
- end
+ it "adds the specified class to the item's html classes" do
+ expect(item.html_options[:class]).to include('my_class')
+ end
- it "doesn't replace the default html classes of a selected item" do
- expect(item.html_options[:class]).to include(selected_classes)
- end
+ it "doesn't replace the default html classes of a selected item" do
+ expect(item.html_options[:class]).to include(selected_classes)
end
+ end
- context "and the item isn't selected" do
- before { allow(item).to receive_messages(selected?: false, selected_by_condition?: false) }
+ context "and the item isn't selected" do
+ before { allow(item).to receive_messages(selected?: false, selected_by_condition?: false) }
- it "sets the specified class as the item's html classes" do
- expect(item.html_options[:class]).to include('my_class')
- end
+ it "sets the specified class as the item's html classes" do
+ expect(item.html_options[:class]).to include('my_class')
end
end
+ end
- context "when the :class option isn't given" do
- context 'and the item is selected' do
- before { allow(item).to receive_messages(selected?: true, selected_by_condition?: true) }
+ context "when the :class option isn't given" do
+ context 'and the item is selected' do
+ before { allow(item).to receive_messages(selected?: true, selected_by_condition?: true) }
- it "sets the default html classes of a selected item" do
- expect(item.html_options[:class]).to include(selected_classes)
- end
+ it 'sets the default html classes of a selected item' do
+ expect(item.html_options[:class]).to include(selected_classes)
end
+ end
- context "and the item isn't selected" do
- before { allow(item).to receive_messages(selected?: false, selected_by_condition?: false) }
+ context "and the item isn't selected" do
+ before { allow(item).to receive_messages(selected?: false, selected_by_condition?: false) }
- it "doesn't set any html class on the item" do
- expect(item.html_options[:class]).to be_blank
- end
+ it "doesn't set any html class on the item" do
+ expect(item.html_options[:class]).to be_blank
end
end
+ end
- shared_examples 'generating id' do |id|
- it "sets the item's html id to the specified id" do
- expect(item.html_options[:id]).to eq id
- end
+ shared_examples 'generating id' do |id|
+ it "sets the item's html id to the specified id" do
+ expect(item.html_options[:id]).to eq id
end
+ end
- describe 'when the :id option is given' do
- let(:options) {{ html: { id: 'my_id' } }}
+ describe 'when the :id option is given' do
+ let(:options) { { html: { id: 'my_id' } } }
- before do
- allow(SimpleNavigation.config).to receive_messages(autogenerate_item_ids: generate_ids)
- allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
- end
+ before do
+ allow(SimpleNavigation.config).to receive_messages(autogenerate_item_ids: generate_ids)
+ allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
+ end
- context 'and :autogenerate_item_ids is true' do
- let(:generate_ids) { true }
+ context 'and :autogenerate_item_ids is true' do
+ let(:generate_ids) { true }
- it_behaves_like 'generating id', 'my_id'
- end
+ it_behaves_like 'generating id', 'my_id'
+ end
- context 'and :autogenerate_item_ids is false' do
- let(:generate_ids) { false }
+ context 'and :autogenerate_item_ids is false' do
+ let(:generate_ids) { false }
- it_behaves_like 'generating id', 'my_id'
- end
+ it_behaves_like 'generating id', 'my_id'
end
+ end
- context "when the :id option isn't given" do
- before do
- allow(SimpleNavigation.config).to receive_messages(autogenerate_item_ids: generate_ids)
- allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
- end
+ context "when the :id option isn't given" do
+ before do
+ allow(SimpleNavigation.config).to receive_messages(autogenerate_item_ids: generate_ids)
+ allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
+ end
- context 'and :autogenerate_item_ids is true' do
- let(:generate_ids) { true }
+ context 'and :autogenerate_item_ids is true' do
+ let(:generate_ids) { true }
- it_behaves_like 'generating id', 'my_key'
- end
+ it_behaves_like 'generating id', 'my_key'
+ end
- context 'and :autogenerate_item_ids is false' do
- let(:generate_ids) { false }
+ context 'and :autogenerate_item_ids is false' do
+ let(:generate_ids) { false }
- it "doesn't set any html id on the item" do
- expect(item.html_options[:id]).to be_blank
- end
+ it "doesn't set any html id on the item" do
+ expect(item.html_options[:id]).to be_blank
end
end
end
diff --git a/spec/simple_navigation/items_provider_spec.rb b/spec/simple_navigation/items_provider_spec.rb
index fd5022e5..a3623a2a 100644
--- a/spec/simple_navigation/items_provider_spec.rb
+++ b/spec/simple_navigation/items_provider_spec.rb
@@ -1,43 +1,43 @@
-module SimpleNavigation
- describe ItemsProvider do
- let(:items_provider) { ItemsProvider.new(provider) }
+# frozen_string_literal: true
- describe '#items' do
- let(:items) { double(:items) }
+RSpec.describe SimpleNavigation::ItemsProvider do
+ let(:items_provider) { described_class.new(provider) }
- context 'when provider is a symbol' do
- let(:context) { double(:context, provider_method: items) }
- let(:provider) { :provider_method }
+ describe '#items' do
+ let(:items) { double(:items) }
- before { allow(SimpleNavigation).to receive_messages(context_for_eval: context) }
+ context 'when provider is a symbol' do
+ let(:context) { double(:context, provider_method: items) }
+ let(:provider) { :provider_method }
- it 'retrieves the items from the evaluation context' do
- expect(items_provider.items).to eq items
- end
+ before { allow(SimpleNavigation).to receive_messages(context_for_eval: context) }
+
+ it 'retrieves the items from the evaluation context' do
+ expect(items_provider.items).to eq items
end
+ end
- context 'when provider responds to :items' do
- let(:provider) { double(:provider, items: items) }
+ context 'when provider responds to :items' do
+ let(:provider) { double(:provider, items: items) }
- it 'retrieves the items from the provider object' do
- expect(items_provider.items).to eq items
- end
+ it 'retrieves the items from the provider object' do
+ expect(items_provider.items).to eq items
end
+ end
- context 'provider is a collection' do
- let(:provider) { [] }
+ context 'provider is a collection' do
+ let(:provider) { [] }
- it 'retrieves the items by returning the provider' do
- expect(items_provider.items).to eq provider
- end
+ it 'retrieves the items by returning the provider' do
+ expect(items_provider.items).to eq provider
end
+ end
- context 'when provider is something else' do
- let(:provider) { double(:provider) }
+ context 'when provider is something else' do
+ let(:provider) { double(:provider) }
- it 'raises an exception' do
- expect{ items_provider.items }.to raise_error(RuntimeError, /items_provider either must be a symbol .*, an object .* or an enumerable/)
- end
+ it 'raises an exception' do
+ expect { items_provider.items }.to raise_error(RuntimeError, /items_provider either must be a symbol .*, an object .* or an enumerable/)
end
end
end
diff --git a/spec/simple_navigation/renderer/base_spec.rb b/spec/simple_navigation/renderer/base_spec.rb
index 704a17cd..f5d0c802 100644
--- a/spec/simple_navigation/renderer/base_spec.rb
+++ b/spec/simple_navigation/renderer/base_spec.rb
@@ -1,238 +1,236 @@
-module SimpleNavigation
- module Renderer
- describe Base do
- subject(:base) { Base.new(options) }
+# frozen_string_literal: true
- let(:adapter) { double(:adapter) }
- let(:options) { Hash.new }
+RSpec.describe SimpleNavigation::Renderer::Base do
+ subject(:base) { described_class.new(options) }
- before { allow(SimpleNavigation).to receive_messages(adapter: adapter) }
+ let(:adapter) { double(:adapter) }
+ let(:options) { {} }
- it 'delegates the :link_to method to adapter' do
- allow(adapter).to receive_messages(link_to: 'link_to')
- expect(base.link_to).to eq 'link_to'
- end
-
- it 'delegates the :content_tag method to adapter' do
- allow(adapter).to receive_messages(content_tag: 'content_tag')
- expect(base.content_tag).to eq 'content_tag'
- end
+ before { allow(SimpleNavigation).to receive_messages(adapter: adapter) }
- describe '#initialize' do
- it "sets the renderer adapter to the SimpleNavigation one" do
- expect(base.adapter).to be adapter
- end
- end
+ it 'delegates the :link_to method to adapter' do
+ allow(adapter).to receive_messages(link_to: 'link_to')
+ expect(base.link_to).to eq 'link_to'
+ end
- describe '#options' do
- it "returns the renderer's options" do
- expect(base.options).to be options
- end
- end
+ it 'delegates the :content_tag method to adapter' do
+ allow(adapter).to receive_messages(content_tag: 'content_tag')
+ expect(base.content_tag).to eq 'content_tag'
+ end
- describe '#render' do
- it "raise an exception to indicate it's a subclass responsibility" do
- expect{ base.render(:container) }.to raise_error(NotImplementedError, 'subclass responsibility')
- end
- end
+ describe '#initialize' do
+ it 'sets the renderer adapter to the SimpleNavigation one' do
+ expect(base.adapter).to be adapter
+ end
+ end
- describe '#expand_all?' do
- context 'when :options is set' do
- context 'and the :expand_all option is true' do
- let(:options) {{ expand_all: true }}
+ describe '#options' do
+ it "returns the renderer's options" do
+ expect(base.options).to be options
+ end
+ end
- it 'returns true' do
- expect(base.expand_all?).to be true
- end
- end
+ describe '#render' do
+ it "raise an exception to indicate it's a subclass responsibility" do
+ expect { base.render(:container) }.to raise_error(NotImplementedError, 'subclass responsibility')
+ end
+ end
- context 'and the :expand_all option is false' do
- let(:options) {{ expand_all: false }}
+ describe '#expand_all?' do
+ context 'when :options is set' do
+ context 'and the :expand_all option is true' do
+ let(:options) { { expand_all: true } }
- it 'returns false' do
- expect(base.expand_all?).to be false
- end
- end
+ it 'returns true' do
+ expect(base.expand_all?).to be true
end
+ end
- context "when :options isn't set" do
- let(:options) { Hash.new }
+ context 'and the :expand_all option is false' do
+ let(:options) { { expand_all: false } }
- it 'returns false' do
- expect(base.expand_all?).to be false
- end
+ it 'returns false' do
+ expect(base.expand_all?).to be false
end
end
+ end
- describe '#skip_if_empty?' do
- context 'when :options is set' do
- context 'and the :skip_if_empty option is true' do
- let(:options) {{ skip_if_empty: true }}
+ context "when :options isn't set" do
+ let(:options) { {} }
- it 'returns true' do
- expect(base.skip_if_empty?).to be true
- end
- end
+ it 'returns false' do
+ expect(base.expand_all?).to be false
+ end
+ end
+ end
- context 'and the :skip_if_empty option is false' do
- let(:options) {{ skip_if_empty: false }}
+ describe '#skip_if_empty?' do
+ context 'when :options is set' do
+ context 'and the :skip_if_empty option is true' do
+ let(:options) { { skip_if_empty: true } }
- it 'returns true' do
- expect(base.skip_if_empty?).to be false
- end
- end
+ it 'returns true' do
+ expect(base.skip_if_empty?).to be true
end
+ end
- context "when :options isn't set" do
- let(:options) { Hash.new }
+ context 'and the :skip_if_empty option is false' do
+ let(:options) { { skip_if_empty: false } }
- it 'returns true' do
- expect(base.skip_if_empty?).to be false
- end
+ it 'returns true' do
+ expect(base.skip_if_empty?).to be false
end
end
+ end
- describe '#level' do
- context 'and the :level option is set' do
- let(:options) {{ level: 1 }}
+ context "when :options isn't set" do
+ let(:options) { {} }
- it 'returns the specified level' do
- expect(base.level).to eq 1
- end
- end
+ it 'returns true' do
+ expect(base.skip_if_empty?).to be false
+ end
+ end
+ end
- context "and the :level option isn't set" do
- let(:options) { Hash.new }
+ describe '#level' do
+ context 'and the :level option is set' do
+ let(:options) { { level: 1 } }
- it 'returns :all' do
- expect(base.level).to eq :all
- end
- end
+ it 'returns the specified level' do
+ expect(base.level).to eq 1
end
+ end
- describe '#consider_sub_navigation?' do
- let(:item) { double(:item) }
+ context "and the :level option isn't set" do
+ let(:options) { {} }
- before { allow(item).to receive_messages(sub_navigation: sub_navigation) }
+ it 'returns :all' do
+ expect(base.level).to eq :all
+ end
+ end
+ end
- context 'when the item has no sub navigation' do
- let(:sub_navigation) { nil }
+ describe '#consider_sub_navigation?' do
+ let(:item) { double(:item) }
- it 'returns false' do
- expect(base.send(:consider_sub_navigation?, item)).to be false
- end
- end
+ before { allow(item).to receive_messages(sub_navigation: sub_navigation) }
- context 'when the item has sub navigation' do
- let(:sub_navigation) { double(:sub_navigation) }
+ context 'when the item has no sub navigation' do
+ let(:sub_navigation) { nil }
- context 'and the renderer has an unknown level' do
- before { allow(base).to receive_messages(level: 'unknown') }
+ it 'returns false' do
+ expect(base.send(:consider_sub_navigation?, item)).to be false
+ end
+ end
- it 'returns false' do
- expect(base.send(:consider_sub_navigation?, item)).to be false
- end
- end
+ context 'when the item has sub navigation' do
+ let(:sub_navigation) { double(:sub_navigation) }
- context 'and the renderer has a level set to :all' do
- before { allow(base).to receive_messages(level: :all) }
+ context 'and the renderer has an unknown level' do
+ before { allow(base).to receive_messages(level: 'unknown') }
- it 'returns false' do
- expect(base.send(:consider_sub_navigation?, item)).to be true
- end
- end
+ it 'returns false' do
+ expect(base.send(:consider_sub_navigation?, item)).to be false
+ end
+ end
- context "when the renderer's level is a number" do
- before { allow(base).to receive_messages(level: 2) }
+ context 'and the renderer has a level set to :all' do
+ before { allow(base).to receive_messages(level: :all) }
- it 'returns false' do
- expect(base.send(:consider_sub_navigation?, item)).to be false
- end
- end
+ it 'returns false' do
+ expect(base.send(:consider_sub_navigation?, item)).to be true
+ end
+ end
- context "when the renderer's level is a Range" do
- before { allow(base).to receive_messages(level: 2..3) }
+ context "when the renderer's level is a number" do
+ before { allow(base).to receive_messages(level: 2) }
- context "and sub navigation's level is greater than range.max" do
- before { allow(sub_navigation).to receive_messages(level: 4) }
+ it 'returns false' do
+ expect(base.send(:consider_sub_navigation?, item)).to be false
+ end
+ end
- it 'returns false' do
- expect(base.send(:consider_sub_navigation?, item)).to be false
- end
- end
+ context "when the renderer's level is a Range" do
+ before { allow(base).to receive_messages(level: 2..3) }
- context "and sub navigation's level is equal to range.max" do
- before { allow(sub_navigation).to receive_messages(level: 3) }
+ context "and sub navigation's level is greater than range.max" do
+ before { allow(sub_navigation).to receive_messages(level: 4) }
- it 'returns true' do
- expect(base.send(:consider_sub_navigation?, item)).to be true
- end
- end
+ it 'returns false' do
+ expect(base.send(:consider_sub_navigation?, item)).to be false
+ end
+ end
- context "and sub navigation's level is equal to range.min" do
- before { allow(sub_navigation).to receive_messages(level: 2) }
+ context "and sub navigation's level is equal to range.max" do
+ before { allow(sub_navigation).to receive_messages(level: 3) }
- it 'returns true' do
- expect(base.send(:consider_sub_navigation?, item)).to be true
- end
- end
+ it 'returns true' do
+ expect(base.send(:consider_sub_navigation?, item)).to be true
end
end
- end
- describe '#include_sub_navigation?' do
- let(:item) { double(:item) }
+ context "and sub navigation's level is equal to range.min" do
+ before { allow(sub_navigation).to receive_messages(level: 2) }
- context 'when consider_sub_navigation? is true' do
- before { allow(base).to receive_messages(consider_sub_navigation?: true) }
+ it 'returns true' do
+ expect(base.send(:consider_sub_navigation?, item)).to be true
+ end
+ end
+ end
+ end
+ end
- context 'and expand_sub_navigation? is true' do
- before { allow(base).to receive_messages(expand_sub_navigation?: true) }
+ describe '#include_sub_navigation?' do
+ let(:item) { double(:item) }
- it 'returns true' do
- expect(base.include_sub_navigation?(item)).to be true
- end
- end
+ context 'when consider_sub_navigation? is true' do
+ before { allow(base).to receive_messages(consider_sub_navigation?: true) }
- context 'and expand_sub_navigation? is false' do
- before { allow(base).to receive_messages(expand_sub_navigation?: false) }
+ context 'and expand_sub_navigation? is true' do
+ before { allow(base).to receive_messages(expand_sub_navigation?: true) }
- it 'returns false' do
- expect(base.include_sub_navigation?(item)).to be false
- end
- end
+ it 'returns true' do
+ expect(base.include_sub_navigation?(item)).to be true
end
+ end
- context 'consider_sub_navigation? is false' do
- before { allow(base).to receive_messages(consider_sub_navigation?: false) }
+ context 'and expand_sub_navigation? is false' do
+ before { allow(base).to receive_messages(expand_sub_navigation?: false) }
- context 'and expand_sub_navigation? is true' do
- before { allow(base).to receive_messages(expand_sub_navigation?: true) }
+ it 'returns false' do
+ expect(base.include_sub_navigation?(item)).to be false
+ end
+ end
+ end
- it 'returns false' do
- expect(base.include_sub_navigation?(item)).to be false
- end
- end
+ context 'consider_sub_navigation? is false' do
+ before { allow(base).to receive_messages(consider_sub_navigation?: false) }
- context 'and expand_sub_navigation? is false' do
- before { allow(base).to receive_messages(expand_sub_navigation?: false) }
+ context 'and expand_sub_navigation? is true' do
+ before { allow(base).to receive_messages(expand_sub_navigation?: true) }
- it 'returns false' do
- expect(base.include_sub_navigation?(item)).to be false
- end
- end
+ it 'returns false' do
+ expect(base.include_sub_navigation?(item)).to be false
end
end
- describe '#render_sub_navigation_for' do
- let(:item) { double(:item, sub_navigation: sub_navigation) }
- let(:sub_navigation) { double(:sub_navigation) }
+ context 'and expand_sub_navigation? is false' do
+ before { allow(base).to receive_messages(expand_sub_navigation?: false) }
- it 'renders the sub navigation passing it the options' do
- expect(sub_navigation).to receive(:render).with(options)
- base.render_sub_navigation_for(item)
+ it 'returns false' do
+ expect(base.include_sub_navigation?(item)).to be false
end
end
end
end
+
+ describe '#render_sub_navigation_for' do
+ let(:item) { double(:item, sub_navigation: sub_navigation) }
+ let(:sub_navigation) { double(:sub_navigation) }
+
+ it 'renders the sub navigation passing it the options' do
+ expect(sub_navigation).to receive(:render).with(options)
+ base.render_sub_navigation_for(item)
+ end
+ end
end
diff --git a/spec/simple_navigation/renderer/breadcrumbs_spec.rb b/spec/simple_navigation/renderer/breadcrumbs_spec.rb
index 4fa5c2c1..33cd1e8a 100644
--- a/spec/simple_navigation/renderer/breadcrumbs_spec.rb
+++ b/spec/simple_navigation/renderer/breadcrumbs_spec.rb
@@ -1,115 +1,113 @@
-module SimpleNavigation
- module Renderer
- describe Breadcrumbs do
- let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
+# frozen_string_literal: true
- let(:item) { nil }
- let(:options) {{ level: :all }}
- let(:output) { renderer.render(navigation) }
- let(:renderer) { Breadcrumbs.new(options) }
+RSpec.describe SimpleNavigation::Renderer::Breadcrumbs do
+ let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
- before { select_an_item(navigation[item]) if item }
+ let(:item) { nil }
+ let(:options) { { level: :all } }
+ let(:output) { renderer.render(navigation) }
+ let(:renderer) { described_class.new(options) }
- describe '#render' do
- it "renders a 'div' tag for the navigation" do
- expect(output).to have_css('div')
- end
+ before { select_an_item(navigation[item]) if item }
- it "sets the right html id on the rendered 'div' tag" do
- expect(output).to have_css('div#nav_id')
- end
+ describe '#render' do
+ it "renders a 'div' tag for the navigation" do
+ expect(output).to have_css('div')
+ end
- it "sets the right html classes on the rendered 'div' tag" do
- expect(output).to have_css('div.nav_class')
- end
+ it "sets the right html id on the rendered 'div' tag" do
+ expect(output).to have_css('div#nav_id')
+ end
- context 'when no item is selected' do
- it "doesn't render any 'a' tag in the 'div' tag" do
- expect(output).not_to have_css('div a')
- end
- end
+ it "sets the right html classes on the rendered 'div' tag" do
+ expect(output).to have_css('div.nav_class')
+ end
+
+ context 'when no item is selected' do
+ it "doesn't render any 'a' tag in the 'div' tag" do
+ expect(output).not_to have_css('div a')
+ end
+ end
- context 'when an item is selected' do
- let(:item) { :invoices }
+ context 'when an item is selected' do
+ let(:item) { :invoices }
- it "renders the selected 'a' tag" do
- expect(output).to have_css('div a')
- end
+ it "renders the selected 'a' tag" do
+ expect(output).to have_css('div a')
+ end
- it "remders the 'a' tag without any html id" do
- expect(output).not_to have_css('div a[id]')
- end
+ it "remders the 'a' tag without any html id" do
+ expect(output).not_to have_css('div a[id]')
+ end
- it "renders the 'a' tag without any html class" do
- expect(output).not_to have_css('div a[class]')
- end
+ it "renders the 'a' tag without any html class" do
+ expect(output).not_to have_css('div a[class]')
+ end
- context 'and the :allow_classes_and_ids option is true' do
- let(:options) {{ level: :all, allow_classes_and_ids: true }}
+ context 'and the :allow_classes_and_ids option is true' do
+ let(:options) { { level: :all, allow_classes_and_ids: true } }
- it "renders the 'a' tag with the selected class" do
- expect(output).to have_css('div a.selected')
- end
+ it "renders the 'a' tag with the selected class" do
+ expect(output).to have_css('div a.selected')
+ end
- context "and the item hasn't any id explicitly set" do
- it "renders the 'a' tag without any html id" do
- expect(output).not_to have_css('div a[id]')
- end
- end
+ context "and the item hasn't any id explicitly set" do
+ it "renders the 'a' tag without any html id" do
+ expect(output).not_to have_css('div a[id]')
+ end
+ end
- context 'and the item has an explicitly set id' do
- let(:item) { :users }
+ context 'and the item has an explicitly set id' do
+ let(:item) { :users }
- it "renders the 'a' tag with an html id" do
- expect(output).to have_css('div a#breadcrumb_users_link_id')
- end
- end
+ it "renders the 'a' tag with an html id" do
+ expect(output).to have_css('div a#breadcrumb_users_link_id')
end
end
+ end
+ end
- context 'and the :prefix option is set' do
- let(:options) {{ prefix: 'You are here: ' }}
+ context 'and the :prefix option is set' do
+ let(:options) { { prefix: 'You are here: ' } }
- context 'and there are no items to render' do
- let(:item) { nil }
+ context 'and there are no items to render' do
+ let(:item) { nil }
- it "doesn't render the prefix before the breadcrumbs" do
- expect(output).not_to match(/^You are here: /)
- end
- end
+ it "doesn't render the prefix before the breadcrumbs" do
+ expect(output).not_to match(/^You are here: /)
+ end
+ end
- context 'and there are items to render' do
- let(:item) { :invoices }
+ context 'and there are items to render' do
+ let(:item) { :invoices }
- it 'renders the prefix before the breadcrumbs' do
- expect(output).to match(/^You are here: /)
- end
- end
+ it 'renders the prefix before the breadcrumbs' do
+ expect(output).to match(/^You are here: /)
end
+ end
+ end
- context 'when a sub navigation item is selected' do
- before do
- allow(navigation[:invoices]).to receive_messages(selected?: true)
+ context 'when a sub navigation item is selected' do
+ before do
+ allow(navigation[:invoices]).to receive_messages(selected?: true)
- allow(navigation[:invoices].sub_navigation[:unpaid]).to \
- receive_messages(selected?: true, selected_by_condition?: true)
- end
+ allow(navigation[:invoices].sub_navigation[:unpaid]).to \
+ receive_messages(selected?: true, selected_by_condition?: true)
+ end
- it 'renders all items as links' do
- expect(output).to have_css('div a', 2)
- end
+ it 'renders all items as links' do
+ expect(output).to have_css('div a', 2)
+ end
- context 'when the :static_leaf option is true' do
- let(:options) {{ level: :all, static_leaf: true }}
+ context 'when the :static_leaf option is true' do
+ let(:options) { { level: :all, static_leaf: true } }
- it 'renders the items as links' do
- expect(output).to have_css('div a')
- end
+ it 'renders the items as links' do
+ expect(output).to have_css('div a')
+ end
- it 'renders the last item as simple text' do
- expect(output).to have_css('div span')
- end
- end
+ it 'renders the last item as simple text' do
+ expect(output).to have_css('div span')
end
end
end
diff --git a/spec/simple_navigation/renderer/json_spec.rb b/spec/simple_navigation/renderer/json_spec.rb
index bc662ff5..a69d8e36 100644
--- a/spec/simple_navigation/renderer/json_spec.rb
+++ b/spec/simple_navigation/renderer/json_spec.rb
@@ -1,73 +1,66 @@
-module SimpleNavigation
- module Renderer
- describe Json do
- describe '#render' do
- let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
+# frozen_string_literal: true
- let(:item) { :invoices }
- let(:options) {{ level: :all }}
- let(:output) { renderer.render(navigation) }
- let(:parsed_output) { JSON.parse(output) }
- let(:renderer) { Json.new(options) }
+RSpec.describe SimpleNavigation::Renderer::Json do
+ describe '#render' do
+ let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
- before { select_an_item(navigation[item]) if item }
+ let(:item) { :invoices }
+ let(:options) { { level: :all } }
+ let(:output) { renderer.render(navigation) }
+ let(:parsed_output) { JSON.parse(output) }
+ let(:renderer) { described_class.new(options) }
- context 'when an item is selected' do
+ before { select_an_item(navigation[item]) if item }
- it 'renders the selected page' do
- invoices_item = parsed_output.find { |item| item['name'] == 'Invoices' }
- expect(invoices_item).to include('selected' => true)
- end
- end
+ context 'when an item is selected' do
+ it 'renders the selected page' do
+ invoices_item = parsed_output.find { |item| item['name'] == 'Invoices' }
+ expect(invoices_item).to include('selected' => true)
+ end
+ end
- context 'when the :as_hash option is true' do
- let(:options) {{ level: :all, as_hash: true }}
+ context 'when the :as_hash option is true' do
+ let(:options) { { level: :all, as_hash: true } }
- it 'returns every item as a hash' do
- expect(output).to be_an Array
+ it 'returns every item as a hash' do # rubocop:disable RSpec/MultipleExpectations
+ expect(output).to be_an Array
- output.each do |item|
- expect(item).to be_an Hash
- end
- end
+ expect(output).to all(be_an Hash)
+ end
- it 'renders the selected page' do
- invoices_item = output.find { |item| item[:name] == 'Invoices' }
- expect(invoices_item).to include(selected: true)
- end
- end
+ it 'renders the selected page' do
+ invoices_item = output.find { |item| item[:name] == 'Invoices' }
+ expect(invoices_item).to include(selected: true)
+ end
+ end
- context 'with options' do
- it 'should render options for each item' do
- parsed_output.each do |item|
- expect(item).to have_key('options')
- end
- end
- end
+ context 'with options' do
+ it 'renders options for each item' do
+ expect(parsed_output).to all(have_key('options'))
+ end
+ end
- context 'when a sub navigation item is selected' do
- let(:invoices_item) do
- parsed_output.find { |item| item['name'] == 'Invoices' }
- end
- let(:unpaid_item) do
- invoices_item['items'].find { |item| item['name'] == 'Unpaid' }
- end
+ context 'when a sub navigation item is selected' do
+ let(:invoices_item) do
+ parsed_output.find { |item| item['name'] == 'Invoices' }
+ end
+ let(:unpaid_item) do
+ invoices_item['items'].find { |item| item['name'] == 'Unpaid' }
+ end
- before do
- allow(navigation[:invoices]).to receive_messages(selected?: true)
+ before do
+ allow(navigation[:invoices]).to receive_messages(selected?: true)
- allow(navigation[:invoices].sub_navigation[:unpaid]).to \
- receive_messages(selected?: true, selected_by_condition?: true)
- end
+ allow(navigation[:invoices].sub_navigation[:unpaid]).to \
+ receive_messages(selected?: true, selected_by_condition?: true)
+ end
- it 'marks all the parent items as selected' do
- expect(invoices_item).to include('selected' => true)
- end
+ it 'marks all the parent items as selected' do
+ expect(invoices_item).to include('selected' => true)
+ end
- it 'marks the item as selected' do
- expect(unpaid_item).to include('selected' => true)
- end
- end
+ it 'marks the item as selected' do
+ expect(unpaid_item).to include('selected' => true)
end
end
end
diff --git a/spec/simple_navigation/renderer/links_spec.rb b/spec/simple_navigation/renderer/links_spec.rb
index 4fafd5f4..6eef103a 100644
--- a/spec/simple_navigation/renderer/links_spec.rb
+++ b/spec/simple_navigation/renderer/links_spec.rb
@@ -1,86 +1,84 @@
-module SimpleNavigation
- module Renderer
- describe Links do
- describe '#render' do
- let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
-
- let(:item) { nil }
- let(:options) { { level: :all } }
- let(:output) { renderer.render(navigation) }
- let(:renderer) { Links.new(options) }
-
- before { select_an_item(navigation[item]) if item }
-
- it "renders a 'div' tag for the navigation" do
- expect(output).to have_css('div')
- end
-
- it "sets the right html id on the rendered 'div' tag" do
- expect(output).to have_css('div#nav_id')
- end
-
- it "sets the right html classes on the rendered 'div' tag" do
- expect(output).to have_css('div.nav_class')
- end
-
- it "renders an 'a' tag for each item" do
- expect(output).to have_css('a', 3)
- end
-
- it "renders the 'a' tags with the corresponding item's :html_options" do
- expect(output).to have_css('a[style="float:right"]')
- end
-
- context 'when an item has a specified id' do
- it "renders the 'a' tags with the specified id" do
- expect(output).to have_css('a#users_id')
- end
- end
-
- context 'when an item has no specified id' do
- it "uses a default id by stringifying the item's key" do
- expect(output).to have_css('a#invoices')
- end
- end
-
- context 'when no item is selected' do
- it "renders items without the 'selected' class" do
- expect(output).not_to have_css('a.selected')
- end
- end
-
- context 'when an item is selected' do
- let(:item) { :invoices }
-
- it "renders the selected item with the 'selected' class" do
- expect(output).to have_css('a#invoices.selected')
- end
- end
-
- context "when the :join_with option is set" do
- let(:options) {{ level: :all, join_with: ' | ' }}
-
- it 'separates the items with the specified separator' do
- expect(output.scan(' | ').size).to eq 3
- end
- end
-
- context 'when a sub navigation item is selected' do
- before do
- allow(navigation[:invoices]).to receive_messages(selected?: true)
-
- allow(navigation[:invoices].sub_navigation[:unpaid]).to \
- receive_messages(selected?: true, selected_by_condition?: true)
- end
-
- it 'renders the main parent as selected' do
- expect(output).to have_css('a#invoices.selected')
- end
-
- it "doesn't render the nested item's link" do
- expect(output).not_to have_css('a#unpaid')
- end
- end
+# frozen_string_literal: true
+
+RSpec.describe SimpleNavigation::Renderer::Links do
+ describe '#render' do
+ let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
+
+ let(:item) { nil }
+ let(:options) { { level: :all } }
+ let(:output) { renderer.render(navigation) }
+ let(:renderer) { described_class.new(options) }
+
+ before { select_an_item(navigation[item]) if item }
+
+ it "renders a 'div' tag for the navigation" do
+ expect(output).to have_css('div')
+ end
+
+ it "sets the right html id on the rendered 'div' tag" do
+ expect(output).to have_css('div#nav_id')
+ end
+
+ it "sets the right html classes on the rendered 'div' tag" do
+ expect(output).to have_css('div.nav_class')
+ end
+
+ it "renders an 'a' tag for each item" do
+ expect(output).to have_css('a', 3)
+ end
+
+ it "renders the 'a' tags with the corresponding item's :html_options" do
+ expect(output).to have_css('a[style="float:right"]')
+ end
+
+ context 'when an item has a specified id' do
+ it "renders the 'a' tags with the specified id" do
+ expect(output).to have_css('a#users_id')
+ end
+ end
+
+ context 'when an item has no specified id' do
+ it "uses a default id by stringifying the item's key" do
+ expect(output).to have_css('a#invoices')
+ end
+ end
+
+ context 'when no item is selected' do
+ it "renders items without the 'selected' class" do
+ expect(output).not_to have_css('a.selected')
+ end
+ end
+
+ context 'when an item is selected' do
+ let(:item) { :invoices }
+
+ it "renders the selected item with the 'selected' class" do
+ expect(output).to have_css('a#invoices.selected')
+ end
+ end
+
+ context 'when the :join_with option is set' do
+ let(:options) { { level: :all, join_with: ' | ' } }
+
+ it 'separates the items with the specified separator' do
+ expect(output.scan(' | ').size).to eq 3
+ end
+ end
+
+ context 'when a sub navigation item is selected' do
+ before do
+ allow(navigation[:invoices]).to receive_messages(selected?: true)
+
+ allow(navigation[:invoices].sub_navigation[:unpaid]).to \
+ receive_messages(selected?: true, selected_by_condition?: true)
+ end
+
+ it 'renders the main parent as selected' do
+ expect(output).to have_css('a#invoices.selected')
+ end
+
+ it "doesn't render the nested item's link" do
+ expect(output).not_to have_css('a#unpaid')
end
end
end
diff --git a/spec/simple_navigation/renderer/list_spec.rb b/spec/simple_navigation/renderer/list_spec.rb
index b0eb89d4..d28f1edf 100644
--- a/spec/simple_navigation/renderer/list_spec.rb
+++ b/spec/simple_navigation/renderer/list_spec.rb
@@ -1,94 +1,92 @@
-module SimpleNavigation
- module Renderer
- describe List do
- let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
-
- let(:item) { nil }
- let(:options) { { level: :all } }
- let(:output) { renderer.render(navigation) }
- let(:renderer) { List.new(options) }
-
- before { select_an_item(navigation[item]) if item }
-
- describe '#render' do
- it "renders an 'ul' tag for the navigation" do
- expect(output).to have_css('ul')
- end
-
- it "sets the right html id on the rendered 'ul' tag" do
- expect(output).to have_css('ul#nav_id')
- end
-
- it "sets the right html classes on the rendered 'ul' tag" do
- expect(output).to have_css('ul.nav_class')
- end
-
- context 'when an item has no specified id' do
- it "renders the item's 'li' tag with the item's stingified key as id" do
- expect(output).to have_css('li#invoices')
- end
- end
-
- context 'when an item has a specified id' do
- it "renders the item's 'li' tag with the specified id" do
- expect(output).to have_css('li#users_id')
- end
- end
-
- context 'when no item is selected' do
- it "renders each item as 'li' tag without any selected class" do
- expect(output).not_to have_css('ul li.selected')
- end
-
- it "renders each item as 'a' tag without any selected class" do
- expect(output).not_to have_css('ul li a.selected')
- end
- end
-
- context 'when an item is selected' do
- let(:item) { :invoices }
-
- it "renders the item's 'li' tag with its id and selected classes" do
- expect(output).to have_css('li#invoices.selected')
- end
-
- it "renders the item's 'a' tag with the selected classes" do
- expect(output).to have_css('li#invoices a.selected')
- end
- end
-
- context 'when the :ordered option is true' do
- let(:options) {{ level: :all, ordered: true }}
-
- it "renders an 'ol' tag for the navigation" do
- expect(output).to have_css('ol')
- end
-
- it "sets the right html id on the rendered 'ol' tag" do
- expect(output).to have_css('ol#nav_id')
- end
-
- it "sets the right html classes on the rendered 'ol' tag" do
- expect(output).to have_css('ol.nav_class')
- end
- end
-
- context 'when a sub navigation item is selected' do
- before do
- allow(navigation[:invoices]).to receive_messages(selected?: true)
-
- allow(navigation[:invoices].sub_navigation[:unpaid]).to \
- receive_messages(selected?: true, selected_by_condition?: true)
- end
-
- it 'renders the parent items as selected' do
- expect(output).to have_css('li#invoices.selected')
- end
-
- it "renders the selected nested item's link as selected" do
- expect(output).to have_css('li#unpaid.selected')
- end
- end
+# frozen_string_literal: true
+
+RSpec.describe SimpleNavigation::Renderer::List do
+ let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
+
+ let(:item) { nil }
+ let(:options) { { level: :all } }
+ let(:output) { renderer.render(navigation) }
+ let(:renderer) { described_class.new(options) }
+
+ before { select_an_item(navigation[item]) if item }
+
+ describe '#render' do
+ it "renders an 'ul' tag for the navigation" do
+ expect(output).to have_css('ul')
+ end
+
+ it "sets the right html id on the rendered 'ul' tag" do
+ expect(output).to have_css('ul#nav_id')
+ end
+
+ it "sets the right html classes on the rendered 'ul' tag" do
+ expect(output).to have_css('ul.nav_class')
+ end
+
+ context 'when an item has no specified id' do
+ it "renders the item's 'li' tag with the item's stingified key as id" do
+ expect(output).to have_css('li#invoices')
+ end
+ end
+
+ context 'when an item has a specified id' do
+ it "renders the item's 'li' tag with the specified id" do
+ expect(output).to have_css('li#users_id')
+ end
+ end
+
+ context 'when no item is selected' do
+ it "renders each item as 'li' tag without any selected class" do
+ expect(output).not_to have_css('ul li.selected')
+ end
+
+ it "renders each item as 'a' tag without any selected class" do
+ expect(output).not_to have_css('ul li a.selected')
+ end
+ end
+
+ context 'when an item is selected' do
+ let(:item) { :invoices }
+
+ it "renders the item's 'li' tag with its id and selected classes" do
+ expect(output).to have_css('li#invoices.selected')
+ end
+
+ it "renders the item's 'a' tag with the selected classes" do
+ expect(output).to have_css('li#invoices a.selected')
+ end
+ end
+
+ context 'when the :ordered option is true' do
+ let(:options) { { level: :all, ordered: true } }
+
+ it "renders an 'ol' tag for the navigation" do
+ expect(output).to have_css('ol')
+ end
+
+ it "sets the right html id on the rendered 'ol' tag" do
+ expect(output).to have_css('ol#nav_id')
+ end
+
+ it "sets the right html classes on the rendered 'ol' tag" do
+ expect(output).to have_css('ol.nav_class')
+ end
+ end
+
+ context 'when a sub navigation item is selected' do
+ before do
+ allow(navigation[:invoices]).to receive_messages(selected?: true)
+
+ allow(navigation[:invoices].sub_navigation[:unpaid]).to \
+ receive_messages(selected?: true, selected_by_condition?: true)
+ end
+
+ it 'renders the parent items as selected' do
+ expect(output).to have_css('li#invoices.selected')
+ end
+
+ it "renders the selected nested item's link as selected" do
+ expect(output).to have_css('li#unpaid.selected')
end
end
end
diff --git a/spec/simple_navigation/renderer/text_spec.rb b/spec/simple_navigation/renderer/text_spec.rb
index 4fb5b09a..583afb20 100644
--- a/spec/simple_navigation/renderer/text_spec.rb
+++ b/spec/simple_navigation/renderer/text_spec.rb
@@ -1,49 +1,47 @@
-module SimpleNavigation
- module Renderer
- describe Text do
- let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
-
- let(:item) { nil }
- let(:options) {{ level: :all }}
- let(:output) { renderer.render(navigation) }
- let(:renderer) { Text.new(options) }
-
- before { select_an_item(navigation[item]) if item }
-
- describe '#render' do
- context 'when no item is selected' do
- it 'renders an empty string' do
- expect(output).to eq ''
- end
- end
+# frozen_string_literal: true
- context 'when an item is selected' do
- let(:item) { :invoices }
+RSpec.describe SimpleNavigation::Renderer::Text do
+ let!(:navigation) { setup_navigation('nav_id', 'nav_class') }
- it "renders the selected item's name" do
- expect(output).to eq 'Invoices'
- end
- end
+ let(:item) { nil }
+ let(:options) { { level: :all } }
+ let(:output) { renderer.render(navigation) }
+ let(:renderer) { described_class.new(options) }
+
+ before { select_an_item(navigation[item]) if item }
+
+ describe '#render' do
+ context 'when no item is selected' do
+ it 'renders an empty string' do
+ expect(output).to eq ''
+ end
+ end
- context 'when a sub navigation item is selected' do
- before do
- allow(navigation[:invoices]).to receive_messages(selected?: true)
+ context 'when an item is selected' do
+ let(:item) { :invoices }
- allow(navigation[:invoices].sub_navigation[:unpaid]).to \
- receive_messages(selected?: true, selected_by_condition?: true)
- end
+ it "renders the selected item's name" do
+ expect(output).to eq 'Invoices'
+ end
+ end
+
+ context 'when a sub navigation item is selected' do
+ before do
+ allow(navigation[:invoices]).to receive_messages(selected?: true)
- it 'separates the items with a space' do
- expect(output).to eq 'Invoices Unpaid'
- end
+ allow(navigation[:invoices].sub_navigation[:unpaid]).to \
+ receive_messages(selected?: true, selected_by_condition?: true)
+ end
+
+ it 'separates the items with a space' do
+ expect(output).to eq 'Invoices Unpaid'
+ end
- context "and the :join_with option is set" do
- let(:options) {{ level: :all, join_with: ' | ' }}
+ context 'and the :join_with option is set' do
+ let(:options) { { level: :all, join_with: ' | ' } }
- it 'separates the items with the specified separator' do
- expect(output).to eq 'Invoices | Unpaid'
- end
- end
+ it 'separates the items with the specified separator' do
+ expect(output).to eq 'Invoices | Unpaid'
end
end
end
diff --git a/spec/simple_navigation_spec.rb b/spec/simple_navigation_spec.rb
index da708875..5c21ca46 100644
--- a/spec/simple_navigation_spec.rb
+++ b/spec/simple_navigation_spec.rb
@@ -1,4 +1,6 @@
-describe SimpleNavigation do
+# frozen_string_literal: true
+
+RSpec.describe SimpleNavigation do
before { subject.config_file_path = 'path_to_config' }
describe 'config_file_path=' do
@@ -53,7 +55,7 @@
end
end
- describe '.load_config', memfs: true do
+ describe '.load_config', :memfs do
let(:paths) { ['/path/one', '/path/two'] }
before do
@@ -104,7 +106,7 @@
context "when the config file for the context doesn't exists" do
it 'raises an exception' do
- expect{ subject.load_config }.to raise_error(RuntimeError, /Config file 'navigation.rb' not found in path\(s\)/)
+ expect { subject.load_config }.to raise_error(RuntimeError, /Config file 'navigation.rb' not found in path\(s\)/)
end
end
end
@@ -150,7 +152,7 @@
context 'when level is something else' do
it 'raises an exception' do
- expect{
+ expect {
subject.active_item_container_for('something else')
}.to raise_error(ArgumentError, 'Invalid navigation level: something else')
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 463deec4..c41e5996 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,76 +1,155 @@
-require 'initializers/have_css_matcher'
-require 'initializers/memfs'
-require 'initializers/coveralls'
-require 'initializers/rails'
-require 'initializers/rspec'
+# frozen_string_literal: true
+
+# Load ruby-warning gem
+require 'warning'
+
+Warning[:deprecated] = true
+Warning[:experimental] = true
+Warning[:performance] = true if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.3.0')
+
+# Ignore all warnings in Gem dependencies
+Gem.path.each do |path|
+ Warning.ignore(//, path)
+end
+
+# Ignore method redefinitions
+Warning.ignore(/warning: previous definition of/)
+Warning.ignore(/warning: method redefined;/)
+
+# Load simplecov
+require 'simplecov'
+require 'simplecov_json_formatter'
+
+# Start SimpleCov
+SimpleCov.start do
+ formatter SimpleCov::Formatter::MultiFormatter.new([SimpleCov::Formatter::HTMLFormatter, SimpleCov::Formatter::JSONFormatter])
+ add_filter 'spec/'
+end
+
+# Load test gems
+require 'memfs'
require 'capybara/rspec'
-require 'bundler/setup'
-Bundler.require
+# Define our own spec helper
+module SimpleNavigationTest
+ extend RSpec::Mocks::ExampleMethods
-if defined? Rails
- require 'fake_app/rails_app'
- require 'rspec/rails'
+ module_function
- Capybara.app = RailsApp::Application
+ def setup_adapter_for(framework, context = double(:context))
+ if framework == :rails
+ # Rails 6.0 and 6.1 provide ActionView::Base.empty method that creates ActionView with an empty LookupContext.
+ # The method is not available on older versions
+ view_context = ActionView::Base.respond_to?(:empty) ? ActionView::Base.empty : ActionView::Base.new
+ allow(context).to receive_messages(view_context: view_context)
+ end
- RSpec.configure do |config|
- config.before do
- SimpleNavigation.config_files.clear
- setup_adapter_for :rails
+ allow(SimpleNavigation).to receive_messages(framework: framework)
+ SimpleNavigation.load_adapter
+ SimpleNavigation.init_adapter_from(context)
+ end
+
+ def select_an_item(item)
+ allow(item).to receive_messages(selected?: true)
+ end
+
+ def setup_container(dom_id, dom_class)
+ container = SimpleNavigation::ItemContainer.new(1)
+ container.dom_id = dom_id
+ container.dom_class = dom_class
+ container
+ end
+
+ def setup_navigation(dom_id, dom_class)
+ setup_adapter_for :rails
+ container = setup_container(dom_id, dom_class)
+ setup_items(container)
+ container
+ end
+
+ # FIXME: adding the :link option for the list renderer messes up the other
+ # renderers
+ def setup_items(container) # rubocop:disable Metrics/AbcSize
+ container.item :users, 'Users', '/users', html: { id: 'users_id' }, link_html: { id: 'users_link_id' }
+ container.item :invoices, 'Invoices', '/invoices' do |invoices|
+ invoices.item :paid, 'Paid', '/invoices/paid'
+ invoices.item :unpaid, 'Unpaid', '/invoices/unpaid'
+ end
+ container.item :accounts, 'Accounts', '/accounts', html: { style: 'float:right' }
+ container.item :miscellany, 'Miscellany'
+
+ container.items.each do |item|
+ allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
+
+ item.sub_navigation&.items&.each do |item|
+ allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
+ end
end
end
end
-def setup_adapter_for(framework, context = double(:context))
- if framework == :rails
- # Rails 6.0 and 6.1 provide ActionView::Base.empty method that creates ActionView with an empty LookupContext.
- # The method is not available on older versions
- view_context = ActionView::Base.respond_to?(:empty) ? ActionView::Base.empty : ActionView::Base.new
- allow(context).to receive_messages(view_context: view_context)
+# Configure RSpec
+RSpec.configure do |config|
+ config.include SimpleNavigationTest
+
+ config.color = true
+ config.fail_fast = false
+
+ config.order = :random
+ Kernel.srand config.seed
+
+ config.expect_with(:rspec) do |c|
+ c.syntax = :expect
end
- allow(SimpleNavigation).to receive_messages(framework: framework)
- SimpleNavigation.load_adapter
- SimpleNavigation.init_adapter_from(context)
-end
+ # disable monkey patching
+ # see: https://rspec.info/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/
+ config.disable_monkey_patching!
-def select_an_item(item)
- allow(item).to receive_messages(selected?: true)
-end
+ config.raise_errors_for_deprecations!
-def setup_container(dom_id, dom_class)
- container = SimpleNavigation::ItemContainer.new(1)
- container.dom_id = dom_id
- container.dom_class = dom_class
- container
+ config.around(memfs: true) do |example|
+ MemFs.activate { example.run }
+ end
end
-def setup_navigation(dom_id, dom_class)
- setup_adapter_for :rails
- container = setup_container(dom_id, dom_class)
- setup_items(container)
- container
-end
+# Define our own matcher
+RSpec::Matchers.define :have_css do |expected, times|
+ match do |actual|
+ selector = Nokogiri::HTML(actual).css(expected)
-# FIXME: adding the :link option for the list renderer messes up the other
-# renderers
-def setup_items(container)
- container.item :users, 'Users', '/users', html: { id: 'users_id' }, link_html: { id: 'users_link_id' }
- container.item :invoices, 'Invoices', '/invoices' do |invoices|
- invoices.item :paid, 'Paid', '/invoices/paid'
- invoices.item :unpaid, 'Unpaid', '/invoices/unpaid'
+ if times
+ expect(selector.size).to eq times
+ else
+ expect(selector.size).to be >= 1
+ end
end
- container.item :accounts, 'Accounts', '/accounts', html: { style: 'float:right' }
- container.item :miscellany, 'Miscellany'
- container.items.each do |item|
- allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
+ failure_message do |actual|
+ "expected #{actual} to have #{times || 1} elements matching '#{expected}'"
+ end
- if item.sub_navigation
- item.sub_navigation.items.each do |item|
- allow(item).to receive_messages(selected?: false, selected_by_condition?: false)
- end
+ failure_message_when_negated do |actual|
+ "expected #{actual} not to have #{times || 1} elements matching '#{expected}'"
+ end
+end
+
+# Configure RSpec with Rails
+begin
+ require 'rails'
+rescue LoadError # rubocop:disable Lint/SuppressedException
+else
+ require 'fake_app/rails_app'
+ require 'rspec/rails'
+
+ Capybara.app = RailsApp::Application
+
+ RSpec.configure do |config|
+ config.before do
+ SimpleNavigation.config_files.clear
+ SimpleNavigationTest.setup_adapter_for :rails
end
end
end
+
+class ModifiedHash < Hash; end
diff --git a/uninstall.rb b/uninstall.rb
deleted file mode 100644
index 97383334..00000000
--- a/uninstall.rb
+++ /dev/null
@@ -1 +0,0 @@
-# Uninstall hook code here