diff --git a/Gemfile b/Gemfile
index e3e96c44d..0d3ce960b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -21,6 +21,8 @@ gem 'font-awesome-sass'
gem 'uglifier' # JavaScript compressor
+gem 'oj' # Speeds up json
+
# planting and harvest predictions
# based on median values for the crop
gem 'active_median', '0.1.4' # needs postgresql update https://github.com/Growstuff/growstuff/issues/1757
@@ -78,17 +80,12 @@ gem 'omniauth-facebook'
gem 'omniauth-flickr', '>= 0.0.15'
gem 'omniauth-twitter'
+# Pretty charts
gem "chartkick"
-# client for Elasticsearch. Elasticsearch is a flexible
-# and powerful, distributed, real-time search and analytics engine.
-# An example of the use in the project is fuzzy crop search.
-# Project does not use semver, so we want to be in sync with the version of
-# elasticsearch we use
-# See https://github.com/elastic/elasticsearch-ruby#compatibility
-gem "elasticsearch-api", "~> 6.0.0"
-gem "elasticsearch-model", "~> 6.0.0"
-gem "elasticsearch-rails", "~> 6.0.0"
+# clever elastic search
+gem 'searchkick'
+
gem "hashie", ">= 3.5.3"
gem 'rake', '>= 10.0.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 3043c46d2..c1195da99 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -79,8 +79,8 @@ GEM
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.0.1)
- cancancan (2.3.0)
- capybara (3.15.0)
+ cancancan (3.0.1)
+ capybara (3.16.2)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
@@ -134,7 +134,7 @@ GEM
activesupport (>= 3.0.0)
dalli (2.7.10)
database_cleaner (1.7.0)
- devise (4.6.1)
+ devise (4.6.2)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 6.0)
@@ -142,17 +142,17 @@ GEM
warden (~> 1.2.3)
diff-lcs (1.3)
docile (1.1.5)
- elasticsearch (6.0.3)
- elasticsearch-api (= 6.0.3)
- elasticsearch-transport (= 6.0.3)
- elasticsearch-api (6.0.3)
+ elasticsearch (6.2.0)
+ elasticsearch-api (= 6.2.0)
+ elasticsearch-transport (= 6.2.0)
+ elasticsearch-api (6.2.0)
multi_json
elasticsearch-model (6.0.0)
activesupport (> 3)
elasticsearch (> 1)
hashie
elasticsearch-rails (6.0.0)
- elasticsearch-transport (6.0.3)
+ elasticsearch-transport (6.2.0)
faraday
multi_json
erubi (1.8.0)
@@ -212,7 +212,7 @@ GEM
excon
moneta
multi_json (>= 1.9.2)
- highline (2.0.0)
+ highline (2.0.1)
html2haml (2.2.0)
erubis (~> 2.7.0)
haml (>= 4.0, < 6)
@@ -223,7 +223,7 @@ GEM
multi_xml (>= 0.5.2)
i18n (1.6.0)
concurrent-ruby (~> 1.0)
- i18n-tasks (0.9.28)
+ i18n-tasks (0.9.29)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
erubi
@@ -240,11 +240,11 @@ GEM
thor (>= 0.14, < 2.0)
jquery-ui-rails (6.0.1)
railties (>= 3.2.16)
- js-routes (1.4.4)
- railties (>= 3.2)
+ js-routes (1.4.6)
+ railties (>= 4)
sprockets-rails
json (2.1.0)
- jsonapi-resources (0.9.5)
+ jsonapi-resources (0.9.6)
activerecord (>= 4.1)
concurrent-ruby
railties (>= 4.1)
@@ -265,7 +265,7 @@ GEM
kramdown (2.1.0)
launchy (2.4.3)
addressable (~> 2.3)
- leaflet-rails (1.3.1)
+ leaflet-rails (1.4.0)
rails (>= 4.2.0)
letter_opener (1.7.0)
launchy (~> 2.2)
@@ -296,7 +296,7 @@ GEM
multipart-post (2.0.0)
newrelic_rpm (6.2.0.354)
nio4r (2.3.1)
- nokogiri (1.10.1)
+ nokogiri (1.10.2)
mini_portile2 (~> 2.4.0)
oauth (0.5.4)
oauth2 (1.4.1)
@@ -305,6 +305,7 @@ GEM
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
+ oj (3.7.11)
omniauth (1.9.0)
hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3)
@@ -323,10 +324,10 @@ GEM
omniauth-oauth (~> 1.1)
rack
orm_adapter (0.5.0)
- parallel (1.14.0)
+ parallel (1.17.0)
paranoia (2.4.1)
activerecord (>= 4.0, < 5.3)
- parser (2.6.0.0)
+ parser (2.6.2.1)
ast (~> 2.4.0)
pg (0.21.0)
platform-api (2.2.0)
@@ -339,7 +340,7 @@ GEM
psych (3.1.0)
public_suffix (3.0.3)
puma (3.12.1)
- rack (2.0.6)
+ rack (2.0.7)
rack-protection (2.0.5)
rack
rack-test (1.1.0)
@@ -390,7 +391,7 @@ GEM
rb-inotify (0.10.0)
ffi (~> 1.0)
redis (4.1.0)
- regexp_parser (1.3.0)
+ regexp_parser (1.4.0)
responders (2.4.1)
actionpack (>= 4.2.0, < 6.0)
railties (>= 4.2.0, < 6.0)
@@ -415,7 +416,7 @@ GEM
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
- rubocop (0.66.0)
+ rubocop (0.67.2)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1)
@@ -452,11 +453,15 @@ GEM
sprockets-rails
tilt
scout_apm (2.4.24)
+ searchkick (3.1.2)
+ activemodel (>= 4.2)
+ elasticsearch (>= 5)
+ hashie
selenium-webdriver (3.141.0)
childprocess (~> 0.5)
rubyzip (~> 1.2, >= 1.2.2)
sexp_processor (4.12.0)
- sidekiq (5.2.5)
+ sidekiq (5.2.6)
connection_pool (~> 2.2, >= 2.2.2)
rack (>= 1.5.0)
rack-protection (>= 1.5.0)
@@ -536,9 +541,6 @@ DEPENDENCIES
dalli
database_cleaner
devise
- elasticsearch-api (~> 6.0.0)
- elasticsearch-model (~> 6.0.0)
- elasticsearch-rails (~> 6.0.0)
factory_bot_rails
faker
figaro
@@ -565,6 +567,7 @@ DEPENDENCIES
loofah (>= 2.2.1)
memcachier
newrelic_rpm
+ oj
omniauth (~> 1.3)
omniauth-facebook
omniauth-flickr (>= 0.0.15)
@@ -588,6 +591,7 @@ DEPENDENCIES
ruby-units
sass-rails
scout_apm
+ searchkick
selenium-webdriver
sidekiq
timecop
diff --git a/README.md b/README.md
index a0433b22b..c2d696fa2 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ encourage participation from people of all backgrounds and skill levels.
## Important links
-* [Issues](http://github.com/Growstuff/growstuff/issues) (features we're
+* [Issues](https://github.com/orgs/Growstuff/projects/1) (features we're
working on, known bugs, etc)
* [IRC](https://webchat.freenode.net/) growstuff channel (general chat, brainstorming and troubleshooting) or [Gitter](https://gitter.im/Growstuff/growstuff)
* [Wiki](https://github.com/Growstuff/growstuff/wiki) (general documentation, etc. Help by migrating from the [old wiki](https://web.archive.org/web/*/wiki.growstuff.org))
@@ -44,9 +44,9 @@ You might like to check out:
Here on Github, you might find these useful:
-* [Waffle](http://waffle.io/Growstuff/growstuff) has stories in "ready" that can be worked on.
+* [Github Project Board](https://github.com/orgs/Growstuff/projects/1) has stories in "ready" that can be worked on.
* [needs: design](https://github.com/Growstuff/growstuff/labels/needs:%20design) - tasks requiring high-level design
-* [needs: visual design](https://github.com/Growstuff/growstuff/labels/needs:%20visual design) - tasks requiring visual/graphical design
+* [needs: visual design](https://github.com/Growstuff/growstuff/labels/needs:%20visual+design) - tasks requiring visual/graphical design
* [needs: documentation](https://github.com/Growstuff/growstuff/labels/needs:%20documentation)
* [needs: data](https://github.com/Growstuff/growstuff/labels/needs:%20data) - tasks requiring data entry, data design, data import, or similar
* [curated:beginner](https://github.com/Growstuff/growstuff/labels/curated:%20beginner) - tasks that are ideal for beginner programmers or people new to the project
diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb
index 5b9562077..c4e2fcdfb 100644
--- a/app/controllers/crops_controller.rb
+++ b/app/controllers/crops_controller.rb
@@ -42,14 +42,18 @@ class CropsController < ApplicationController
def search
@term = params[:term]
- @matches = Crop.search(@term)
- @paginated_matches = @matches.paginate(page: params[:page])
- respond_with @matches
+ @crops = CropSearchService.search(
+ @term, page: params[:page],
+ per_page: 12,
+ current_member: current_member
+ )
+ respond_with @crops
end
def show
- @crop = Crop.includes(:scientific_names, plantings: :photos).find_by!(slug: params[:slug])
+ @crop = Crop.includes(:scientific_names, plantings: :photos)
+ .find_by!(slug: params[:slug])
@posts = @crop.posts.order(created_at: :desc).paginate(page: params[:page])
@photos = Photo.by_crop(@crop)
diff --git a/app/controllers/garden_types_controller.rb b/app/controllers/garden_types_controller.rb
new file mode 100644
index 000000000..5fade528a
--- /dev/null
+++ b/app/controllers/garden_types_controller.rb
@@ -0,0 +1,51 @@
+class GardenTypesController < ApplicationController
+ respond_to :html, :json
+ load_and_authorize_resource
+
+ # GET /garden_types
+ def index
+ @garden_types = GardenType.all.paginate(page: params[:page])
+ respond_with @garden_types
+ end
+
+ # GET /garden_types/1
+ def show
+ respond_with @garden_type
+ end
+
+ # GET /garden_types/new
+ def new
+ @garden_type = GardenType.new
+ end
+
+ # GET /garden_types/1/edit
+ def edit; end
+
+ # POST /garden_types
+ def create
+ @garden_type = GardenType.create(garden_type_params)
+ respond_with(@garden_type)
+ end
+
+ # PATCH/PUT /garden_types/1
+ def update
+ @garden_type.update(garden_type_params)
+ respond_with @garden_type
+ end
+
+ # DELETE /garden_types/1
+ def destroy
+ @garden_type.destroy
+ respond_with @garden_type
+ end
+
+ private
+
+ def set_garden_type
+ @garden_type = GardenType.find(params[:id])
+ end
+
+ def garden_type_params
+ params.require(:garden_type).permit(:description, :slug)
+ end
+end
diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb
index e69fda623..5851ba722 100644
--- a/app/controllers/gardens_controller.rb
+++ b/app/controllers/gardens_controller.rb
@@ -13,6 +13,7 @@ class GardensController < ApplicationController
@gardens = @gardens.active unless @show_all
@gardens = @gardens.where(owner: @owner) if @owner.present?
@gardens = @gardens.joins(:owner).order(:name).paginate(page: params[:page])
+ @gardens = @gardens.includes(:owner, plantings: [:owner, crop: :parent])
respond_with(@gardens)
end
@@ -67,6 +68,6 @@ class GardensController < ApplicationController
def garden_params
params.require(:garden).permit(:name, :slug, :description, :active,
- :location, :latitude, :longitude, :area, :area_unit)
+ :location, :latitude, :longitude, :area, :area_unit, :garden_type_id)
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index d93850629..b86731d7e 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -27,11 +27,9 @@ module ApplicationHelper
end
def required_field_help_text
- # rubocop:disable Rails/OutputSafety
asterisk = content_tag :span, '*', class: ['red']
text = content_tag :em, 'denotes a required field'
content_tag :div, asterisk + ' '.html_safe + text, class: ['margin-bottom']
- # rubocop:enable Rails/OutputSafety
end
#
diff --git a/app/helpers/auto_suggest_helper.rb b/app/helpers/auto_suggest_helper.rb
index 6d4637d4e..1f9030fd8 100644
--- a/app/helpers/auto_suggest_helper.rb
+++ b/app/helpers/auto_suggest_helper.rb
@@ -10,8 +10,7 @@ module AutoSuggestHelper
end
resource = resource.class.name.downcase
- source_path = Rails.application.routes.url_helpers.send("search_#{source}s_path")
-
+ source_path = Rails.application.routes.url_helpers.send("search_#{source}s_path", format: :json)
%(
{ approved.has_photos }
scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) }
+ # Special scope to control if it's in the search index
+ scope :search_import, -> { approved }
+
##
## Validations
# Reasons are only necessary when rejecting
@@ -53,47 +56,7 @@ class Crop < ApplicationRecord
####################################
# Elastic search configuration
if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
- include Elasticsearch::Model
- include Elasticsearch::Model::Callbacks
- # In order to avoid clashing between different environments,
- # use Rails.env as a part of index name (eg. development_growstuff)
- index_name [Rails.env, "growstuff"].join('_')
- settings index: { number_of_shards: 1 },
- analysis: {
- tokenizer: {
- gs_edgeNGram_tokenizer: {
- type: "edgeNGram", # edgeNGram: NGram match from the start of a token
- min_gram: 3,
- max_gram: 10,
- # token_chars: Elasticsearch will split on characters
- # that don't belong to any of these classes
- token_chars: %w(letter digit)
- }
- },
- analyzer: {
- gs_edgeNGram_analyzer: {
- tokenizer: "gs_edgeNGram_tokenizer",
- filter: ["lowercase"]
- }
- }
- } do
- mappings dynamic: 'false' do
- indexes :id, type: 'long'
- indexes :name, type: 'text', analyzer: 'gs_edgeNGram_analyzer'
- indexes :approval_status, type: 'text'
- indexes :scientific_names do
- indexes :name,
- type: 'text',
- analyzer: 'gs_edgeNGram_analyzer',
- # Disabling field-length norm (norm). If the norm option is turned on(by default),
- # higher weigh would be given for shorter fields, which in our case is irrelevant.
- norms: { enabled: false }
- end
- indexes :alternate_names do
- indexes :name, type: 'text', analyzer: 'gs_edgeNGram_analyzer'
- end
- end
- end
+ searchkick word_start: %i(name alternate_names scientific_names), case_sensitive: false
end
def planting_photos
@@ -108,13 +71,6 @@ class Crop < ApplicationRecord
Photo.joins(:seeds).where("seeds.crop_id": id)
end
- # update the Elasticsearch index (only if we're using it in this
- # environment)
- def update_index(_name_obj)
- __elasticsearch__.index_document if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
- end
- # End Elasticsearch section
-
def to_s
name
end
@@ -210,14 +166,24 @@ class Crop < ApplicationRecord
update(median_days_to_last_harvest: Planting.where(crop: self).median(:days_to_last_harvest))
end
- def self.search(query)
- CropSearchService.search(query)
- end
-
def self.case_insensitive_name(name)
where(["lower(crops.name) = :value", { value: name.downcase }])
end
+ def should_index?
+ approved?
+ end
+
+ def search_data
+ {
+ name: name,
+ alternate_names: alternate_names.pluck(:name),
+ scientific_names: scientific_names.pluck(:name),
+ plantings_count: plantings_count, # boost the crops that are planted the most
+ planters_ids: plantings.pluck(:owner_id) # boost this product for these members
+ }
+ end
+
private
def count_uses_of_property(col_name)
diff --git a/app/models/garden.rb b/app/models/garden.rb
index e712ce11c..fcbb32ea6 100644
--- a/app/models/garden.rb
+++ b/app/models/garden.rb
@@ -8,6 +8,8 @@ class Garden < ApplicationRecord
has_many :plantings, dependent: :destroy
has_many :crops, through: :plantings
+ belongs_to :garden_type, optional: true
+
# set up geocoding
geocoded_by :location
after_validation :geocode
@@ -17,6 +19,7 @@ class Garden < ApplicationRecord
default_scope { joins(:owner) } # Ensures owner exists
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
+ scope :order_by_name, -> { order("lower(name) asc") }
validates :location, length: { maximum: 255 }
validates :slug, uniqueness: true
@@ -43,7 +46,6 @@ class Garden < ApplicationRecord
}.freeze
validates :area_unit, inclusion: { in: AREA_UNITS_VALUES.values,
message: "%s is not a valid area unit" },
- allow_nil: true,
allow_blank: true
after_validation :cleanup_area
diff --git a/app/models/garden_type.rb b/app/models/garden_type.rb
new file mode 100644
index 000000000..b81789b69
--- /dev/null
+++ b/app/models/garden_type.rb
@@ -0,0 +1,19 @@
+class GardenType < ApplicationRecord
+ extend FriendlyId
+ friendly_id :name, use: %i(slugged finders)
+
+ has_many :gardens, dependent: :nullify
+
+ validates :name, presence: true, uniqueness: true
+ validates :slug, presence: true, uniqueness: true
+
+ def garden_type_slug
+ name.gsub!(/[^A-Za-z]/, '')
+ end
+
+ def subtitler(garden_type)
+ num = garden_type.gardens.uniq.count
+ s = num > 1 || num.zero? ? "s are" : " is"
+ "#{num} garden#{s} using this garden type"
+ end
+end
diff --git a/app/models/harvest.rb b/app/models/harvest.rb
index 94b71d7b4..c3ea95b66 100644
--- a/app/models/harvest.rb
+++ b/app/models/harvest.rb
@@ -57,11 +57,11 @@ class Harvest < ApplicationRecord
validates :quantity, allow_nil: true, numericality: {
only_integer: false, greater_than_or_equal_to: 0
}
- validates :unit, allow_nil: true, allow_blank: true, inclusion: {
+ validates :unit, allow_blank: true, inclusion: {
in: UNITS_VALUES.values, message: "%s is not a valid unit"
}
validates :weight_quantity, allow_nil: true, numericality: { only_integer: false }
- validates :weight_unit, allow_nil: true, allow_blank: true, inclusion: {
+ validates :weight_unit, allow_blank: true, inclusion: {
in: WEIGHT_UNITS_VALUES.values, message: "%s is not a valid unit"
}
validate :crop_must_match_planting
diff --git a/app/models/planting.rb b/app/models/planting.rb
index 95908723b..9c4a59be5 100644
--- a/app/models/planting.rb
+++ b/app/models/planting.rb
@@ -23,7 +23,7 @@ class Planting < ApplicationRecord
# Ancestry of food
belongs_to :parent_seed, class_name: 'Seed', # parent
foreign_key: 'parent_seed_id',
- required: false,
+ optional: true,
inverse_of: :child_plantings
has_many :child_seeds, class_name: 'Seed', # children
foreign_key: 'parent_planting_id',
@@ -56,10 +56,10 @@ class Planting < ApplicationRecord
validates :quantity, allow_nil: true, numericality: {
only_integer: true, greater_than_or_equal_to: 0
}
- validates :sunniness, allow_nil: true, allow_blank: true, inclusion: {
+ validates :sunniness, allow_blank: true, inclusion: {
in: SUNNINESS_VALUES, message: "%s is not a valid sunniness value"
}
- validates :planted_from, allow_nil: true, allow_blank: true, inclusion: {
+ validates :planted_from, allow_blank: true, inclusion: {
in: PLANTED_FROM_VALUES, message: "%s is not a valid planting method"
}
diff --git a/app/models/scientific_name.rb b/app/models/scientific_name.rb
index 7b20d2e9e..f593d0eef 100644
--- a/app/models/scientific_name.rb
+++ b/app/models/scientific_name.rb
@@ -1,7 +1,8 @@
class ScientificName < ApplicationRecord
- after_commit { |sn| sn.crop.__elasticsearch__.index_document if sn.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" }
belongs_to :crop
belongs_to :creator, class_name: 'Member', inverse_of: :created_scientific_names
validates :name, presence: true
validates :crop, presence: true
+ after_commit :reindex if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
+ delegate :reindex, to: :crop
end
diff --git a/app/models/seed.rb b/app/models/seed.rb
index 2075afba2..7c49c9201 100644
--- a/app/models/seed.rb
+++ b/app/models/seed.rb
@@ -14,7 +14,7 @@ class Seed < ApplicationRecord
# Relationships
belongs_to :crop
belongs_to :parent_planting, class_name: 'Planting', foreign_key: 'parent_planting_id',
- required: false, inverse_of: :child_seeds # parent
+ optional: true, inverse_of: :child_seeds # parent
has_many :child_plantings, class_name: 'Planting',
foreign_key: 'parent_seed_id', dependent: :nullify,
inverse_of: :parent_seed # children
@@ -29,17 +29,17 @@ class Seed < ApplicationRecord
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
validates :days_until_maturity_max, allow_nil: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
- validates :tradable_to, allow_nil: false, allow_blank: false,
- inclusion: { in: TRADABLE_TO_VALUES, message: "You may only trade seed nowhere, "\
+ validates :tradable_to, allow_blank: false,
+ inclusion: { in: TRADABLE_TO_VALUES, message: "You may only trade seed nowhere, "\
"locally, nationally, or internationally" }
- validates :organic, allow_nil: false, allow_blank: false,
- inclusion: { in: ORGANIC_VALUES, message: "You must say whether the seeds "\
+ validates :organic, allow_blank: false,
+ inclusion: { in: ORGANIC_VALUES, message: "You must say whether the seeds "\
"are organic or not, or that you don't know" }
- validates :gmo, allow_nil: false, allow_blank: false,
- inclusion: { in: GMO_VALUES, message: "You must say whether the seeds are "\
+ validates :gmo, allow_blank: false,
+ inclusion: { in: GMO_VALUES, message: "You must say whether the seeds are "\
"genetically modified or not, or that you don't know" }
- validates :heirloom, allow_nil: false, allow_blank: false,
- inclusion: { in: HEIRLOOM_VALUES, message: "You must say whether the seeds"\
+ validates :heirloom, allow_blank: false,
+ inclusion: { in: HEIRLOOM_VALUES, message: "You must say whether the seeds"\
"are heirloom, hybrid, or unknown" }
#
diff --git a/app/services/crop_search_service.rb b/app/services/crop_search_service.rb
index 8fce60b2d..c2df12ef5 100644
--- a/app/services/crop_search_service.rb
+++ b/app/services/crop_search_service.rb
@@ -1,40 +1,49 @@
class CropSearchService
# Crop.search(string)
- def self.search(query)
- if ENV['GROWSTUFF_ELASTICSEARCH'] == "true"
- search_str = query.nil? ? "" : query.downcase
- response = Crop.__elasticsearch__.search(
- query: {
- bool: {
- filter: {
- term: { "approval_status" => "approved" }
- },
- must: {
- query_string: {
- query: "*#{search_str}*"
- }
- }
- }
- }
- )
- response.records.to_a
+ def self.search(query, page: 1, per_page: 12, current_member: nil)
+ if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
+ elasticsearch(query, page: page, per_page: per_page, current_member: current_member)
else
- # if we don't have elasticsearch, just do a basic SQL query.
- # also, make sure it's an actual array not an activerecord
- # collection, so it matches what we get from elasticsearch and we can
- # manipulate it in the same ways (eg. deleting elements without deleting
- # the whole record from the db)
- matches = Crop.approved.where("name ILIKE ?", "%#{query}%").to_a
-
- # we want to make sure that exact matches come first, even if not
- # using elasticsearch (eg. in development)
- exact_match = Crop.approved.find_by(name: query)
- if exact_match
- matches.delete(exact_match)
- matches.unshift(exact_match)
- end
-
- matches
+ dbsearch(query, page: page, per_page: per_page)
end
end
+
+ def self.elasticsearch(query, page: 1, per_page: 12, current_member: nil)
+ search_params = {
+ page: page,
+ per_page: per_page,
+ fields: %i(name^5 alternate_names scientific_names),
+ match: :word_start,
+ boost_by: [:plantings_count],
+ includes: %i(scientific_names alternate_names),
+ misspellings: { edit_distance: 2 }
+ }
+ # prioritise crops the member has planted
+ search_params[:boost_where] = { planters_ids: current_member.id } if current_member
+
+ Crop.search(query, search_params)
+ end
+
+ def self.dbsearch(query, page: 1, per_page: 12)
+ # if we don't have elasticsearch, just do a basic SQL query.
+ # also, make sure it's an actual array not an activerecord
+ # collection, so it matches what we get from elasticsearch and we can
+ # manipulate it in the same ways (eg. deleting elements without deleting
+ # the whole record from the db)
+ matcher = "%#{query}%"
+ matches = Crop.approved
+ .left_outer_joins(:alternate_names, :scientific_names)
+ .where("crops.name ILIKE ? OR alternate_names.name ILIKE ? OR scientific_names.name ILIKE ?",
+ matcher, matcher, matcher)
+
+ matches = matches.to_a
+ # we want to make sure that exact matches come first, even if not
+ # using elasticsearch (eg. in development)
+ exact_match = Crop.approved.find_by(name: query)
+ if exact_match
+ matches.delete(exact_match)
+ matches.unshift(exact_match)
+ end
+ matches.paginate(page: page, per_page: per_page)
+ end
end
diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml
index e7b164280..ba67f1ec2 100644
--- a/app/views/admin/index.html.haml
+++ b/app/views/admin/index.html.haml
@@ -5,10 +5,12 @@
.row
.col-md-4
%h2 Site admin
+
%ul#site_admin
%li= link_to "Roles", roles_path
%li= link_to "Forums", forums_path
%li= link_to "CMS", comfy_admin_cms_path
+ %li= link_to t('.garden_types'), garden_types_path
.col-md-4
%h2 Crop data admin
diff --git a/app/views/crops/_thumbnail.html.haml b/app/views/crops/_thumbnail.html.haml
index 77793ef22..c9dfe207e 100644
--- a/app/views/crops/_thumbnail.html.haml
+++ b/app/views/crops/_thumbnail.html.haml
@@ -11,6 +11,8 @@
- unless crop.scientific_names.empty?
.scientificname
= crop.scientific_names.first.name
- .plantingcount
- Planted
- = pluralize(crop.plantings.size, "time")
+ - if crop.annual? && crop.median_lifespan.present?
+ .planting-lifespan
+ lifespan
+ %strong= crop.median_lifespan
+ days
diff --git a/app/views/crops/_varieties.html.haml b/app/views/crops/_varieties.html.haml
index 5cdc453ed..2b3407388 100644
--- a/app/views/crops/_varieties.html.haml
+++ b/app/views/crops/_varieties.html.haml
@@ -1,20 +1,5 @@
-.varieties
- - if crop.parent
- %p
- = crop.name
- is a variety of
- = succeed "." do
- = link_to crop.parent, crop.parent
-
- - unless crop.varieties.empty?
- %p
- Varieties of #{crop.name}:
-
- - max = 5
- = render partial: 'hierarchy', locals: { display_crops: [crop], max: max }
- - if max != 0 && @count > max
- = button_tag "Show all #{@count - 1} varieties", class: 'btn btn-link toggle crop-hierarchy'
- = button_tag "Show less varieties", class: 'btn btn-link toggle crop-hierarchy hide'
-
- - if !crop.parent && crop.varieties.empty?
- %p None known.
+- if crop.varieties.size.positive?
+ %h3 Varieties
+ .row
+ - crop.varieties.order(:name).each do |v|
+ .col-md-2.six-across= render 'crops/thumbnail', crop: v
\ No newline at end of file
diff --git a/app/views/crops/search.html.haml b/app/views/crops/search.html.haml
index 1d1879447..468339bc8 100644
--- a/app/views/crops/search.html.haml
+++ b/app/views/crops/search.html.haml
@@ -1,7 +1,7 @@
- if @term
- content_for :title, "Crops matching \"#{@term}\""
- - if @matches
- - content_for :subtitle, "#{@matches.size} total"
+ - if @crops
+ - content_for :subtitle, "#{@crops.size} total"
- else
- content_for :title, "Crop search"
@@ -15,7 +15,7 @@
value: @term
= submit_tag "Search", class: 'btn btn-primary'
-- if @matches.empty?
+- if @crops.empty?
%h2 No results found
%p
Sorry, we couldn't find any crops that matched your search for "#{@term}".
@@ -26,13 +26,12 @@
- else
.pagination
- = will_paginate @paginated_matches
+ = will_paginate @crops
#paginated_matches
.row
- - @paginated_matches.each do |c|
- .col-md-2.six-across
- = render partial: "thumbnail", locals: { crop: c }
+ - @crops.each do |c|
+ .col-md-2.six-across= render partial: "thumbnail", locals: { crop: c }
.pagination
- = will_paginate @paginated_matches
+ = will_paginate @crops
diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml
index 2b58de0bf..42ba16869 100644
--- a/app/views/crops/show.html.haml
+++ b/app/views/crops/show.html.haml
@@ -36,7 +36,7 @@
%h2 Photos
%p= render 'crops/photos', photos: @photos
%p= link_to 'more photos', crop_photos_path(@crop)
-
+
.row
.col-md-3
%h3 Sunniness
@@ -48,6 +48,7 @@
%h3 Harvested for
= pie_chart crop_harvested_for_path(@crop, format: :json), legend: "bottom"
+ .varieties= render 'varieties', crop: @crop
%h3 Crop Map
%p
@@ -90,8 +91,13 @@
= render 'scientific_names', crop: @crop
= render 'alternate_names', crop: @crop
- %h4 #{@crop.name.capitalize} varieties
- = render 'varieties', crop: @crop
+ - if @crop.parent
+ .parent-crop
+ = @crop.name
+ is a variety of
+ = succeed "." do
+ = link_to @crop.parent, @crop.parent
+ = render 'crops/thumbnail', crop: @crop.parent
= render 'plantings', crop: @crop
= render 'harvests', crop: @crop
diff --git a/app/views/garden_types/_actions.html.haml b/app/views/garden_types/_actions.html.haml
new file mode 100644
index 000000000..9dcf04028
--- /dev/null
+++ b/app/views/garden_types/_actions.html.haml
@@ -0,0 +1,4 @@
+.btn-group.garden_type-actions
+ = render 'shared/buttons/edit', path: edit_garden_type_path(garden_type)
+ .pull-right
+ = render 'shared/buttons/delete', path: garden_type_path(garden_type)
diff --git a/app/views/garden_types/_form.html.haml b/app/views/garden_types/_form.html.haml
new file mode 100644
index 000000000..a6d84885a
--- /dev/null
+++ b/app/views/garden_types/_form.html.haml
@@ -0,0 +1,20 @@
+= form_for @garden_type, html: { class: 'form-horizontal', role: "form" } do |f|
+ - if @garden_type.errors.any?
+ #error_explanation
+ %h2= "#{pluralize(@garden_type.errors.count, "error")} prohibited this garden_type from being saved:"
+ %ul
+ - @garden_type.errors.full_messages.each do |message|
+ %li= message
+
+ %h2 Basic information
+
+ .form-group
+ = f.label :name, class: 'control-label col-md-2'
+ .col-md-8
+ = f.text_field :name, class: 'form-control'
+ %span.help-block
+ The name for the garden_type, i.e. "organic", in English (required).
+
+ .form-group
+ .form-actions.col-md-offset-2.col-md-8
+ = f.submit 'Save', class: 'btn btn-primary'
diff --git a/app/views/garden_types/_thumbnail.html.haml b/app/views/garden_types/_thumbnail.html.haml
new file mode 100644
index 000000000..1004ac019
--- /dev/null
+++ b/app/views/garden_types/_thumbnail.html.haml
@@ -0,0 +1,7 @@
+- cache cache_key_for(GardenType, garden_type.id) do
+ .thumbnail
+ .garden_type-thumbnail
+ - if garden_type
+ .garden_typeinfo
+ .garden_typename
+ = link_to garden_type.name, garden_type
diff --git a/app/views/garden_types/edit.html.haml b/app/views/garden_types/edit.html.haml
new file mode 100644
index 000000000..1ec811b50
--- /dev/null
+++ b/app/views/garden_types/edit.html.haml
@@ -0,0 +1,4 @@
+- content_for :title, "Edit GardenType"
+
+- if can? :update, @garden_type
+ = render 'form'
diff --git a/app/views/garden_types/index.html.haml b/app/views/garden_types/index.html.haml
new file mode 100644
index 000000000..49352bc4c
--- /dev/null
+++ b/app/views/garden_types/index.html.haml
@@ -0,0 +1,17 @@
+- content_for :title, 'GardenTypes'
+
+%p
+ #{ENV['GROWSTUFF_SITE_NAME']} tracks who's growing what, where.
+ View any garden_type page to see which of our members have used it.
+
+.row
+ - @garden_types.each do |garden_type|
+ .col-md-2.six-across
+ = render partial: "thumbnail", locals: { garden_type: garden_type }
+
+- if can? :create, GardenType
+ %div
+ = link_to 'New GardenType', new_garden_type_path, class: 'btn btn-primary'
+
+.pagination
+ = will_paginate @garden_types
diff --git a/app/views/garden_types/new.html.haml b/app/views/garden_types/new.html.haml
new file mode 100644
index 000000000..a898fef65
--- /dev/null
+++ b/app/views/garden_types/new.html.haml
@@ -0,0 +1,4 @@
+- content_for :title, "New GardenType"
+
+- if can? :create, @garden_type
+ = render 'form'
diff --git a/app/views/garden_types/show.html.haml b/app/views/garden_types/show.html.haml
new file mode 100644
index 000000000..cd9575965
--- /dev/null
+++ b/app/views/garden_types/show.html.haml
@@ -0,0 +1,12 @@
+- content_for :title, @garden_type.name.capitalize
+- content_for :subtitle, @garden_type.subtitler(@garden_type)
+
+- if can?(:create, @garden_type) && can?(:edit, @garden_type) && can?(:destroy, @garden_type)
+ - content_for :buttonbar do
+ = render 'garden_types/actions', garden_type: @garden_type
+
+- if @garden_type.gardens.uniq.empty?
+ %p There are no gardens to display.
+- else
+ - @garden_type.gardens.uniq.each do |garden|
+ = render 'gardens/overview', garden: garden
diff --git a/app/views/gardens/_form.html.haml b/app/views/gardens/_form.html.haml
index 05afdb42b..b5510fad9 100644
--- a/app/views/gardens/_form.html.haml
+++ b/app/views/gardens/_form.html.haml
@@ -43,6 +43,15 @@
.col-md-2
= f.select(:area_unit, Garden::AREA_UNITS_VALUES, { include_blank: false }, class: 'form-control')
+ .form-group
+ = f.label :garden_type, class: 'control-label col-md-2'
+ .col-md-2
+ = collection_select(:garden, :garden_type_id,
+ GardenType.all.order(:name),
+ :id, :name,
+ selected: @garden.garden_type_id,
+ class: 'form-control')
+
.form-group
= f.label :active, 'Active? ', class: 'control-label col-md-2'
.col-md-8
diff --git a/app/views/plantings/_form.html.haml b/app/views/plantings/_form.html.haml
index 874b5329b..87f7ba16a 100644
--- a/app/views/plantings/_form.html.haml
+++ b/app/views/plantings/_form.html.haml
@@ -25,7 +25,7 @@
= f.label :garden_id, 'Where did you plant it?', class: 'control-label col-md-2'
.col-md-8
= collection_select(:planting, :garden_id,
- current_member.gardens.active.order("lower(gardens.name)"),
+ current_member.gardens.active.order_by_name,
:id, :name,
selected: @planting.garden_id || @garden.id,
class: 'form-control')
diff --git a/config/environments/production.rb b/config/environments/production.rb
index c99504683..3dc784029 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -89,7 +89,7 @@ Rails.application.configure do
config.active_record.dump_schema_after_migration = false
# Growstuff configuration
- config.action_mailer.default_url_options = { host: ENV['MAIL_SENDER_HOST'] }
+ config.action_mailer.default_url_options = { host: ENV['HOST'] }
config.action_mailer.smtp_settings = {
user_name: ENV['SENDGRID_USERNAME'],
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 01cab2db2..d1076dc0c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -202,6 +202,8 @@ en:
browse_members: Browse Members
community: Community
community_map: Community Map
+ garden_type: Garden Type
+ garden_types: Garden Types
crop_wrangling: Crop Wrangling
crops: Crops
current_memberlogin_name: "%{current_memberlogin_name}"
@@ -309,6 +311,7 @@ en:
planting: Please sign in or sign up to plant something.
post: Please sign in or sign up to post.
seed: Please sign in or sign up to add seeds.
+ garden_type: Not authorized. Only admins can create garden types.
manage:
all: Not authorized to %{action} %{subject}.
read:
diff --git a/config/routes.rb b/config/routes.rb
index 84886fc50..ff1687d52 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,6 +1,9 @@
Rails.application.routes.draw do
get '/robots.txt' => 'robots#robots'
+ resources :garden_types
+ resources :plant_parts
+
devise_for :members, controllers: {
registrations: "registrations",
passwords: "passwords",
diff --git a/db/migrate/20190326063855_create_garden_types.rb b/db/migrate/20190326063855_create_garden_types.rb
new file mode 100644
index 000000000..0d7ca230e
--- /dev/null
+++ b/db/migrate/20190326063855_create_garden_types.rb
@@ -0,0 +1,17 @@
+class CreateGardenTypes < ActiveRecord::Migration[5.2]
+ def change
+ create_table :garden_types do |t|
+ t.text :name, null: false, unique: true
+ t.text :slug, null: false, unique: true
+ t.timestamps null: false
+ end
+ add_column :gardens, :garden_type_id, :integer
+ add_index :gardens, :garden_type_id
+ ['organic', 'conventional', 'container', 'vertical', 'greenhouse', 'rooftop', 'no-dig', 'raised bed',
+ 'wicking bed', 'permaculture', 'hydroponic', 'aquaponic', 'orchard', 'food forest',
+ 'biodynamic'].each do |name|
+ say "Creating #{name}"
+ GardenType.create! name: name
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 5c98e630d..d0e1ac43e 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_03_17_023129) do
+ActiveRecord::Schema.define(version: 2019_03_26_063855) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -200,6 +200,13 @@ ActiveRecord::Schema.define(version: 2019_03_17_023129) do
t.index ["slug"], name: "index_forums_on_slug", unique: true
end
+ create_table "garden_types", force: :cascade do |t|
+ t.text "name", null: false
+ t.text "slug", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "gardens", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.integer "owner_id"
@@ -213,6 +220,8 @@ ActiveRecord::Schema.define(version: 2019_03_17_023129) do
t.float "longitude"
t.decimal "area"
t.string "area_unit"
+ t.integer "garden_type_id"
+ t.index ["garden_type_id"], name: "index_gardens_on_garden_type_id"
t.index ["owner_id"], name: "index_gardens_on_owner_id"
t.index ["slug"], name: "index_gardens_on_slug", unique: true
end
diff --git a/lib/tasks/search.rake b/lib/tasks/search.rake
index 7097e029c..0ac99404f 100644
--- a/lib/tasks/search.rake
+++ b/lib/tasks/search.rake
@@ -1,11 +1,6 @@
namespace :search do
- desc "Create elastic search index"
- task create: :environment do
- puts Crop.__elasticsearch__.create_index! force: true
- end
-
- desc 'Refresh elastic search index'
- task refresh: :environment do
- puts Crop.__elasticsearch__.refresh_index!
+ desc 'reindex'
+ task reindex: :environment do
+ puts Crop.reindex
end
end
diff --git a/spec/controllers/crops_controller_spec.rb b/spec/controllers/crops_controller_spec.rb
index d9dce9b9e..d4271ed5b 100644
--- a/spec/controllers/crops_controller_spec.rb
+++ b/spec/controllers/crops_controller_spec.rb
@@ -40,10 +40,21 @@ describe CropsController do
describe "GET crop search" do
describe 'fetches the crop search page' do
- before { get :search }
+ let!(:tomato) { FactoryBot.create :tomato }
+ let!(:maize) { FactoryBot.create :maize }
+ before { Crop.reindex if ENV["GROWSTUFF_ELASTICSEARCH"] == "true" }
+ describe 'search form page' do
+ before { get :search }
- it { is_expected.to be_success }
- it { is_expected.to render_template("crops/search") }
+ it { is_expected.to be_success }
+ it { is_expected.to render_template("crops/search") }
+ end
+
+ describe 'perform a search' do
+ before { get :search, params: { term: 'tom' } }
+ it { expect(assigns(:term)).to eq 'tom' }
+ it { expect(assigns(:crops).map(&:name)).to eq ['tomato'] }
+ end
end
end
diff --git a/spec/controllers/garden_types_controller_spec.rb b/spec/controllers/garden_types_controller_spec.rb
new file mode 100644
index 000000000..73e59d176
--- /dev/null
+++ b/spec/controllers/garden_types_controller_spec.rb
@@ -0,0 +1,90 @@
+require 'rails_helper'
+
+RSpec.describe GardenTypesController, type: :controller do
+ include Devise::Test::ControllerHelpers
+ let(:valid_params) { { name: 'My second GardenType' } }
+ let(:garden_type) { FactoryBot.create :garden_type }
+
+ let(:member) { FactoryBot.create(:member) }
+ let(:admin_member) { FactoryBot.create(:admin) }
+
+ context "when not signed in" do
+ describe 'GET new' do
+ before { get :new, params: { id: garden_type.to_param } }
+
+ it { expect(response).to redirect_to(root_path) }
+ end
+
+ describe 'PUT create' do
+ before { put :create, params: { garden_type: valid_params } }
+
+ it { expect(response).to redirect_to(root_path) }
+ end
+
+ describe 'changing existing records' do
+ before do
+ allow(GardenType).to receive(:find).and_return(:garden_type)
+ expect(garden_type).not_to receive(:save)
+ expect(garden_type).not_to receive(:save!)
+ expect(garden_type).not_to receive(:update)
+ expect(garden_type).not_to receive(:update!)
+ expect(garden_type).not_to receive(:destroy)
+ end
+
+ describe 'GET edit' do
+ before { get :edit, params: { id: garden_type.to_param } }
+
+ it { expect(response).to redirect_to(root_path) }
+ end
+
+ describe 'POST update' do
+ before { post :update, params: { id: garden_type.to_param, garden_type: valid_params } }
+
+ it { expect(response).to redirect_to(root_path) }
+ end
+
+ describe 'DELETE' do
+ before { delete :destroy, params: { id: garden_type.to_param, params: { garden_type: valid_params } } }
+
+ it { expect(response).to redirect_to(root_path) }
+ end
+ end
+ end
+
+ context "when signed in as a member" do
+ before { sign_in member }
+
+ let!(:member) { FactoryBot.create(:member) }
+
+ describe "for any garden_type" do
+ let(:any_garden_type) { double('garden_type') }
+
+ before do
+ expect(GardenType).to receive(:find).and_return(:any_garden_type)
+ expect(any_garden_type).not_to receive(:save)
+ expect(any_garden_type).not_to receive(:save!)
+ expect(any_garden_type).not_to receive(:update)
+ expect(any_garden_type).not_to receive(:update!)
+ expect(any_garden_type).not_to receive(:destroy)
+ end
+
+ describe 'GET edit' do
+ before { get :edit, params: { id: any_garden_type.to_param } }
+
+ it { expect(response).to redirect_to(root_path) }
+ end
+
+ describe 'POST update' do
+ before { post :update, params: { id: any_garden_type.to_param, garden_type: valid_params } }
+
+ it { expect(response).to redirect_to(root_path) }
+ end
+
+ describe 'DELETE' do
+ before { delete :destroy, params: { id: any_garden_type.to_param, params: { garden_type: valid_params } } }
+
+ it { expect(response).to redirect_to(root_path) }
+ end
+ end
+ end
+end
diff --git a/spec/factories/garden_types.rb b/spec/factories/garden_types.rb
new file mode 100644
index 000000000..942fd7932
--- /dev/null
+++ b/spec/factories/garden_types.rb
@@ -0,0 +1,5 @@
+FactoryBot.define do
+ factory :garden_type do
+ name { "homemade swamp" }
+ end
+end
diff --git a/spec/factories/photos.rb b/spec/factories/photos.rb
index 5d3ef467c..b0a64331e 100644
--- a/spec/factories/photos.rb
+++ b/spec/factories/photos.rb
@@ -4,7 +4,7 @@ FactoryBot.define do
factory :photo do
owner
flickr_photo_id { 1 }
- title { Faker::HarryPotter.quote }
+ title { Faker::Movies::HarryPotter.quote }
license_name { "CC-BY" }
license_url { "http://example.com/license.html" }
thumbnail_url { "http://example.com/#{Faker::File.file_name}.jpg" }
diff --git a/spec/features/admin/forums_spec.rb b/spec/features/admin/forums_spec.rb
index 8cfce4915..75acbbbd3 100644
--- a/spec/features/admin/forums_spec.rb
+++ b/spec/features/admin/forums_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
-feature "forums", js: true do
+describe "forums", js: true do
context "as an admin user" do
let(:member) { create :admin_member }
let(:forum) { create :forum }
- background do
+ before do
login_as member
end
- scenario "navigating to forum admin without js", js: false do
+ it "navigating to forum admin without js", js: false do
visit root_path
click_link "Admin"
expect(current_path).to eq admin_path
@@ -20,7 +20,7 @@ feature "forums", js: true do
expect(page).to have_content "New forum"
end
- scenario "navigating to forum admin with js" do
+ it "navigating to forum admin with js" do
visit root_path
click_link member.login_name
click_link "Admin"
@@ -32,7 +32,7 @@ feature "forums", js: true do
expect(page).to have_content "New forum"
end
- scenario "adding a forum" do
+ it "adding a forum" do
visit forums_path
click_link "New forum"
expect(current_path).to eq new_forum_path
@@ -43,7 +43,7 @@ feature "forums", js: true do
expect(page).to have_content 'Forum was successfully created'
end
- scenario 'editing forum' do
+ it 'editing forum' do
visit forum_path forum
click_link 'Edit'
fill_in 'Name', with: 'Something else'
@@ -54,7 +54,7 @@ feature "forums", js: true do
expect(page).to have_content 'Something else'
end
- scenario 'deleting forum' do
+ it 'deleting forum' do
visit forum_path forum
click_link 'Delete'
expect(current_path).to eq forums_path
diff --git a/spec/features/cms_spec.rb b/spec/features/cms_spec.rb
index 405f77f18..4abe7d6d4 100644
--- a/spec/features/cms_spec.rb
+++ b/spec/features/cms_spec.rb
@@ -1,16 +1,16 @@
require 'rails_helper'
-feature "cms admin" do
+describe "cms admin" do
let(:member) { create :member }
let(:admin_member) { create :admin_member }
- scenario "can't view CMS admin if not signed in" do
+ it "can't view CMS admin if not signed in" do
visit comfy_admin_cms_path
expect(current_path).to eq root_path
expect(page).to have_content "Please sign in as an admin user"
end
- scenario "can't view CMS admin if not an admin member" do
+ it "can't view CMS admin if not an admin member" do
# sign in as an ordinary member
login_as member
visit comfy_admin_cms_path
@@ -18,7 +18,7 @@ feature "cms admin" do
expect(page).to have_content "Please sign in as an admin user"
end
- scenario "admin members can view CMS admin area" do
+ it "admin members can view CMS admin area" do
login_as admin_member
visit comfy_admin_cms_path
expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page
diff --git a/spec/features/comments/commenting_a_comment_spec.rb b/spec/features/comments/commenting_a_comment_spec.rb
index 6c195e518..2ab3fa615 100644
--- a/spec/features/comments/commenting_a_comment_spec.rb
+++ b/spec/features/comments/commenting_a_comment_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
-feature 'Commenting on a post' do
+describe 'Commenting on a post' do
let(:member) { create :member }
let(:post) { create :post, author: member }
- background do
+ before do
login_as member
visit new_comment_path post_id: post.id
end
- scenario "creating a comment" do
+ it "creating a comment" do
fill_in "comment_body", with: "This is a sample test for comment"
click_button "Post comment"
expect(page).to have_content "comment was successfully created."
@@ -19,11 +19,11 @@ feature 'Commenting on a post' do
context "editing a comment" do
let(:existing_comment) { create :comment, post: post, author: member }
- background do
+ before do
visit edit_comment_path existing_comment
end
- scenario "saving edit" do
+ it "saving edit" do
fill_in "comment_body", with: "Testing edit for comment"
click_button "Post comment"
expect(page).to have_content "comment was successfully updated."
diff --git a/spec/features/crops/alternate_name_spec.rb b/spec/features/crops/alternate_name_spec.rb
index 716a26bc2..522ee8e30 100644
--- a/spec/features/crops/alternate_name_spec.rb
+++ b/spec/features/crops/alternate_name_spec.rb
@@ -1,16 +1,16 @@
require 'rails_helper'
-feature "Alternate names", js: true do
+describe "Alternate names", js: true do
let!(:alternate_eggplant) { create :alternate_eggplant }
let(:crop) { alternate_eggplant.crop }
- scenario "Display alternate names on crop page" do
+ it "Display alternate names on crop page" do
visit crop_path(alternate_eggplant.crop)
expect(page.status_code).to equal 200
expect(page).to have_content alternate_eggplant.name
end
- scenario "Index page for alternate names" do
+ it "Index page for alternate names" do
visit alternate_names_path
expect(page).to have_content alternate_eggplant.name
end
@@ -19,11 +19,11 @@ feature "Alternate names", js: true do
let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 }
let(:member) { crop_wranglers.first }
- background do
+ before do
login_as member
end
- scenario "Crop wranglers can edit alternate names" do
+ it "Crop wranglers can edit alternate names" do
visit crop_path(crop)
expect(page.status_code).to equal 200
expect(page).to have_content "CROP WRANGLER"
@@ -39,7 +39,7 @@ feature "Alternate names", js: true do
expect(page).to have_content 'Alternate name was successfully updated'
end
- scenario "Crop wranglers can delete alternate names" do
+ it "Crop wranglers can delete alternate names" do
visit crop_path(alternate_eggplant.crop)
expect(page).to have_link "Delete",
href: alternate_name_path(alternate_eggplant)
@@ -49,7 +49,7 @@ feature "Alternate names", js: true do
expect(page).to have_content 'Alternate name was successfully deleted'
end
- scenario "Crop wranglers can add alternate names" do
+ it "Crop wranglers can add alternate names" do
visit crop_path(crop)
expect(page).to have_link "Add",
href: new_alternate_name_path(crop_id: crop.id)
@@ -63,7 +63,7 @@ feature "Alternate names", js: true do
expect(page).to have_content 'Alternate name was successfully created'
end
- scenario "The show-alternate-name page works" do
+ it "The show-alternate-name page works" do
visit alternate_name_path(alternate_eggplant)
expect(page.status_code).to equal 200
expect(page).to have_content alternate_eggplant.crop.name
@@ -73,7 +73,7 @@ feature "Alternate names", js: true do
let(:rejected_crop) { create :rejected_crop }
let(:pending_alt_name) { create :alternate_name, crop: rejected_crop }
- scenario "Displays crop rejection message" do
+ it "Displays crop rejection message" do
visit alternate_name_path(pending_alt_name)
expect(page).to have_content "This crop was rejected for the following reason: Totally fake"
end
diff --git a/spec/features/crops/browse_crops_spec.rb b/spec/features/crops/browse_crops_spec.rb
index c9a6335ec..9a4c23ac3 100644
--- a/spec/features/crops/browse_crops_spec.rb
+++ b/spec/features/crops/browse_crops_spec.rb
@@ -1,28 +1,28 @@
require 'rails_helper'
-feature "browse crops" do
+describe "browse crops" do
let(:tomato) { create :tomato }
let(:maize) { create :maize }
let(:pending_crop) { create :crop_request }
let(:rejected_crop) { create :rejected_crop }
- scenario "has a form for sorting by" do
+ it "has a form for sorting by" do
visit crops_path
expect(page).to have_css "select#sort"
end
- scenario "shows a list of crops" do
+ it "shows a list of crops" do
crop1 = tomato
visit crops_path
expect(page).to have_content crop1.name
end
- scenario "pending crops are not listed" do
+ it "pending crops are not listed" do
visit crops_path
expect(page).not_to have_content pending_crop.name
end
- scenario "rejected crops are not listed" do
+ it "rejected crops are not listed" do
visit crops_path
expect(page).not_to have_content rejected_crop.name
end
diff --git a/spec/features/crops/creating_a_crop_spec.rb b/spec/features/crops/creating_a_crop_spec.rb
index 64eff3628..14dd983d2 100644
--- a/spec/features/crops/creating_a_crop_spec.rb
+++ b/spec/features/crops/creating_a_crop_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
-feature "Crop - " do
+describe "Crop - " do
let!(:crop_wrangler) { FactoryBot.create :crop_wrangling_member }
let!(:member) { FactoryBot.create :member }
- background do
+ before do
login_as member
visit new_crop_path
end
- scenario "creating a crop with multiple scientific and alternate name", :js do
+ it "creating a crop with multiple scientific and alternate name", :js do
within "form#new_crop" do
fill_in "crop_name", with: "Philippine flower"
fill_in "en_wikipedia_url", with: "https://en.wikipedia.org/wiki/Jasminum_sambac"
diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb
index 6386c7044..2c263999b 100644
--- a/spec/features/crops/crop_detail_page_spec.rb
+++ b/spec/features/crops/crop_detail_page_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-feature "crop detail page", js: true do
+describe "crop detail page", js: true do
subject do
# Update the medians after all the
# data has been loaded
@@ -14,82 +14,11 @@ feature "crop detail page", js: true do
let(:crop) { create :crop }
context "varieties" do
- scenario "The crop DOES NOT have varieties" do
+ it "The crop DOES NOT have varieties" do
visit crop_path(crop)
within ".varieties" do
- expect(page).to have_no_selector('li', text: /tomato/i)
- expect(page).to have_no_selector('button', text: /Show+/i)
- end
- end
-
- scenario "The crop has one variety" do
- create :crop, name: 'Roma tomato 1', parent: crop
-
- subject
-
- within ".varieties" do
- # It lists all 2 items (note: including the top level item.)
- expect(page).to have_selector('li', text: /tomato/i, count: 2)
- # It DOES NOT have "Show all/less" toggle link
- expect(page).to have_no_selector('button', text: /Show+/i)
- end
- end
-
- context "many" do
- let!(:roma1) { create :crop, name: 'Roma tomato 1', parent: crop }
- let!(:roma2) { create :crop, name: 'Roma tomato 2', parent: crop }
- let!(:roma3) { create :crop, name: 'Roma tomato 3', parent: crop }
- let!(:roma4) { create :crop, name: 'Roma tomato 4', parent: crop }
-
- scenario "The crop has 4 varieties" do
- subject
-
- within ".varieties" do
- # It lists all 5 items (note: including the top level item.)
- expect(page).to have_selector('li', text: /tomato/i, count: 5)
- # It DOES NOT have "Show all/less" toggle link
- expect(page).to have_no_selector('button', text: /Show+/i)
- end
- end
-
- scenario "The crop has 5 varieties, including grandchild", js: true do
- create :crop, name: 'Roma tomato child 1', parent: roma4
-
- subject
-
- within ".varieties" do
- # It lists the first 5 items (note: including the top level item.)
- # It HAS have "Show all" toggle link but not "Show less" link
- expect(page).to have_selector('li', text: /tomato/i, count: 5)
- expect(page).to have_selector('li', text: 'Roma tomato 4')
- expect(page).to have_no_selector('li', text: 'Roma tomato child 1')
- # It shows the total number (5) correctly
- expect(page).to have_selector('button', text: /Show all 5 +/i)
- expect(page).to have_no_selector('button', text: /Show less+/i)
-
- # Clik "Show all" link
- page.find('button', text: /Show all+/).click
-
- # It lists all 6 items (note: including the top level item.)
- # It HAS have "Show less" toggle link but not "Show all" link
- expect(page).to have_selector('li', text: /tomato/i, count: 6)
- expect(page).to have_selector('li', text: 'Roma tomato 4')
- expect(page).to have_selector('li', text: 'Roma tomato child 1')
- expect(page).to have_no_selector('button', text: /Show all+/i)
- expect(page).to have_selector('button', text: /Show less+/i)
-
- # Clik "Show less" link
- page.find('button', text: /Show less+/).click
-
- # It lists 5 items (note: including the top level item.)
- # It HAS have "Show all" toggle link but not "Show less" link
- expect(page).to have_selector('li', text: /tomato/i, count: 5)
- expect(page).to have_selector('li', text: 'Roma tomato 4')
- expect(page).to have_no_selector('li', text: 'Roma tomato child 1')
- expect(page).to have_selector('button', text: /Show all 5 +/i)
- expect(page).to have_no_selector('button', text: /Show less+/i)
- end
+ expect(page).not_to have_text 'tomato'
end
end
end
@@ -97,54 +26,54 @@ feature "crop detail page", js: true do
context "signed in member" do
let(:member) { create :member }
- background do
+ before do
login_as(member)
end
context "action buttons" do
- background { subject }
+ before { subject }
- scenario "has a link to plant the crop" do
+ it "has a link to plant the crop" do
expect(page).to have_link "Plant #{crop.name}", href: new_planting_path(crop_id: crop.id)
end
- scenario "has a link to harvest the crop" do
+ it "has a link to harvest the crop" do
expect(page).to have_link "Harvest #{crop.name}", href: new_harvest_path(crop_id: crop.id)
end
- scenario "has a link to add seeds" do
+ it "has a link to add seeds" do
expect(page).to have_link "Add #{crop.name} seeds to stash", href: new_seed_path(crop_id: crop.id)
end
end
context "SEO" do
- background { subject }
+ before { subject }
- scenario "has seed heading with SEO" do
+ it "has seed heading with SEO" do
expect(page).to have_content "Find #{crop.name} seeds"
end
- scenario "has harvest heading with SEO" do
+ it "has harvest heading with SEO" do
expect(page).to have_content "#{crop.name.capitalize} harvests"
end
- scenario "has planting heading with SEO" do
+ it "has planting heading with SEO" do
expect(page).to have_content "See who's planted #{crop.name.pluralize}"
end
- scenario "has planting advice with SEO" do
+ it "has planting advice with SEO" do
expect(page).to have_content "How to grow #{crop.name}"
end
- scenario "has a link to Wikipedia with SEO" do
+ it "has a link to Wikipedia with SEO" do
expect(page).to have_content "Learn more about #{crop.name}"
expect(page).to have_link "Wikipedia (English)", href: crop.en_wikipedia_url
end
- scenario "has a link to OpenFarm" do
+ it "has a link to OpenFarm" do
expect(page).to have_link "OpenFarm - Growing guide",
href: "https://openfarm.cc/en/crops/#{CGI.escape crop.name}"
end
- scenario "has a link to gardenate" do
+ it "has a link to gardenate" do
expect(page).to have_link "Gardenate - Planting reminders",
href: "http://www.gardenate.com/plant/#{CGI.escape crop.name}"
end
@@ -155,18 +84,18 @@ feature "crop detail page", js: true do
let(:member) { create :member }
let(:seed) { create :seed, crop: crop, quantity: 20, owner: member }
- scenario "User not signed in" do
+ it "User not signed in" do
visit crop_path(seed.crop)
expect(page).not_to have_content "You have 20 seeds"
end
- scenario "User signed in" do
+ it "User signed in" do
login_as(member)
visit crop_path(seed.crop)
expect(page).to have_link "You have 20 seeds of this crop."
end
- scenario "click link to your owned seeds" do
+ it "click link to your owned seeds" do
login_as(member)
visit crop_path(seed.crop)
click_link "You have 20 seeds of this crop."
@@ -190,7 +119,7 @@ feature "crop detail page", js: true do
end
it "predicts harvest" do
- is_expected.to have_text("First harvest expected 20 days after planting")
+ expect(subject).to have_text("First harvest expected 20 days after planting")
end
end
end
@@ -213,12 +142,12 @@ feature "crop detail page", js: true do
end
it "predicts lifespan" do
- is_expected.to have_text "Median lifespan"
- is_expected.to have_text "99 days"
+ expect(subject).to have_text "Median lifespan"
+ expect(subject).to have_text "99 days"
end
it "describes annual crops" do
- is_expected.to have_text(
+ expect(subject).to have_text(
"#{crop.name} is an annual crop (living and reproducing in a single year or less)"
)
end
@@ -235,7 +164,7 @@ feature "crop detail page", js: true do
end
it "describes perennial crops" do
- is_expected.to have_text("#{crop.name} is a perennial crop (living more than two years)")
+ expect(subject).to have_text("#{crop.name} is a perennial crop (living more than two years)")
end
end
diff --git a/spec/features/crops/crop_photos_spec.rb b/spec/features/crops/crop_photos_spec.rb
index 0d7d1fbee..1507a5a15 100644
--- a/spec/features/crops/crop_photos_spec.rb
+++ b/spec/features/crops/crop_photos_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-feature "crop detail page", js: true do
+describe "crop detail page", js: true do
subject { page }
let!(:member) { FactoryBot.create :member }
@@ -50,12 +50,14 @@ feature "crop detail page", js: true do
end
context "when signed in" do
- background { login_as(FactoryBot.create(:member)) }
+ before { login_as(FactoryBot.create(:member)) }
+
include_examples "shows photos"
end
context "when signed in as photos owner" do
- background { login_as(member) }
+ before { login_as(member) }
+
include_examples "shows photos"
end
diff --git a/spec/features/crops/crop_search_spec.rb b/spec/features/crops/crop_search_spec.rb
index 0cea2e168..b87655a01 100644
--- a/spec/features/crops/crop_search_spec.rb
+++ b/spec/features/crops/crop_search_spec.rb
@@ -1,7 +1,7 @@
require 'rails_helper'
-feature "crop search" do
- scenario "search results show the search term in title" do
+describe "crop search" do
+ it "search results show the search term in title" do
visit root_path
within "form#navbar-search" do
fill_in "term", with: "tomato"
@@ -10,12 +10,12 @@ feature "crop search" do
expect(page).to have_css "h1", text: "Crops matching \"tomato\""
end
- scenario "search page with no search term shows suitable title" do
+ it "search page with no search term shows suitable title" do
visit search_crops_path
expect(page).to have_css "h1", text: "Crop search"
end
- scenario "search page has a search form on it" do
+ it "search page has a search form on it" do
visit search_crops_path
expect(page).to have_css "form#crop-search"
end
diff --git a/spec/features/crops/crop_wranglers_spec.rb b/spec/features/crops/crop_wranglers_spec.rb
index f9db489b2..c623d16b6 100644
--- a/spec/features/crops/crop_wranglers_spec.rb
+++ b/spec/features/crops/crop_wranglers_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-feature "crop wranglers", js: true do
+describe "crop wranglers", js: true do
context "signed in wrangler" do
let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 }
let(:wrangler) { crop_wranglers.first }
@@ -8,9 +8,9 @@ feature "crop wranglers", js: true do
let!(:requested_crop) { create :crop_request }
let!(:rejected_crop) { create :rejected_crop }
- background { login_as wrangler }
+ before { login_as wrangler }
- scenario "sees crop wranglers listed on the crop wrangler page" do
+ it "sees crop wranglers listed on the crop wrangler page" do
visit root_path
click_link wrangler.login_name
click_link 'Crop Wrangling'
@@ -23,7 +23,7 @@ feature "crop wranglers", js: true do
end
end
- scenario "can see list of crops with extra detail of who created a crop" do
+ it "can see list of crops with extra detail of who created a crop" do
visit root_path
click_link wrangler.login_name
click_link 'Crop Wrangling'
@@ -40,7 +40,7 @@ feature "crop wranglers", js: true do
it { expect(page).to have_link 'Delete' }
end
- scenario "can create a new crop" do
+ it "can create a new crop" do
visit root_path
click_link wrangler.login_name
click_link 'Crop Wrangling'
@@ -53,13 +53,13 @@ feature "crop wranglers", js: true do
expect(page).to have_content 'planticus maximus'
end
- scenario "View pending crops" do
+ it "View pending crops" do
visit crop_path(requested_crop)
expect(page).to have_content "This crop is currently pending approval."
expect(page).to have_content "Please approve this even though it's fake."
end
- scenario "View rejected crops" do
+ it "View rejected crops" do
visit crop_path(rejected_crop)
expect(page).to have_content "This crop was rejected for the following reason: Totally fake"
end
@@ -69,14 +69,14 @@ feature "crop wranglers", js: true do
let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 }
let(:member) { create :member }
- background { login_as member }
+ before { login_as member }
- scenario "can't see wrangling page without js", js: false do
+ it "can't see wrangling page without js", js: false do
visit root_path
expect(page).not_to have_link "Crop Wrangling"
end
- scenario "can't see wrangling page with js" do
+ it "can't see wrangling page with js" do
visit root_path
click_link member.login_name
expect(page).not_to have_link "Crop Wrangling"
diff --git a/spec/features/crops/crop_wrangling_button_spec.rb b/spec/features/crops/crop_wrangling_button_spec.rb
index bf285ba66..7e9c3d8d1 100644
--- a/spec/features/crops/crop_wrangling_button_spec.rb
+++ b/spec/features/crops/crop_wrangling_button_spec.rb
@@ -1,27 +1,27 @@
require 'rails_helper'
-feature "crop wrangling button" do
+describe "crop wrangling button" do
let(:crop_wrangler) { create :crop_wrangling_member }
let(:member) { create :member }
context "crop wrangling button" do
- background do
+ before do
login_as crop_wrangler
visit crops_path
end
- scenario "has a link to crop wrangling page" do
+ it "has a link to crop wrangling page" do
expect(page).to have_link "Wrangle Crops", href: wrangle_crops_path
end
end
context "crop wrangling button" do
- background do
+ before do
login_as member
visit crops_path
end
- scenario "has no link to crop wrangling page" do
+ it "has no link to crop wrangling page" do
expect(page).to have_no_link "Wrangle Crops", href: wrangle_crops_path
end
end
diff --git a/spec/features/crops/delete_crop_spec.rb b/spec/features/crops/delete_crop_spec.rb
index f1302c784..8a25b629a 100644
--- a/spec/features/crops/delete_crop_spec.rb
+++ b/spec/features/crops/delete_crop_spec.rb
@@ -1,20 +1,20 @@
require 'rails_helper'
-feature "Delete crop spec" do
+describe "Delete crop spec" do
context "As a crop wrangler" do
let(:wrangler) { FactoryBot.create :crop_wrangling_member }
let!(:pending_crop) { FactoryBot.create :crop_request }
let!(:approved_crop) { FactoryBot.create :crop }
- background { login_as wrangler }
+ before { login_as wrangler }
- scenario "Delete approved crop" do
+ it "Delete approved crop" do
visit crop_path(approved_crop)
click_link 'Delete'
expect(page).to have_content "crop was successfully destroyed"
end
- scenario "Delete pending crop" do
+ it "Delete pending crop" do
visit crop_path(pending_crop)
click_link 'Delete'
expect(page).to have_content "crop was successfully destroyed"
diff --git a/spec/features/crops/inflections_spec.rb b/spec/features/crops/inflections_spec.rb
index 615c4c9e9..c7ca5ce37 100644
--- a/spec/features/crops/inflections_spec.rb
+++ b/spec/features/crops/inflections_spec.rb
@@ -1,10 +1,10 @@
require 'rails_helper'
-feature "irregular crop inflections" do
+describe "irregular crop inflections" do
# We're just testing a couple of representative crops to
# check that inflection works: you don't need to add
# every crop here.
- scenario "crops which are mass nouns" do
+ it "crops which are mass nouns" do
expect("kale".pluralize).to eq "kale"
expect("broccoli".pluralize).to eq "broccoli"
expect("square foot".pluralize).to eq "square feet"
@@ -26,29 +26,29 @@ feature "irregular crop inflections" do
expect("star anise".pluralize).to eq "star anise"
end
- scenario "crops which are particularly irregular" do
+ it "crops which are particularly irregular" do
expect("curry leaf".pluralize).to eq "curry leaves"
end
- scenario "crops which require -es" do
+ it "crops which require -es" do
expect("mango".pluralize).to eq "mangoes"
expect("potato".pluralize).to eq "potatoes"
end
- scenario "crops where the first crop would normally be pluralized" do
+ it "crops where the first crop would normally be pluralized" do
expect("Potato Onion".pluralize).to eq "Potato Onions"
expect("pear tomato".pluralize).to eq "pear tomatoes"
expect("chilli pepper".pluralize).to eq "chilli peppers"
end
- scenario "crops where the proper name succeeds the crop that would normally be pluralized" do
+ it "crops where the proper name succeeds the crop that would normally be pluralized" do
expect("potato Taranaki".pluralize).to eq "potato Taranaki"
expect("potato Gladstone".pluralize).to eq "potato Gladstone"
expect("potato matariki".pluralize).to eq "potato matariki"
expect("spinach Santana".pluralize).to eq "spinach Santana"
end
- scenario "crops of Māori origin" do
+ it "crops of Māori origin" do
expect("kūmara".pluralize).to eq "kūmara"
expect("pūhā".pluralize).to eq "pūhā"
end
diff --git a/spec/features/crops/request_new_crop_spec.rb b/spec/features/crops/request_new_crop_spec.rb
index 1374d1176..cd5cfb984 100644
--- a/spec/features/crops/request_new_crop_spec.rb
+++ b/spec/features/crops/request_new_crop_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
-feature "Requesting a new crop" do
+describe "Requesting a new crop" do
context "As a regular member" do
let(:member) { create :member }
let!(:wrangler) { create :crop_wrangling_member }
- background do
+ before do
login_as member
end
- scenario "Submit request" do
+ it "Submit request" do
visit new_crop_path
fill_in "Name", with: "Couch potato"
fill_in "request_notes", with: "Couch potatoes are real for real."
@@ -24,9 +24,9 @@ feature "Requesting a new crop" do
let!(:crop) { create :crop_request }
let!(:already_approved) { create :crop }
- background { login_as wrangler }
+ before { login_as wrangler }
- scenario "Approve a request" do
+ it "Approve a request" do
visit edit_crop_path(crop)
select "approved", from: "Approval status"
click_button "Save"
@@ -36,7 +36,7 @@ feature "Requesting a new crop" do
expect(page).to have_content "crop was successfully updated."
end
- scenario "Rejecting a crop" do
+ it "Rejecting a crop" do
visit edit_crop_path(crop)
select "rejected", from: "Approval status"
select "not edible", from: "Reason for rejection"
diff --git a/spec/features/crops/requested_crops_spec.rb b/spec/features/crops/requested_crops_spec.rb
index 2ab750fe7..a4e406b63 100644
--- a/spec/features/crops/requested_crops_spec.rb
+++ b/spec/features/crops/requested_crops_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
-feature "Crop - " do
+describe "Crop - " do
let(:member) { create :member }
let!(:requested_crop) { create :crop, requester: member, approval_status: 'pending', name: 'puha for dinner' }
- background do
+ before do
login_as member
visit requested_crops_path
end
- scenario "creating a crop with multiple scientific and alternate name", :js do
+ it "creating a crop with multiple scientific and alternate name", :js do
expect(page).to have_content "puha for dinner"
end
end
diff --git a/spec/features/crops/show_spec.rb b/spec/features/crops/show_spec.rb
index cc5ff75db..bfab353a4 100644
--- a/spec/features/crops/show_spec.rb
+++ b/spec/features/crops/show_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature "browse crops" do
+describe "browse crops" do
let(:tomato) { create :tomato }
let(:maize) { create :maize }
let(:pending_crop) { create :crop_request }
let(:rejected_crop) { create :rejected_crop }
- scenario "Show crop info" do
+ it "Show crop info" do
visit crop_path(tomato)
expect(page).to have_text 'tomato'
end
@@ -18,7 +18,7 @@ feature "browse crops" do
FactoryBot.create :harvest, crop: tomato, harvested_at: 60.minutes.ago, created_at: 10.minutes.ago
end
- scenario "Shows most recently harvested harvest" do
+ it "Shows most recently harvested harvest" do
visit crop_path(tomato)
expect(page).to have_link(href: harvest_path(most_recent_harvest))
end
@@ -31,7 +31,7 @@ feature "browse crops" do
FactoryBot.create :planting, crop: tomato, planted_at: 60.minutes.ago, created_at: 10.minutes.ago
end
- scenario "Shows most recently planted planting" do
+ it "Shows most recently planted planting" do
visit crop_path(tomato)
expect(page).to have_link(href: planting_path(most_recent_planting))
end
diff --git a/spec/features/following_spec.rb b/spec/features/following_spec.rb
index 0be64a4f0..762320671 100644
--- a/spec/features/following_spec.rb
+++ b/spec/features/following_spec.rb
@@ -1,10 +1,10 @@
require 'rails_helper'
-feature "follows", :js do
+describe "follows", :js do
context "when signed out" do
let(:member) { create :member }
- scenario "follow buttons on member profile page" do
+ it "follow buttons on member profile page" do
visit member_path(member)
expect(page).not_to have_link "Follow"
expect(page).not_to have_link "Unfollow"
@@ -15,36 +15,36 @@ feature "follows", :js do
let(:member) { create :member }
let(:other_member) { create :member }
- background do
+ before do
login_as(member)
end
- scenario "your profile doesn't have a follow button" do
+ it "your profile doesn't have a follow button" do
visit member_path(member)
expect(page).not_to have_link "Follow"
expect(page).not_to have_link "Unfollow"
end
context "following another member" do
- background { visit member_path(other_member) }
+ before { visit member_path(other_member) }
- scenario "has a follow button" do
+ it "has a follow button" do
expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug)
end
- scenario "has correct message and unfollow button" do
+ it "has correct message and unfollow button" do
click_link 'Follow'
expect(page).to have_content "Followed #{other_member.login_name}"
expect(page).to have_link "Unfollow", href: follow_path(member.get_follow(other_member))
end
- scenario "has a followed member listed in the following page" do
+ it "has a followed member listed in the following page" do
click_link 'Follow'
visit member_follows_path(member)
expect(page).to have_content other_member.login_name
end
- scenario "has correct message and follow button after unfollow" do
+ it "has correct message and follow button after unfollow" do
click_link 'Follow'
click_link 'Unfollow'
expect(page).to have_content "Unfollowed #{other_member.login_name}"
@@ -52,19 +52,19 @@ feature "follows", :js do
expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug)
end
- scenario "has member in following list" do
+ it "has member in following list" do
click_link 'Follow'
visit member_follows_path(member)
expect(page).to have_content other_member.login_name
end
- scenario "appears in in followed member's followers list" do
+ it "appears in in followed member's followers list" do
click_link 'Follow'
visit member_followers_path(other_member)
expect(page).to have_content member.login_name
end
- scenario "removes members from following and followers lists after unfollow" do
+ it "removes members from following and followers lists after unfollow" do
click_link 'Follow'
click_link 'Unfollow'
visit member_follows_path(member)
diff --git a/spec/features/footer_spec.rb b/spec/features/footer_spec.rb
index b7d109773..59d65b4db 100644
--- a/spec/features/footer_spec.rb
+++ b/spec/features/footer_spec.rb
@@ -1,9 +1,9 @@
require 'rails_helper'
-feature "footer", js: true do
+describe "footer", js: true do
before { visit root_path }
- scenario "footer is on home page" do
+ it "footer is on home page" do
expect(page).to have_css 'footer'
end
diff --git a/spec/features/gardens/actions_spec.rb b/spec/features/gardens/actions_spec.rb
index 98337063d..4da6b1e32 100644
--- a/spec/features/gardens/actions_spec.rb
+++ b/spec/features/gardens/actions_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
require 'custom_matchers'
-feature "Gardens" do
+describe "Gardens" do
context 'logged in' do
subject { page }
let(:member) { FactoryBot.create :member }
- background { login_as member }
+ before { login_as member }
let(:garden) { member.gardens.first }
let(:other_member_garden) { FactoryBot.create :garden }
@@ -15,9 +15,9 @@ feature "Gardens" do
shared_examples "has buttons bar at top" do
it "has buttons bar at top" do
within '.layout-actions' do
- is_expected.to have_link 'Add a garden'
- is_expected.to have_link 'My gardens'
- is_expected.to have_link "Everyone's gardens"
+ expect(subject).to have_link 'Add a garden'
+ expect(subject).to have_link 'My gardens'
+ expect(subject).to have_link "Everyone's gardens"
end
end
end
@@ -27,11 +27,11 @@ feature "Gardens" do
include_examples "has buttons bar at top"
it "has actions on garden" do
- is_expected.to have_link 'Plant something here'
- is_expected.to have_link 'Mark as inactive'
- is_expected.to have_link 'Edit'
- is_expected.to have_link 'Add photo'
- is_expected.to have_link 'Delete'
+ expect(subject).to have_link 'Plant something here'
+ expect(subject).to have_link 'Mark as inactive'
+ expect(subject).to have_link 'Edit'
+ expect(subject).to have_link 'Add photo'
+ expect(subject).to have_link 'Delete'
end
end
@@ -72,36 +72,4 @@ feature "Gardens" do
end
end
end
-
- # background do
- # login_as member
- # visit new_garden_path
- # end
-
- # it "has the required fields help text" do
- # expect(page).to have_content "* denotes a required field"
- # end
-
- # it "displays required and optional fields properly" do
- # expect(page).to have_selector ".form-group.required", text: "Name"
- # expect(page).to have_optional 'textarea#garden_description'
- # expect(page).to have_optional 'input#garden_location'
- # expect(page).to have_optional 'input#garden_area'
- # end
-
- # scenario "Create new garden" do
- # fill_in "Name", with: "New garden"
- # click_button "Save"
- # expect(page).to have_content "Garden was successfully created"
- # expect(page).to have_content "New garden"
- # end
-
- # scenario "Refuse to create new garden with negative area" do
- # visit new_garden_path
- # fill_in "Name", with: "Negative Garden"
- # fill_in "Area", with: -5
- # click_button "Save"
- # expect(page).not_to have_content "Garden was successfully created"
- # expect(page).to have_content "Area must be greater than or equal to 0"
- # end
end
diff --git a/spec/features/gardens/adding_gardens_spec.rb b/spec/features/gardens/adding_gardens_spec.rb
index c3f78dd18..437d2812f 100644
--- a/spec/features/gardens/adding_gardens_spec.rb
+++ b/spec/features/gardens/adding_gardens_spec.rb
@@ -1,10 +1,10 @@
require 'rails_helper'
require 'custom_matchers'
-feature "Gardens", :js do
+describe "Gardens", :js do
let(:member) { FactoryBot.create :member }
- background do
+ before do
login_as member
visit new_garden_path
end
@@ -20,14 +20,14 @@ feature "Gardens", :js do
expect(page).to have_optional 'input#garden_area'
end
- scenario "Create new garden" do
+ it "Create new garden" do
fill_in "Name", with: "New garden"
click_button "Save"
expect(page).to have_content "Garden was successfully created"
expect(page).to have_content "New garden"
end
- scenario "Refuse to create new garden with negative area" do
+ it "Refuse to create new garden with negative area" do
visit new_garden_path
fill_in "Name", with: "Negative Garden"
fill_in "Area", with: -5
diff --git a/spec/features/gardens/gardens_index_spec.rb b/spec/features/gardens/gardens_index_spec.rb
index b5b929df1..e14bbbc5d 100644
--- a/spec/features/gardens/gardens_index_spec.rb
+++ b/spec/features/gardens/gardens_index_spec.rb
@@ -1,11 +1,11 @@
require 'rails_helper'
require 'custom_matchers'
-feature "Gardens#index", :js do
+describe "Gardens#index", :js do
context "Logged in as member" do
let(:member) { FactoryBot.create :member, login_name: 'shadow' }
- background { login_as member }
+ before { login_as member }
context "with 10 gardens" do
before do
diff --git a/spec/features/gardens_spec.rb b/spec/features/gardens_spec.rb
index 504ecda49..816995dad 100644
--- a/spec/features/gardens_spec.rb
+++ b/spec/features/gardens_spec.rb
@@ -1,17 +1,17 @@
require 'rails_helper'
-feature "Planting a crop", js: true do
+describe "Planting a crop", js: true do
# name is aaa to ensure it is ordered first
let!(:garden) { create :garden, name: 'aaa' }
let!(:planting) { create :planting, garden: garden, owner: garden.owner, planted_at: Date.parse("2013-3-10") }
let!(:tomato) { create :tomato }
let!(:finished_planting) { create :finished_planting, owner: garden.owner, garden: garden, crop: tomato }
- background do
+ before do
login_as garden.owner
end
- scenario "View gardens" do
+ it "View gardens" do
visit gardens_path
expect(page).to have_content "Everyone's gardens"
within '.layout-actions' do
@@ -24,7 +24,7 @@ feature "Planting a crop", js: true do
expect(page).to have_content "Everyone's gardens"
end
- scenario "Marking a garden as inactive" do
+ it "Marking a garden as inactive" do
visit garden_path(garden)
click_link "Mark as inactive"
expect(page).to have_content "Garden was successfully updated"
@@ -33,14 +33,14 @@ feature "Planting a crop", js: true do
expect(page).not_to have_content "Mark as inactive"
end
- scenario "List only active gardens" do
+ it "List only active gardens" do
visit garden_path(garden)
click_link "Mark as inactive"
visit gardens_path
expect(page).not_to have_link garden_path(garden)
end
- scenario "Create new garden" do
+ it "Create new garden" do
visit new_garden_path
fill_in "Name", with: "New garden"
click_button "Save"
@@ -48,7 +48,7 @@ feature "Planting a crop", js: true do
expect(page).to have_content "New garden"
end
- scenario "Refuse to create new garden with negative area" do
+ it "Refuse to create new garden with negative area" do
visit new_garden_path
fill_in "Name", with: "Negative Garden"
fill_in "Area", with: -5
@@ -58,17 +58,17 @@ feature "Planting a crop", js: true do
end
context "Clicking edit from the index page" do
- background do
+ before do
visit gardens_path
end
- scenario "button on index to edit garden" do
+ it "button on index to edit garden" do
click_link href: edit_garden_path(garden)
expect(page).to have_content 'Edit garden'
end
end
- scenario "Edit garden" do
+ it "Edit garden" do
visit new_garden_path
fill_in "Name", with: "New garden"
click_button "Save"
@@ -81,7 +81,7 @@ feature "Planting a crop", js: true do
expect(page).to have_content "Different name"
end
- scenario "Delete garden" do
+ it "Delete garden" do
visit new_garden_path
fill_in "Name", with: "New garden"
click_button "Save"
@@ -98,7 +98,7 @@ feature "Planting a crop", js: true do
it_behaves_like "append date"
end
- scenario "List only active plantings on a garden" do
+ it "List only active plantings on a garden" do
visit gardens_path
expect(page).not_to have_content finished_planting.crop_name
end
diff --git a/spec/features/harvests/browse_harvests_spec.rb b/spec/features/harvests/browse_harvests_spec.rb
index b2409c122..1f05c5a34 100644
--- a/spec/features/harvests/browse_harvests_spec.rb
+++ b/spec/features/harvests/browse_harvests_spec.rb
@@ -1,36 +1,36 @@
require 'rails_helper'
-feature "browse harvests" do
+describe "browse harvests" do
subject { page }
let!(:member) { create :member }
let!(:harvest) { create :harvest, owner: member }
- background { login_as member }
+ before { login_as member }
- feature 'blank optional fields' do
+ describe 'blank optional fields' do
let!(:harvest) { create :harvest, :no_description }
before { visit harvests_path }
- scenario 'read more' do
- is_expected.not_to have_link "Read more"
+ it 'read more' do
+ expect(subject).not_to have_link "Read more"
end
end
- feature "filled in optional fields" do
+ describe "filled in optional fields" do
let!(:harvest) { create :harvest, :long_description }
before do
visit harvests_path
end
- scenario 'read more' do
- is_expected.to have_link "Read more"
+ it 'read more' do
+ expect(subject).to have_link "Read more"
end
it 'links to #show' do
- is_expected.to have_link harvest.crop.name, href: harvest_path(harvest)
+ expect(subject).to have_link harvest.crop.name, href: harvest_path(harvest)
end
end
end
diff --git a/spec/features/harvests/harvesting_a_crop_spec.rb b/spec/features/harvests/harvesting_a_crop_spec.rb
index f30d12baa..171d54e0b 100644
--- a/spec/features/harvests/harvesting_a_crop_spec.rb
+++ b/spec/features/harvests/harvesting_a_crop_spec.rb
@@ -1,16 +1,15 @@
require 'rails_helper'
require 'custom_matchers'
-feature "Harvesting a crop", :js, :elasticsearch do
+describe "Harvesting a crop", :js, :elasticsearch do
let(:member) { create :member }
let!(:maize) { create :maize }
let!(:plant_part) { create :plant_part }
let(:planting) { create :planting, crop: maize, owner: member }
- background do
+ before do
login_as member
visit new_harvest_path
- sync_elasticsearch [maize]
end
it_behaves_like "crop suggest", "harvest", "crop"
@@ -19,14 +18,14 @@ feature "Harvesting a crop", :js, :elasticsearch do
expect(page).to have_content "* denotes a required field"
end
- it "displays required and optional fields properly" do
- expect(page).to have_selector ".form-group.required", text: "What did you harvest?"
- expect(page).to have_optional 'input#harvest_quantity'
- expect(page).to have_optional 'input#harvest_weight_quantity'
- expect(page).to have_optional 'textarea#harvest_description'
+ describe "displays required and optional fields properly" do
+ it { expect(page).to have_selector ".form-group.required", text: "What did you harvest?" }
+ it { expect(page).to have_optional 'input#harvest_quantity' }
+ it { expect(page).to have_optional 'input#harvest_weight_quantity' }
+ it { expect(page).to have_optional 'textarea#harvest_description' }
end
- scenario "Creating a new harvest", :js do
+ it "Creating a new harvest", :js do
fill_autocomplete "crop", with: "mai"
select_from_autocomplete "maize"
@@ -45,63 +44,67 @@ feature "Harvesting a crop", :js, :elasticsearch do
context "Clicking edit from the index page" do
let!(:harvest) { create :harvest, crop: maize, owner: member }
- background do
+ before do
visit harvests_path
end
- scenario "button on index to edit harvest" do
+ it "button on index to edit harvest" do
click_link "edit_harvest_glyphicon"
expect(current_path).to eq edit_harvest_path(harvest)
expect(page).to have_content 'Editing harvest'
end
end
- scenario "Clicking link to owner's profile" do
+ it "Clicking link to owner's profile" do
visit member_harvests_path(member)
click_link "View #{member}'s profile >>"
expect(current_path).to eq member_path member
end
- scenario "Harvesting from crop page" do
- visit crop_path(maize)
- within '.crop-actions' do
- click_link "Harvest #{maize.name}"
+ describe "Harvesting from crop page" do
+ before do
+ visit crop_path(maize)
+ within '.crop-actions' do
+ click_link "Harvest #{maize.name}"
+ end
+ within "form#new_harvest" do
+ select plant_part.name, from: 'harvest[plant_part_id]'
+ expect(page).to have_selector "input[value='maize']"
+ click_button "Save"
+ end
end
- within "form#new_harvest" do
+
+ it { expect(page).to have_content "harvest was successfully created." }
+ it { expect(page).to have_content "maize" }
+ end
+
+ describe "Harvesting from planting page" do
+ let!(:planting) { create :planting, crop: maize, owner: member, garden: member.gardens.first }
+ before do
+ visit planting_path(planting)
+ within ".planting-actions" do
+ click_link "Harvest"
+ end
+
select plant_part.name, from: 'harvest[plant_part_id]'
- expect(page).to have_selector "input[value='maize']"
click_button "Save"
end
- expect(page).to have_content "harvest was successfully created."
- expect(page).to have_content "maize"
- end
-
- scenario "Harvesting from planting page" do
- planting = create :planting, crop: maize, owner: member, garden: member.gardens.first
- visit planting_path(planting)
- within ".planting-actions" do
- click_link "Harvest"
- end
-
- select plant_part.name, from: 'harvest[plant_part_id]'
- click_button "Save"
-
- expect(page).to have_content "harvest was successfully created."
- expect(page).to have_content planting.garden.name
- expect(page).to have_content "maize"
+ it { expect(page).to have_content "harvest was successfully created." }
+ it { expect(page).to have_content planting.garden.name }
+ it { expect(page).to have_content "maize" }
end
context "Editing a harvest" do
let(:existing_harvest) { create :harvest, crop: maize, owner: member }
let!(:other_plant_part) { create :plant_part, name: 'chocolate' }
- background do
+ before do
visit harvest_path(existing_harvest)
click_link "Edit"
end
- scenario "Saving without edits" do
+ it "Saving without edits" do
# Check that the autosuggest helper properly fills inputs with
# existing resource's data
click_button "Save"
@@ -109,7 +112,7 @@ feature "Harvesting a crop", :js, :elasticsearch do
expect(page).to have_content "maize"
end
- scenario "change plant part" do
+ it "change plant part" do
select other_plant_part.name, from: 'harvest[plant_part_id]'
click_button "Save"
expect(page).to have_content "harvest was successfully updated."
@@ -127,11 +130,11 @@ feature "Harvesting a crop", :js, :elasticsearch do
planted_at: Time.zone.yesterday
end
- background do
+ before do
visit harvest_path(existing_harvest)
end
- scenario "linking to a planting" do
+ it "linking to a planting" do
expect(page).to have_content existing_planting.to_s
choose("harvest_planting_id_#{existing_planting.id}")
click_button "save"
diff --git a/spec/features/home/home_spec.rb b/spec/features/home/home_spec.rb
index 7376de882..6ef612af0 100644
--- a/spec/features/home/home_spec.rb
+++ b/spec/features/home/home_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-feature "home page" do
+describe "home page" do
subject { page }
let(:member) { FactoryBot.create :member }
@@ -16,7 +16,7 @@ feature "home page" do
let!(:finished_seed) { FactoryBot.create :tradable_seed, finished: true }
let!(:untradable_seed) { FactoryBot.create :untradable_seed }
- background do
+ before do
# Add photos, so they can appear on home page
planting.photos << photo
seed.photos << photo
@@ -27,13 +27,13 @@ feature "home page" do
shared_examples 'shows seeds' do
it "show tradeable seed" do
- is_expected.to have_link href: seed_path(tradable_seed)
+ expect(subject).to have_link href: seed_path(tradable_seed)
end
it "does not show finished seeds" do
- is_expected.not_to have_link href: seed_path(finished_seed)
+ expect(subject).not_to have_link href: seed_path(finished_seed)
end
it "does not show untradable seeds" do
- is_expected.not_to have_link href: seed_path(untradable_seed)
+ expect(subject).not_to have_link href: seed_path(untradable_seed)
end
it { is_expected.to have_text 'View all seeds' }
@@ -41,14 +41,14 @@ feature "home page" do
shared_examples 'show plantings' do
it 'shows plantings section' do
- is_expected.to have_text 'Recently Planted'
- is_expected.to have_link href: planting_path(planting)
+ expect(subject).to have_text 'Recently Planted'
+ expect(subject).to have_link href: planting_path(planting)
end
end
shared_examples 'show harvests' do
it 'shows harvests section' do
- is_expected.to have_text 'Recently Harvested'
- is_expected.to have_link href: harvest_path(harvest)
+ expect(subject).to have_text 'Recently Harvested'
+ expect(subject).to have_link href: harvest_path(harvest)
end
end
@@ -61,12 +61,12 @@ feature "home page" do
describe 'shows recently added crops' do
it { is_expected.to have_text 'Recently Added' }
it 'link to newest crops' do
- is_expected.to have_link crop.name, href: crop_path(crop)
+ expect(subject).to have_link crop.name, href: crop_path(crop)
end
end
it 'includes a link to all crops' do
- is_expected.to have_link 'View all crops'
+ expect(subject).to have_link 'View all crops'
end
end
@@ -79,7 +79,8 @@ feature "home page" do
end
context "when signed in" do
- background { login_as member }
+ before { login_as member }
+
include_examples 'show crops'
include_examples 'show plantings'
include_examples 'show harvests'
diff --git a/spec/features/likeable_spec.rb b/spec/features/likeable_spec.rb
index d1b637e0d..0a39154b0 100644
--- a/spec/features/likeable_spec.rb
+++ b/spec/features/likeable_spec.rb
@@ -1,17 +1,17 @@
require 'rails_helper'
-feature 'Likeable', js: true do
+describe 'Likeable', js: true do
let(:member) { FactoryBot.create(:member) }
let(:another_member) { FactoryBot.create(:london_member) }
let(:post) { FactoryBot.create(:post) }
context 'logged in member' do
- background do
+ before do
login_as member
visit post_path(post)
end
- scenario 'can be liked' do
+ it 'can be liked' do
expect(page).to have_link 'Like'
click_link 'Like'
expect(page).to have_content '1 like'
@@ -23,7 +23,7 @@ feature 'Likeable', js: true do
expect(page).to have_content '0 likes'
end
- scenario 'displays correct number of likes' do
+ it 'displays correct number of likes' do
expect(page).to have_link 'Like'
click_link 'Like'
expect(page).to have_content '1 like'
diff --git a/spec/features/locale_spec.rb b/spec/features/locale_spec.rb
index 01d164f3c..863fac079 100644
--- a/spec/features/locale_spec.rb
+++ b/spec/features/locale_spec.rb
@@ -1,9 +1,9 @@
require 'rails_helper'
-feature "Changing locales", js: true do
+describe "Changing locales", js: true do
after { I18n.locale = :en }
- scenario "Locale can be set with a query param" do
+ it "Locale can be set with a query param" do
visit root_path
expect(page).to have_content("a community of food gardeners.")
visit root_path(locale: 'ja')
diff --git a/spec/features/member_profile_spec.rb b/spec/features/member_profile_spec.rb
index a548c7eb0..913115188 100644
--- a/spec/features/member_profile_spec.rb
+++ b/spec/features/member_profile_spec.rb
@@ -1,10 +1,10 @@
require 'rails_helper'
-feature "member profile", js: true do
+describe "member profile", js: true do
context "signed out member" do
let(:member) { create :member }
- scenario "basic details on member profile page" do
+ it "basic details on member profile page" do
visit member_path(member)
expect(page).to have_css("h1", text: member.login_name)
expect(page).to have_content member.bio
@@ -12,20 +12,20 @@ feature "member profile", js: true do
expect(page).to have_link "More about this garden...", href: garden_path(member.gardens.first)
end
- scenario "no bio" do
+ it "no bio" do
member.bio = nil
member.save
visit member_path(member)
expect(page).to have_content "hasn't written a bio yet"
end
- scenario "gravatar" do
+ it "gravatar" do
visit member_path(member)
expect(page).to have_css "img.avatar"
end
context "location" do
- scenario "member has set location" do
+ it "member has set location" do
london_member = create :london_member
visit member_path(london_member)
expect(page).to have_css("h1>small", text: london_member.location)
@@ -33,7 +33,7 @@ feature "member profile", js: true do
expect(page).to have_content "See other members, plantings, seeds and more near #{london_member.location}"
end
- scenario "member has not set location" do
+ it "member has not set location" do
visit member_path(member)
expect(page).not_to have_css("h1>small")
expect(page).not_to have_css("#membermap")
@@ -42,31 +42,31 @@ feature "member profile", js: true do
end
context "email privacy" do
- scenario "public email address" do
+ it "public email address" do
public_member = create :public_member
visit member_path(public_member)
expect(page).to have_content public_member.email
end
- scenario "private email address" do
+ it "private email address" do
visit member_path(member)
expect(page).not_to have_content member.email
end
end
context "email privacy" do
- scenario "public email address" do
+ it "public email address" do
public_member = create :public_member
visit member_path(public_member)
expect(page).to have_content public_member.email
end
- scenario "private email address" do
+ it "private email address" do
visit member_path(member)
expect(page).not_to have_content member.email
end
end
context "activity stats" do
- scenario "with no activity" do
+ it "with no activity" do
visit member_path(member)
expect(page).to have_content "Activity"
expect(page).to have_content "0 plantings"
@@ -75,7 +75,7 @@ feature "member profile", js: true do
expect(page).to have_content "0 posts"
end
- scenario "with some activity" do
+ it "with some activity" do
create_list :planting, 2, owner: member
create_list :harvest, 3, owner: member
create_list :seed, 4, owner: member
@@ -88,13 +88,13 @@ feature "member profile", js: true do
end
end
- scenario "twitter link" do
+ it "twitter link" do
twitter_auth = create :authentication, member: member
visit member_path(member)
expect(page).to have_link twitter_auth.name, href: "http://twitter.com/#{twitter_auth.name}"
end
- scenario "flickr link" do
+ it "flickr link" do
flickr_auth = create :flickr_authentication, member: member
visit member_path(member)
expect(page).to have_link flickr_auth.name, href: "http://flickr.com/photos/#{flickr_auth.uid}"
@@ -107,56 +107,56 @@ feature "member profile", js: true do
let(:admin_member) { create :admin_member }
let(:crop_wrangler) { create :crop_wrangling_member }
- background do
+ before do
login_as(member)
end
- scenario "admin user's page" do
+ it "admin user's page" do
visit member_path(admin_member)
expect(page).to have_text "Admin"
end
- scenario "crop wrangler's page" do
+ it "crop wrangler's page" do
visit member_path(crop_wrangler)
expect(page).to have_text "Crop Wrangler"
end
- scenario "ordinary user's page" do
+ it "ordinary user's page" do
visit member_path(other_member)
expect(page).not_to have_text "Crop Wrangler"
expect(page).not_to have_text "Admin"
end
context "your own profile page" do
- background do
+ before do
visit member_path(member)
end
- scenario "has a link to create new garden" do
+ it "has a link to create new garden" do
expect(page).to have_link "New Garden", href: new_garden_path
end
- scenario "has a button to edit profile" do
+ it "has a button to edit profile" do
expect(page).to have_link "Edit profile", href: edit_member_registration_path
end
end
context "someone else's profile page" do
- background do
+ before do
visit member_path(other_member)
end
- scenario "has a private message button" do
+ it "has a private message button" do
expect(page).to have_link "Send message", href: new_notification_path(recipient_id: other_member.id)
end
end
context "home page" do
- background do
+ before do
visit root_path
end
- scenario "does not have a button to edit profile" do
+ it "does not have a button to edit profile" do
expect(page).not_to have_link "Edit profile", href: edit_member_registration_path
end
end
diff --git a/spec/features/members/deletion_spec.rb b/spec/features/members/deletion_spec.rb
index 3c392cb4c..6cf074f1a 100644
--- a/spec/features/members/deletion_spec.rb
+++ b/spec/features/members/deletion_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-feature "member deletion" do
+describe "member deletion" do
context "with activity and followers" do
let(:member) { FactoryBot.create(:member) }
let(:other_member) { FactoryBot.create(:member) }
@@ -12,7 +12,7 @@ feature "member deletion" do
let!(:secondgarden) { FactoryBot.create(:garden, owner: member) }
let(:admin) { FactoryBot.create(:admin_member) }
- background do
+ before do
login_as(member)
visit member_path(other_member)
click_link 'Follow'
@@ -30,13 +30,13 @@ feature "member deletion" do
FactoryBot.create(:member, login_name: "ex_member")
end
- scenario "has option to delete on member profile page" do
+ it "has option to delete on member profile page" do
visit member_path(member)
click_link 'Edit profile'
expect(page).to have_link "Delete Account"
end
- scenario "asks for password before deletion" do
+ it "asks for password before deletion" do
visit member_path(member)
click_link 'Edit profile'
click_link 'Delete Account'
@@ -44,7 +44,7 @@ feature "member deletion" do
expect(page).to have_content "Current password can't be blank"
end
- scenario "password must be correct" do
+ it "password must be correct" do
visit member_path(member)
click_link 'Edit profile'
click_link 'Delete Account'
@@ -53,7 +53,7 @@ feature "member deletion" do
expect(page).to have_content "Current password is invalid"
end
- scenario "deletes and removes bio" do
+ it "deletes and removes bio" do
visit member_path(member)
click_link 'Edit profile'
click_link 'Delete Account'
@@ -64,7 +64,7 @@ feature "member deletion" do
end
context "deletes and" do
- background do
+ before do
logout
login_as(member)
visit member_path(member)
@@ -79,39 +79,39 @@ feature "member deletion" do
it { expect(Member.with_deleted.find(member.id)).to eq member }
end
- scenario "removes plantings" do
+ it "removes plantings" do
visit planting_path(planting)
expect(page.status_code).to eq(404)
end
- scenario "removes gardens" do
+ it "removes gardens" do
visit garden_path(secondgarden)
expect(page.status_code).to eq(404)
end
- scenario "removes harvests and seeds" do
+ it "removes harvests and seeds" do
visit harvest_path(harvest)
expect(page.status_code).to eq(404)
end
- scenario "removes seeds" do
+ it "removes seeds" do
visit seed_path(seed)
expect(page.status_code).to eq(404)
end
- scenario "removes members from following" do
+ it "removes members from following" do
visit member_follows_path(other_member)
expect(page).not_to have_content member.login_name.to_s
visit member_followers_path(other_member)
expect(page).not_to have_content member.login_name.to_s
end
- scenario "replaces posts with deletion note" do
+ it "replaces posts with deletion note" do
visit post_path(memberpost)
expect(page.status_code).to eq(404)
end
- scenario "replaces comments on others' posts with deletion note, leaving post intact" do
+ it "replaces comments on others' posts with deletion note, leaving post intact" do
FactoryBot.create :comment, post: othermemberpost, author: member, body: 'i am deleting my account'
visit post_path(othermemberpost)
@@ -120,7 +120,7 @@ feature "member deletion" do
expect(page).to have_content "Member Deleted"
end
- scenario "can't be interesting" do
+ it "can't be interesting" do
expect(Member.interesting).not_to include(member)
expect(Planting.interesting).not_to include(planting)
expect(Seed.interesting).not_to include(seed)
@@ -128,7 +128,7 @@ feature "member deletion" do
pending "doesn't show in nearby"
- scenario "can no longer sign in" do
+ it "can no longer sign in" do
visit new_member_session_path
fill_in 'Login', with: member.login_name
fill_in 'Password', with: member.password
@@ -145,7 +145,7 @@ feature "member deletion" do
FactoryBot.create(:cropbot)
let!(:ex_wrangler) { FactoryBot.create(:crop_wrangling_member, login_name: "ex_wrangler") }
- scenario "leaves crops behind" do
+ it "leaves crops behind" do
login_as(otherwrangler)
visit edit_crop_path(crop)
expect(page).to have_content member.login_name
diff --git a/spec/features/members_list_spec.rb b/spec/features/members_list_spec.rb
index 184efbfb6..9523b6238 100644
--- a/spec/features/members_list_spec.rb
+++ b/spec/features/members_list_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature "members list" do
+describe "members list" do
context "list all members" do
let!(:member1) { create :member, login_name: "Archaeopteryx", confirmed_at: Time.zone.parse('2013-02-10') }
let!(:member2) { create :member, login_name: "Zephyrosaurus", confirmed_at: Time.zone.parse('2014-01-11') }
let!(:member3) { create :member, login_name: "Testingname", confirmed_at: Time.zone.parse('2014-05-09') }
- scenario "default alphabetical sort" do
+ it "default alphabetical sort" do
visit members_path
expect(page).to have_css "#sort"
expect(page).to have_selector "form"
@@ -16,7 +16,7 @@ feature "members list" do
expect(all_links.last).to have_text member2.login_name
end
- scenario "recently joined sort" do
+ it "recently joined sort" do
visit members_path
expect(page).to have_css "#sort"
expect(page).to have_selector "form"
diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb
index a5c544552..347d27627 100644
--- a/spec/features/notifications_spec.rb
+++ b/spec/features/notifications_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-feature "Notifications", :js do
+describe "Notifications", :js do
let(:sender) { create :member }
let(:recipient) { create :member, login_name: 'beyonce' }
@@ -13,12 +13,12 @@ feature "Notifications", :js do
post_id: nil
end
- background do
+ before do
login_as recipient
visit notification_path(notification)
end
- scenario "Replying to the notification" do
+ it "Replying to the notification" do
click_link "Reply"
expect(page).to have_content "Notification body"
diff --git a/spec/features/photos/new_photo_spec.rb b/spec/features/photos/new_photo_spec.rb
index 3c486fa5b..71cdfc198 100644
--- a/spec/features/photos/new_photo_spec.rb
+++ b/spec/features/photos/new_photo_spec.rb
@@ -1,17 +1,17 @@
require 'rails_helper'
-feature "new photo page" do
+describe "new photo page" do
let(:photo) { FactoryBot.create :photo }
context "signed in member" do
let(:member) { FactoryBot.create :member }
- background { login_as member }
+ before { login_as member }
context "viewing a planting" do
let(:planting) { FactoryBot.create :planting, owner: member }
- scenario "add photo" do
+ it "add photo" do
visit planting_path(planting)
within '.planting-actions' do
click_link('Add photo')
@@ -23,7 +23,7 @@ feature "new photo page" do
context "viewing a harvest" do
let(:harvest) { FactoryBot.create :harvest, owner: member }
- scenario "add photo" do
+ it "add photo" do
visit harvest_path(harvest)
within '.harvest-actions' do
click_link "Add photo"
@@ -35,7 +35,7 @@ feature "new photo page" do
context "viewing a garden" do
let(:garden) { FactoryBot.create :garden, owner: member }
- scenario "add photo" do
+ it "add photo" do
visit garden_path(garden)
within '.garden-actions' do
click_link "Add photo"
@@ -47,7 +47,7 @@ feature "new photo page" do
describe "viewing a seed" do
let(:seed) { FactoryBot.create :seed, owner: member }
- scenario "add photo" do
+ it "add photo" do
visit seed_path(seed)
first('.seed-actions').click_link('Add photo')
expect(page).to have_text seed.to_s
diff --git a/spec/features/photos/show_photo_spec.rb b/spec/features/photos/show_photo_spec.rb
index 973aa349a..a8d2ff802 100644
--- a/spec/features/photos/show_photo_spec.rb
+++ b/spec/features/photos/show_photo_spec.rb
@@ -1,10 +1,10 @@
require 'rails_helper'
-feature "show photo page" do
+describe "show photo page" do
context "signed in member" do
let(:member) { create :member }
- background { login_as member }
+ before { login_as member }
context "linked to planting" do
let(:planting) { create :planting }
diff --git a/spec/features/places/searching_a_place_spec.rb b/spec/features/places/searching_a_place_spec.rb
index 7a2d12898..29e49ce21 100644
--- a/spec/features/places/searching_a_place_spec.rb
+++ b/spec/features/places/searching_a_place_spec.rb
@@ -1,13 +1,13 @@
require "rails_helper"
-feature "User searches" do
+describe "User searches" do
let(:member) { create :member, location: "Philippines" }
let!(:maize) { create :maize }
let(:garden) { create :garden, owner: member }
let!(:seed1) { create :seed, owner: member }
let!(:planting) { create :planting, garden: garden, owner: member, planted_at: Date.parse("2013-3-10") }
- scenario "with a valid place" do
+ it "with a valid place" do
visit places_path
search_with "Philippines"
expect(page).to have_content "community near Philippines"
@@ -16,7 +16,7 @@ feature "User searches" do
expect(page).not_to have_content "No results found"
end
- scenario "with a blank search string" do
+ it "with a blank search string" do
visit places_path
search_with ""
expect(page).to have_content "Please enter a valid location"
diff --git a/spec/features/planting_reminder_spec.rb b/spec/features/planting_reminder_spec.rb
index e13803182..1b8fe7a37 100644
--- a/spec/features/planting_reminder_spec.rb
+++ b/spec/features/planting_reminder_spec.rb
@@ -1,7 +1,7 @@
require 'rails_helper'
require 'capybara/email/rspec'
-feature "Planting reminder email", :js do
+describe "Planting reminder email", :js do
let(:member) { create :member }
let(:mail) { Notifier.planting_reminder(member) }
@@ -11,16 +11,16 @@ feature "Planting reminder email", :js do
{ host: 'localhost', port: 8080 }
end
- scenario "has a greeting" do
+ it "has a greeting" do
expect(mail).to have_content "Hello"
end
context "when member has no plantings" do
- scenario "tells you to track your plantings" do
+ it "tells you to track your plantings" do
expect(mail).to have_content "planting your first crop"
end
- scenario "doesn't list plantings" do
+ it "doesn't list plantings" do
expect(mail).not_to have_content "most recent plantings you've told us about"
end
end
@@ -31,7 +31,7 @@ feature "Planting reminder email", :js do
let!(:p1) { create :planting, garden: member.gardens.first, owner: member }
let!(:p2) { create :planting, garden: member.gardens.first, owner: member }
- scenario "lists plantings" do
+ it "lists plantings" do
expect(mail).to have_content "most recent plantings you've told us about"
expect(mail).to have_link p1.to_s, href: planting_url(p1)
expect(mail).to have_link p2.to_s, href: planting_url(p2)
@@ -40,11 +40,11 @@ feature "Planting reminder email", :js do
end
context "when member has no harvests" do
- scenario "tells you to tracking plantings" do
+ it "tells you to tracking plantings" do
expect(mail).to have_content "Get started now by tracking your first harvest"
end
- scenario "doesn't list plantings" do
+ it "doesn't list plantings" do
expect(mail).not_to have_content "the last few things you harvested were"
end
end
@@ -55,7 +55,7 @@ feature "Planting reminder email", :js do
let!(:h1) { create :harvest, owner: member }
let!(:h2) { create :harvest, owner: member }
- scenario "lists harvests" do
+ it "lists harvests" do
expect(mail).to have_content "the last few things you harvested were"
expect(mail).to have_link h1.to_s, href: harvest_url(h1)
expect(mail).to have_link h2.to_s, href: harvest_url(h2)
diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb
index 8cb70fc5a..f5df9f4b7 100644
--- a/spec/features/plantings/planting_a_crop_spec.rb
+++ b/spec/features/plantings/planting_a_crop_spec.rb
@@ -1,7 +1,7 @@
require "rails_helper"
require 'custom_matchers'
-feature "Planting a crop", :js, :elasticsearch do
+describe "Planting a crop", :js, :elasticsearch do
let(:member) { FactoryBot.create :member }
let!(:maize) { FactoryBot.create :maize }
let(:garden) { FactoryBot.create :garden, owner: member }
@@ -9,10 +9,9 @@ feature "Planting a crop", :js, :elasticsearch do
FactoryBot.create :planting, garden: garden, owner: member, planted_at: Date.parse("2013-03-10")
end
- background do
+ before do
login_as member
visit new_planting_path
- sync_elasticsearch [maize]
end
it_behaves_like "crop suggest", "planting"
@@ -32,26 +31,30 @@ feature "Planting a crop", :js, :elasticsearch do
it { expect(page).to have_optional 'input#planting_finished_at' }
end
- scenario "Creating a new planting" do
- fill_autocomplete "crop", with: "mai"
- select_from_autocomplete "maize"
- within "form#new_planting" do
- fill_in "When", with: "2014-06-15"
- fill_in "How many?", with: 42
- select "cutting", from: "Planted from:"
- select "semi-shade", from: "Sun or shade?"
- fill_in "Tell us more about it", with: "It's rad."
- click_button "Save"
+ describe "Creating a new planting" do
+ before do
+ fill_autocomplete "crop", with: "mai"
+ select_from_autocomplete "maize"
+ within "form#new_planting" do
+ fill_in "When", with: "2014-06-15"
+ fill_in "How many?", with: 42
+ select "cutting", from: "Planted from:"
+ select "semi-shade", from: "Sun or shade?"
+ fill_in "Tell us more about it", with: "It's rad."
+ click_button "Save"
+ end
end
- expect(page).to have_content "planting was successfully created"
- expect(page).to have_content "Not enough data"
+ it { expect(page).to have_content "planting was successfully created" }
+ it { expect(page).to have_content "Not enough data" }
end
- scenario "Clicking link to owner's profile" do
- visit member_plantings_path(member)
- click_link "View #{member}'s profile >>"
- expect(current_path).to eq member_path(member)
+ describe "Clicking link to owner's profile" do
+ before do
+ visit member_plantings_path(member)
+ click_link "View #{member}'s profile >>"
+ end
+ it { expect(current_path).to eq member_path(member) }
end
describe "Progress bar status on planting creation" do
@@ -151,7 +154,7 @@ feature "Planting a crop", :js, :elasticsearch do
end
end
- scenario "Planting from crop page" do
+ it "Planting from crop page" do
visit crop_path(maize)
within '.crop-actions' do
click_link "Plant maize"
@@ -165,7 +168,7 @@ feature "Planting a crop", :js, :elasticsearch do
expect(page).to have_content "maize"
end
- scenario "Editing a planting to add details" do
+ it "Editing a planting to add details" do
visit planting_path(planting)
click_link "Edit"
fill_in "Tell us more about it", with: "Some extra notes"
@@ -173,7 +176,7 @@ feature "Planting a crop", :js, :elasticsearch do
expect(page).to have_content "planting was successfully updated"
end
- scenario "Editing a planting to fill in the finished date" do
+ it "Editing a planting to fill in the finished date" do
visit planting_path(planting)
expect(page).to have_content "Not enough data"
click_link "Edit"
@@ -184,7 +187,7 @@ feature "Planting a crop", :js, :elasticsearch do
expect(page).not_to have_content "Not enough data"
end
- scenario "Marking a planting as finished" do
+ it "Marking a planting as finished" do
fill_autocomplete "crop", with: "mai"
select_from_autocomplete "maize"
within "form#new_planting" do
diff --git a/spec/features/posts/posting_a_post_spec.rb b/spec/features/posts/posting_a_post_spec.rb
index ac31b6fec..7467517c5 100644
--- a/spec/features/posts/posting_a_post_spec.rb
+++ b/spec/features/posts/posting_a_post_spec.rb
@@ -1,14 +1,14 @@
require 'rails_helper'
-feature 'Post a post' do
+describe 'Post a post' do
let(:member) { create :member }
- background do
+ before do
login_as member
visit new_post_path
end
- scenario "creating a post" do
+ it "creating a post" do
fill_in "post_subject", with: "Testing"
fill_in "post_body", with: "This is a sample test"
click_button "Post"
@@ -19,11 +19,11 @@ feature 'Post a post' do
context "editing a post" do
let(:existing_post) { create :post, author: member }
- background do
+ before do
visit edit_post_path(existing_post)
end
- scenario "saving edit" do
+ it "saving edit" do
fill_in "post_subject", with: "Testing Edit"
click_button "Post"
expect(page).to have_content "Post was successfully updated"
diff --git a/spec/features/rss/comments_spec.rb b/spec/features/rss/comments_spec.rb
index f053a7e26..fef92010a 100644
--- a/spec/features/rss/comments_spec.rb
+++ b/spec/features/rss/comments_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature 'Comments RSS feed' do
- scenario 'The index feed exists' do
+describe 'Comments RSS feed' do
+ it 'The index feed exists' do
visit comments_path(format: 'rss')
expect(page.status_code).to equal 200
end
- scenario 'The index title is what we expect' do
+ it 'The index title is what we expect' do
visit comments_path(format: 'rss')
expect(page).to have_content "Recent comments on all posts (#{ENV['GROWSTUFF_SITE_NAME']})"
end
diff --git a/spec/features/rss/crops_spec.rb b/spec/features/rss/crops_spec.rb
index ef45af20b..80ca34b29 100644
--- a/spec/features/rss/crops_spec.rb
+++ b/spec/features/rss/crops_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature 'Crops RSS feed' do
- scenario 'The index feed exists' do
+describe 'Crops RSS feed' do
+ it 'The index feed exists' do
visit crops_path(format: 'rss')
expect(page.status_code).to equal 200
end
- scenario 'The index title is what we expect' do
+ it 'The index title is what we expect' do
visit crops_path(format: 'rss')
expect(page).to have_content "Recently added crops (#{ENV['GROWSTUFF_SITE_NAME']})"
end
diff --git a/spec/features/rss/members_spec.rb b/spec/features/rss/members_spec.rb
index 3849f9d80..8bf13b3c5 100644
--- a/spec/features/rss/members_spec.rb
+++ b/spec/features/rss/members_spec.rb
@@ -1,14 +1,14 @@
require 'rails_helper'
-feature 'Members RSS feed' do
+describe 'Members RSS feed' do
let(:member) { create :member }
- scenario 'The show action exists' do
+ it 'The show action exists' do
visit member_path(member, format: 'rss')
expect(page.status_code).to equal 200
end
- scenario 'The show action title is what we expect' do
+ it 'The show action title is what we expect' do
visit member_path(member, format: 'rss')
expect(page).to have_content "#{member.login_name}'s recent posts (#{ENV['GROWSTUFF_SITE_NAME']})"
end
diff --git a/spec/features/rss/plantings_spec.rb b/spec/features/rss/plantings_spec.rb
index c3f68fea6..7624c22c0 100644
--- a/spec/features/rss/plantings_spec.rb
+++ b/spec/features/rss/plantings_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature 'Plantings RSS feed' do
- scenario 'The index feed exists' do
+describe 'Plantings RSS feed' do
+ it 'The index feed exists' do
visit plantings_path(format: 'rss')
expect(page.status_code).to equal 200
end
- scenario 'The index title is what we expect' do
+ it 'The index title is what we expect' do
visit plantings_path(format: 'rss')
expect(page).to have_content "Recent plantings from "\
"#{@owner || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})"
diff --git a/spec/features/rss/posts_spec.rb b/spec/features/rss/posts_spec.rb
index 668276fbb..93797c7bc 100644
--- a/spec/features/rss/posts_spec.rb
+++ b/spec/features/rss/posts_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature 'Posts RSS feed' do
- scenario 'The index feed exists' do
+describe 'Posts RSS feed' do
+ it 'The index feed exists' do
visit posts_path(format: 'rss')
expect(page.status_code).to equal 200
end
- scenario 'The index title is what we expect' do
+ it 'The index title is what we expect' do
visit posts_path(format: 'rss')
expect(page).to have_content "Recent posts from "\
"#{@author || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})"
diff --git a/spec/features/rss/seeds_spec.rb b/spec/features/rss/seeds_spec.rb
index abb66e7e3..5ae25949e 100644
--- a/spec/features/rss/seeds_spec.rb
+++ b/spec/features/rss/seeds_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature 'Seeds RSS feed' do
- scenario 'The index feed exists' do
+describe 'Seeds RSS feed' do
+ it 'The index feed exists' do
visit seeds_path(format: 'rss')
expect(page.status_code).to equal 200
end
- scenario 'The index title is what we expect' do
+ it 'The index title is what we expect' do
visit seeds_path(format: 'rss')
expect(page).to have_content "Recent seeds from "\
"#{@owner || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})"
diff --git a/spec/features/scientific_name_spec.rb b/spec/features/scientific_name_spec.rb
index 3844a3a07..00563deb6 100644
--- a/spec/features/scientific_name_spec.rb
+++ b/spec/features/scientific_name_spec.rb
@@ -1,16 +1,16 @@
require 'rails_helper'
-feature "Scientific names", js: true do
+describe "Scientific names", js: true do
let!(:zea_mays) { create :zea_mays }
let(:crop) { zea_mays.crop }
- scenario "Display scientific names on crop page" do
+ it "Display scientific names on crop page" do
visit crop_path(zea_mays.crop)
expect(page.status_code).to equal 200
expect(page).to have_content zea_mays.name
end
- scenario "Index page for scientific names" do
+ it "Index page for scientific names" do
visit scientific_names_path
expect(page.status_code).to equal 200
expect(page).to have_content zea_mays.name
@@ -20,11 +20,11 @@ feature "Scientific names", js: true do
let!(:crop_wranglers) { create_list :crop_wrangling_member, 3 }
let(:member) { crop_wranglers.first }
- background do
+ before do
login_as(member)
end
- scenario "Crop wranglers can edit scientific names" do
+ it "Crop wranglers can edit scientific names" do
visit crop_path(crop)
expect(page.status_code).to equal 200
expect(page).to have_content "CROP WRANGLER"
@@ -39,7 +39,7 @@ feature "Scientific names", js: true do
expect(page).to have_content 'crop was successfully updated'
end
- scenario "Crop wranglers can delete scientific names" do
+ it "Crop wranglers can delete scientific names" do
visit crop_path(zea_mays.crop)
expect(page).to have_link "Delete",
href: scientific_name_path(zea_mays)
@@ -49,7 +49,7 @@ feature "Scientific names", js: true do
expect(page).to have_content 'Scientific name was successfully deleted.'
end
- scenario "Crop wranglers can add scientific names" do
+ it "Crop wranglers can add scientific names" do
visit crop_path(crop)
expect(page).to have_link "Add",
href: new_scientific_name_path(crop_id: crop.id)
@@ -63,7 +63,7 @@ feature "Scientific names", js: true do
expect(page).to have_content 'crop was successfully created.'
end
- scenario "The show-scientific-name page works" do
+ it "The show-scientific-name page works" do
visit scientific_name_path(zea_mays)
expect(page.status_code).to equal 200
expect(page).to have_link zea_mays.crop.name,
@@ -74,7 +74,7 @@ feature "Scientific names", js: true do
let(:pending_crop) { create :crop_request }
let(:pending_sci_name) { create :scientific_name, crop: pending_crop }
- scenario "Displays crop pending message" do
+ it "Displays crop pending message" do
visit scientific_name_path(pending_sci_name)
expect(page).to have_content "This crop is currently pending approval"
end
diff --git a/spec/features/seeds/adding_seeds_spec.rb b/spec/features/seeds/adding_seeds_spec.rb
index 2964a5ab3..e407c3782 100644
--- a/spec/features/seeds/adding_seeds_spec.rb
+++ b/spec/features/seeds/adding_seeds_spec.rb
@@ -1,14 +1,13 @@
require 'rails_helper'
require 'custom_matchers'
-feature "Seeds", :js, :elasticsearch do
+describe "Seeds", :js, :elasticsearch do
let(:member) { create :member }
let!(:maize) { create :maize }
- background do
+ before do
login_as member
visit new_seed_path
- sync_elasticsearch [maize]
end
it_behaves_like "crop suggest", "seed", "crop"
diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb
index e7c1e0291..0d75dc3c4 100644
--- a/spec/features/seeds/misc_seeds_spec.rb
+++ b/spec/features/seeds/misc_seeds_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature "seeds", js: true do
+describe "seeds", js: true do
let(:member) { create :member }
context "signed in user" do
let(:crop) { create :crop }
- background { login_as member }
+ before { login_as member }
describe "button on index to edit seed" do
let!(:seed) { create :seed, owner: member }
@@ -41,7 +41,7 @@ feature "seeds", js: true do
# actually adding seeds is in spec/features/seeds_new_spec.rb
- scenario "edit seeds" do
+ it "edit seeds" do
seed = create :seed, owner: member
visit seed_path(seed)
click_link 'Edit'
diff --git a/spec/features/seeds/seed_photos.rb b/spec/features/seeds/seed_photos.rb
index 60746d98b..d1eacdd7f 100644
--- a/spec/features/seeds/seed_photos.rb
+++ b/spec/features/seeds/seed_photos.rb
@@ -1,7 +1,7 @@
require 'rails_helper'
require 'custom_matchers'
-feature "Seeds", :js do
+describe "Seeds", :js do
subject do
login_as member
visit seed_path(seed)
@@ -31,16 +31,16 @@ feature "Seeds", :js do
let!(:photos) { FactoryBot.create_list :photo, 50 }
it "shows newest photo" do
- is_expected.to have_xpath("//img[contains(@src,'#{photos.last.thumbnail_url}')]")
+ expect(subject).to have_xpath("//img[contains(@src,'#{photos.last.thumbnail_url}')]")
end
it "links to newest photo" do
- is_expected.to have_xpath("//a[contains(@href,'#{photo_path(photos.last)}')]")
+ expect(subject).to have_xpath("//a[contains(@href,'#{photo_path(photos.last)}')]")
end
it "does not show oldest photo" do
- is_expected.not_to have_xpath("//img[contains(@src,'#{photos.first.thumbnail_url}')]")
+ expect(subject).not_to have_xpath("//img[contains(@src,'#{photos.first.thumbnail_url}')]")
end
it "does not link to oldest photo" do
- is_expected.not_to have_xpath("//a[contains(@href,'#{photo_path(photos.first)}')]")
+ expect(subject).not_to have_xpath("//a[contains(@href,'#{photo_path(photos.first)}')]")
end
end
end
diff --git a/spec/features/shared_examples/append_date.rb b/spec/features/shared_examples/append_date.rb
index 843730ff7..85b576a75 100644
--- a/spec/features/shared_examples/append_date.rb
+++ b/spec/features/shared_examples/append_date.rb
@@ -2,7 +2,7 @@ shared_examples "append date" do
let(:this_month) { Time.zone.today.strftime("%B") }
let(:this_year) { Time.zone.today.strftime("%Y") }
- background { visit path }
+ before { visit path }
scenario "Selecting a date with datepicker" do
click_link link_text
diff --git a/spec/features/shared_examples/crop_suggest.rb b/spec/features/shared_examples/crop_suggest.rb
index b646ba7df..b7e49dbd8 100644
--- a/spec/features/shared_examples/crop_suggest.rb
+++ b/spec/features/shared_examples/crop_suggest.rb
@@ -6,8 +6,6 @@ shared_examples "crop suggest" do |resource|
let!(:tomato) { create :tomato }
let!(:roma) { create :roma }
- background { sync_elasticsearch [pea, pear, maize, tomato] }
-
scenario "placeholder text in crop auto suggest field" do
expect(page).to have_selector("input[placeholder='e.g. lettuce']")
end
diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb
index 07fd6a130..4be647588 100644
--- a/spec/features/signin_spec.rb
+++ b/spec/features/signin_spec.rb
@@ -1,6 +1,6 @@
require 'rails_helper'
-feature "signin", js: true do
+describe "signin", js: true do
let(:member) { FactoryBot.create :member }
let(:recipient) { FactoryBot.create :member }
let(:wrangler) { FactoryBot.create :crop_wrangling_member }
@@ -12,34 +12,34 @@ feature "signin", js: true do
click_button 'Sign in'
end
- scenario "via email address" do
+ it "via email address" do
visit crops_path # some random page
click_link 'Sign in'
login
expect(page).to have_content("Sign out")
end
- scenario "redirect to previous page after signin" do
+ it "redirect to previous page after signin" do
visit crops_path # some random page
click_link 'Sign in'
login
expect(current_path).to eq crops_path
end
- scenario "don't redirect to devise pages after signin" do
+ it "don't redirect to devise pages after signin" do
visit new_member_registration_path # devise signup page
click_link 'Sign in'
login
expect(current_path).to eq root_path
end
- scenario "redirect to signin page for if not authenticated to view notification" do
+ it "redirect to signin page for if not authenticated to view notification" do
visit notification_path(notification)
expect(current_path).to eq new_member_session_path
end
shared_examples "redirects to what you were trying to do" do
- scenario do
+ it do
visit "/#{model_name}/new"
expect(current_path).to eq new_member_session_path
login
@@ -55,14 +55,14 @@ feature "signin", js: true do
end
end
- scenario "after signin, redirect to new notifications page" do
+ it "after signin, redirect to new notifications page" do
visit new_notification_path(recipient_id: recipient.id)
expect(current_path).to eq new_member_session_path
login
expect(current_path).to eq new_notification_path
end
- scenario "after crop wrangler signs in and crops await wrangling, show alert" do
+ it "after crop wrangler signs in and crops await wrangling, show alert" do
create :crop_request
visit crops_path # some random page
click_link 'Sign in'
@@ -73,7 +73,7 @@ feature "signin", js: true do
end
context "with facebook" do
- scenario "sign in" do
+ it "sign in" do
# Ordinarily done by database_cleaner
Member.where(login_name: 'tdawg').delete_all
diff --git a/spec/features/signout_spec.rb b/spec/features/signout_spec.rb
index 2ccfd17dc..69f285ea7 100644
--- a/spec/features/signout_spec.rb
+++ b/spec/features/signout_spec.rb
@@ -1,11 +1,11 @@
require 'rails_helper'
-feature "signout" do
+describe "signout" do
let(:member) { create :member }
let(:path) {}
- scenario "redirect to previous page after signout" do
+ it "redirect to previous page after signout" do
visit crops_path # some random page
click_link 'Sign in'
fill_in 'Login', with: member.login_name
@@ -16,7 +16,7 @@ feature "signout" do
end
shared_examples "sign-in redirects" do |path|
- scenario "after signout, redirect to signin page if page needs authentication" do
+ it "after signout, redirect to signin page if page needs authentication" do
visit path
expect(current_path).to eq new_member_session_path
expect(page).to have_http_status(200)
@@ -39,7 +39,7 @@ feature "signout" do
include_examples "sign-in redirects", "/seeds/new"
end
- scenario 'photos' do
+ it 'photos' do
garden = FactoryBot.create :garden, owner: member
visit "/photos/new?id=#{garden.id}&type=garden"
expect(current_path).to eq new_member_session_path
diff --git a/spec/features/signup_spec.rb b/spec/features/signup_spec.rb
index 6afb28119..331dedaa7 100644
--- a/spec/features/signup_spec.rb
+++ b/spec/features/signup_spec.rb
@@ -1,7 +1,7 @@
require 'rails_helper'
-feature "signup", js: true do
- scenario "sign up for new account from top menubar" do
+describe "signup", js: true do
+ it "sign up for new account from top menubar" do
visit crops_path # something other than front page, which has multiple signup links
click_link 'Sign up'
fill_in 'Login name', with: 'person123'
@@ -13,7 +13,7 @@ feature "signup", js: true do
expect(current_path).to eq root_path
end
- scenario "sign up for new account with existing username" do
+ it "sign up for new account with existing username" do
visit crops_path # something other than front page, which has multiple signup links
click_link 'Sign up'
fill_in 'Login name', with: 'person123'
@@ -32,7 +32,7 @@ feature "signup", js: true do
click_button 'Sign up'
end
- scenario "sign up for new account without accepting TOS" do
+ it "sign up for new account without accepting TOS" do
visit root_path
first('.signup a').click # click the 'Sign up' button in the middle of the page
fill_in 'Login name', with: 'person123'
@@ -45,7 +45,7 @@ feature "signup", js: true do
end
context "with facebook" do
- scenario "sign up" do
+ it "sign up" do
# Ordinarily done by database_cleaner
Member.where(login_name: 'tdawg').delete_all
Member.where(email: 'tdawg@hotmail.com').delete_all
diff --git a/spec/features/unsubscribing_spec.rb b/spec/features/unsubscribing_spec.rb
index 3f7843034..18af5296b 100644
--- a/spec/features/unsubscribing_spec.rb
+++ b/spec/features/unsubscribing_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
require 'capybara/email/rspec'
-feature "unsubscribe" do
+describe "unsubscribe" do
let(:member) { create :member }
let(:notification) { create :notification }
- background do
+ before do
clear_emails
end
- scenario "from planting reminder mailing list" do
+ it "from planting reminder mailing list" do
# verifying the initial subscription status of the member
expect(member.send_planting_reminder).to eq(true)
expect(member.send_notification_email).to eq(true)
@@ -26,7 +26,7 @@ feature "unsubscribe" do
expect(updated_member.send_notification_email).to eq(true)
end
- scenario "from inbox notification mailing list" do
+ it "from inbox notification mailing list" do
# verifying the initial subscription status of the member
expect(member.send_planting_reminder).to eq(true)
expect(member.send_notification_email).to eq(true)
@@ -44,7 +44,7 @@ feature "unsubscribe" do
expect(updated_member.send_notification_email).to eq(false)
end
- scenario "visit unsubscribe page with a non-encrypted parameter" do
+ it "visit unsubscribe page with a non-encrypted parameter" do
# verifying the initial subscription status of the member
expect(member.send_planting_reminder).to eq(true)
expect(member.send_notification_email).to eq(true)
diff --git a/spec/helpers/photos_helper_spec.rb b/spec/helpers/photos_helper_spec.rb
index 60a6cbc59..cace0e120 100644
--- a/spec/helpers/photos_helper_spec.rb
+++ b/spec/helpers/photos_helper_spec.rb
@@ -22,7 +22,7 @@ describe PhotosHelper do
before { planting.photos << planting_photo }
it "uses planting photos" do
- is_expected.to eq planting_photo.thumbnail_url
+ expect(subject).to eq planting_photo.thumbnail_url
end
end
@@ -30,7 +30,7 @@ describe PhotosHelper do
before { harvest.photos << harvest_photo }
it "uses harvest photos" do
- is_expected.to eq harvest_photo.thumbnail_url
+ expect(subject).to eq harvest_photo.thumbnail_url
end
end
@@ -38,7 +38,7 @@ describe PhotosHelper do
before { seed.photos << seed_photo }
it "uses seed photos" do
- is_expected.to eq seed_photo.thumbnail_url
+ expect(subject).to eq seed_photo.thumbnail_url
end
end
end
diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb
index 4cd9c3fc1..f21688f64 100644
--- a/spec/models/crop_spec.rb
+++ b/spec/models/crop_spec.rb
@@ -4,7 +4,6 @@ describe Crop do
let(:pp2) { FactoryBot.create(:plant_part) }
let(:pp1) { FactoryBot.create(:plant_part) }
let(:maize) { FactoryBot.create(:maize) }
-
context 'all fields present' do
let(:crop) { FactoryBot.create(:tomato) }
@@ -143,57 +142,66 @@ describe Crop do
end
context 'photos' do
- before do
- @crop = FactoryBot.create(:tomato)
+ shared_examples 'has default photo' do
+ it { expect(Crop.has_photos).to include(crop) }
end
+ let!(:crop) { FactoryBot.create :tomato }
+ let(:member) { FactoryBot.create :member }
context 'with a planting photo' do
- before do
- @planting = FactoryBot.create(:planting, crop: @crop)
- @photo = FactoryBot.create(:photo, owner: @planting.owner)
- @planting.photos << @photo
- end
+ let!(:photo) { FactoryBot.create(:photo, owner: planting.owner) }
+ let!(:planting) { FactoryBot.create(:planting, crop: crop) }
- it 'has a default photo' do
- @crop.default_photo.should be_an_instance_of Photo
- expect(@crop.default_photo.id).to eq @photo.id
- end
+ before { planting.photos << photo }
- it 'is found in has_photos scope' do
- Crop.has_photos.should include(@crop)
- end
+ it { expect(crop.default_photo).to eq photo }
+ include_examples 'has default photo'
end
context 'with a harvest photo' do
- before do
- @harvest = FactoryBot.create(:harvest, crop: @crop)
- @photo = FactoryBot.create(:photo, owner: @harvest.owner)
- @harvest.photos << @photo
- end
+ let!(:harvest) { FactoryBot.create(:harvest, crop: crop) }
+ let!(:photo) { FactoryBot.create(:photo, owner: harvest.owner) }
- it 'has a default photo' do
- @crop.default_photo.should be_an_instance_of Photo
- expect(@crop.default_photo.id).to eq @photo.id
- end
+ before { harvest.photos << photo }
+
+ it { expect(crop.default_photo).to eq photo }
+ include_examples 'has default photo'
context 'and planting photo' do
- before do
- @planting = FactoryBot.create(:planting, crop: @crop)
- @planting_photo = FactoryBot.create(:photo, owner: @planting.owner)
- @planting.photos << @planting_photo
- end
+ let(:planting) { FactoryBot.create(:planting, crop: crop) }
+ let!(:planting_photo) { FactoryBot.create(:photo, owner: planting.owner) }
+
+ before { planting.photos << planting_photo }
it 'prefers the planting photo' do
- expect(@crop.default_photo.id).to eq @planting_photo.id
+ expect(crop.default_photo.id).to eq planting_photo.id
end
end
end
context 'with no plantings or harvests' do
it 'has no default photo' do
- expect(@crop.default_photo).to eq nil
+ expect(crop.default_photo).to eq nil
end
end
+
+ describe 'finding all photos' do
+ let(:planting) { FactoryBot.create :planting, crop: crop }
+ let(:harvest) { FactoryBot.create :harvest, crop: crop }
+ let(:seed) { FactoryBot.create :seed, crop: crop }
+
+ before do
+ # Add photos to all
+ planting.photos << FactoryBot.create(:photo, owner: planting.owner)
+ harvest.photos << FactoryBot.create(:photo, owner: harvest.owner)
+ seed.photos << FactoryBot.create(:photo, owner: seed.owner)
+ end
+
+ it { expect(crop.photos.size).to eq 3 }
+ it { expect(crop.planting_photos.size).to eq 1 }
+ it { expect(crop.harvest_photos.size).to eq 1 }
+ it { expect(crop.seed_photos.size).to eq 1 }
+ end
end
context 'sunniness' do
@@ -356,35 +364,6 @@ describe Crop do
expect(@maize.plant_parts).to eq [@pp1]
end
- context "search", :elasticsearch do
- let(:mushroom) { FactoryBot.create(:crop, name: 'mushroom') }
-
- before { sync_elasticsearch([mushroom]) }
-
- it "finds exact matches" do
- expect(Crop.search('mushroom')).to eq [mushroom]
- end
- it "finds approximate matches" do
- expect(Crop.search('mush')).to eq [mushroom]
- end
- it "doesn't find non-matches" do
- Crop.search('mush').should_not include @crop
- end
- it "searches case insensitively" do
- Crop.search('mUsH').should include mushroom
- end
- it "doesn't find 'rejected' crop" do
- @rejected_crop = FactoryBot.create(:rejected_crop, name: 'tomato')
- sync_elasticsearch([@rejected_crop])
- Crop.search('tomato').should_not include @rejected_crop
- end
- it "doesn't find 'pending' crop" do
- @crop_request = FactoryBot.create(:crop_request, name: 'tomato')
- sync_elasticsearch([@crop_request])
- Crop.search('tomato').should_not include @crop_request
- end
- end
-
context "csv loading" do
before do
# don't use 'let' for this -- we need to actually create it,
diff --git a/spec/models/garden_spec.rb b/spec/models/garden_spec.rb
index e538c2d1a..c709794a3 100644
--- a/spec/models/garden_spec.rb
+++ b/spec/models/garden_spec.rb
@@ -1,8 +1,9 @@
require 'rails_helper'
describe Garden do
- let(:owner) { FactoryBot.create(:member, login_name: 'hatupatu') }
- let(:garden) { FactoryBot.create(:garden, owner: owner, name: 'Springfield Community Garden') }
+ let(:owner) { FactoryBot.create(:member, login_name: 'hatupatu') }
+ let(:garden) { FactoryBot.create(:garden, owner: owner, name: 'Springfield Community Garden') }
+ let(:garden_type) { FactoryBot.create(:garden_type, name: "aquaponic") }
it "has a slug" do
garden.slug.should match(/hatupatu-springfield-community-garden/)
diff --git a/spec/models/garden_type.rb b/spec/models/garden_type.rb
new file mode 100644
index 000000000..cd5862c98
--- /dev/null
+++ b/spec/models/garden_type.rb
@@ -0,0 +1,38 @@
+require 'rails_helper'
+
+describe GardenType do
+ let(:garden) { FactoryBot.create(:garden, 'Free Carrots') }
+
+ describe "should have a name" do
+ let(:garden_type) { FactoryBot.build(:garden_type, name: "organic") }
+
+ it { expect(garden_type).to be_valid }
+ end
+
+ describe "doesn't allow a nil name" do
+ let(:garden_type) { FactoryBot.build(:garden_type, name: nil) }
+
+ it { expect(garden_type).not_to be_valid }
+ end
+
+ describe "doesn't allow a blank name" do
+ let(:garden_type) { FactoryBot.build(:garden_type, name: "") }
+
+ it { expect(garden_type).not_to be_valid }
+ end
+
+ describe "doesn't allow a name with only spaces" do
+ let(:garden_type) { FactoryBot.build(:garden_type, name: " ") }
+
+ it { expect(garden_type).not_to be_valid }
+ end
+
+ describe "does not delete gardens when deleted" do
+ before { FactoryBot.create :garden, garden_type: garden_type }
+
+ let(:garden_type) { FactoryBot.create(:garden_type, name: "Massive Flower Pot") }
+
+ it { expect(garden_type.gardens.size).to eq(1) }
+ it { expect { garden_type.destroy }.not_to change(Garden, :count) }
+ end
+end
diff --git a/spec/requests/api/v1/gardens_request_spec.rb b/spec/requests/api/v1/gardens_request_spec.rb
index 127513607..89bb2e8ee 100644
--- a/spec/requests/api/v1/gardens_request_spec.rb
+++ b/spec/requests/api/v1/gardens_request_spec.rb
@@ -38,12 +38,12 @@ RSpec.describe 'Gardens', type: :request do
"related" => "#{resource_url}/photos" } }
end
- scenario '#index' do
+ it '#index' do
get '/api/v1/gardens', params: {}, headers: headers
expect(subject['data']).to include(garden_encoded_as_json_api)
end
- scenario '#show' do
+ it '#show' do
get "/api/v1/gardens/#{garden.id}", params: {}, headers: headers
expect(subject['data']).to include(garden_encoded_as_json_api)
end
diff --git a/spec/requests/api/v1/plantings_request_spec.rb b/spec/requests/api/v1/plantings_request_spec.rb
index 9137f8b39..cfd60fcf7 100644
--- a/spec/requests/api/v1/plantings_request_spec.rb
+++ b/spec/requests/api/v1/plantings_request_spec.rb
@@ -71,12 +71,12 @@ RSpec.describe 'Plantings', type: :request do
}
end
- scenario '#index' do
+ it '#index' do
get '/api/v1/plantings', params: {}, headers: headers
expect(subject['data']).to include(planting_encoded_as_json_api)
end
- scenario '#show' do
+ it '#show' do
get "/api/v1/plantings/#{planting.id}", params: {}, headers: headers
expect(subject['data']['relationships']).to include("garden" => garden_as_json_api)
expect(subject['data']['relationships']).to include("crop" => crop_as_json_api)
diff --git a/spec/requests/garden_types_spec.rb b/spec/requests/garden_types_spec.rb
new file mode 100644
index 000000000..fbacd0491
--- /dev/null
+++ b/spec/requests/garden_types_spec.rb
@@ -0,0 +1,10 @@
+require 'rails_helper'
+
+RSpec.describe "GardenTypes", type: :request do
+ describe "GET /garden_types" do
+ it "works! (now write some real specs)" do
+ get garden_types_path
+ expect(response).to have_http_status(200)
+ end
+ end
+end
diff --git a/spec/routing/garden_types_routing_spec.rb b/spec/routing/garden_types_routing_spec.rb
new file mode 100644
index 000000000..986af7b70
--- /dev/null
+++ b/spec/routing/garden_types_routing_spec.rb
@@ -0,0 +1,33 @@
+require "rails_helper"
+
+describe GardenTypesController do
+ describe "routing" do
+ it "routes to #index" do
+ get("/garden_types").should route_to("garden_types#index")
+ end
+
+ it "routes to #new" do
+ get("/garden_types/new").should route_to("garden_types#new")
+ end
+
+ it "routes to #show" do
+ get("/garden_types/1").should route_to("garden_types#show", id: "1")
+ end
+
+ it "routes to #edit" do
+ get("/garden_types/1/edit").should route_to("garden_types#edit", id: "1")
+ end
+
+ it "routes to #create" do
+ post("/garden_types").should route_to("garden_types#create")
+ end
+
+ it "routes to #update" do
+ put("/garden_types/1").should route_to("garden_types#update", id: "1")
+ end
+
+ it "routes to #destroy" do
+ delete("/garden_types/1").should route_to("garden_types#destroy", id: "1")
+ end
+ end
+end
diff --git a/spec/services/crop_search_service_spec.rb b/spec/services/crop_search_service_spec.rb
new file mode 100644
index 000000000..a73fd70d9
--- /dev/null
+++ b/spec/services/crop_search_service_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe CropSearchService, type: :service do
+ describe 'search', :elasticsearch do
+ def search(term)
+ CropSearchService.search(term).map(&:name)
+ end
+
+ context 'with some crops' do
+ let!(:mushroom) { FactoryBot.create(:crop, name: 'mushroom') }
+ let!(:tomato) { FactoryBot.create(:crop, name: 'tomato') }
+ let!(:taewa) { FactoryBot.create(:crop, name: 'taewa') }
+ let!(:zucchini) { FactoryBot.create(:crop, name: 'zucchini') }
+ let!(:broccoli) { FactoryBot.create(:crop, name: 'broccoli') }
+ before do
+ # Alternate name
+ FactoryBot.create :alternate_name, name: 'fungus', crop: mushroom
+ # scientific name
+ FactoryBot.create :scientific_name, name: 'Agaricus bisporus', crop: mushroom
+
+ # Requested and rejected
+ FactoryBot.create(:rejected_crop, name: 'rejected mushroom')
+ FactoryBot.create(:crop_request, name: 'requested mushroom')
+
+ # Child record
+ FactoryBot.create(:crop, name: 'portobello', parent: mushroom)
+ Crop.reindex if ENV['GROWSTUFF_ELASTICSEARCH'] == 'true'
+ end
+
+ describe 'finds exact match' do
+ it { expect(search('mushroom')).to eq ['mushroom'] }
+ end
+
+ describe 'finds approximate match "mush"' do
+ it { expect(search('mush')).to eq ['mushroom'] }
+ end
+
+ if ENV['GROWSTUFF_ELASTICSEARCH'] == 'true'
+ describe 'finds mispellings matches' do
+ it { expect(search('muhsroom')).to eq ['mushroom'] }
+ it { expect(search('mushrom')).to eq ['mushroom'] }
+ it { expect(search('zuchini')).to eq ['zucchini'] }
+ it { expect(search('brocoli')).to eq ['broccoli'] }
+ end
+
+ describe 'biased' do
+ # Make some crops with planting counts
+ let!(:mushroom_parent) { FactoryBot.create :crop, name: 'mushroom' }
+ let!(:oyster) { FactoryBot.create :crop, name: 'oyster mushroom', parent: mushroom_parent }
+ let!(:shitake) { FactoryBot.create :crop, name: 'shitake mushroom', parent: mushroom_parent }
+ let!(:common) { FactoryBot.create :crop, name: 'common mushroom', parent: mushroom_parent }
+ let!(:brown) { FactoryBot.create :crop, name: 'brown mushroom', parent: mushroom_parent }
+ let!(:white) { FactoryBot.create :crop, name: 'white mushroom', parent: mushroom_parent }
+
+ describe 'biased to higher planting counts' do
+ before do
+ # Having plantings should bring these crops to the top of the search results
+ FactoryBot.create_list :planting, 10, crop: white
+ FactoryBot.create_list :planting, 4, crop: shitake
+ Crop.reindex
+ end
+ subject { search('mushroom') }
+ it { expect(subject.first).to eq 'white mushroom' }
+ it { expect(subject.second).to eq 'shitake mushroom' }
+ end
+ describe "biased to crops you've planted" do
+ let(:owner) { FactoryBot.create :member }
+ before do
+ FactoryBot.create_list :planting, 10, crop: brown
+ FactoryBot.create :planting, crop: oyster, owner: owner
+ FactoryBot.create :planting, crop: oyster, owner: owner
+ FactoryBot.create :planting, crop: shitake, owner: owner
+ Crop.reindex
+ end
+ subject { CropSearchService.search('mushroom', current_member: owner).map(&:name) }
+ it { expect(subject.first).to eq oyster.name }
+ it { expect(subject.second).to eq shitake.name }
+ end
+ end
+ end
+
+ describe 'doesn\'t find non-match "coffee"' do
+ it { expect(search('coffee')).to eq [] }
+ end
+
+ if ENV['GROWSTUFF_ELASTICSEARCH'] == 'true'
+ describe 'finds plurals' do
+ it { expect(search('mushrooms')).to eq ['mushroom'] }
+ it { expect(search('tomatoes')).to eq ['tomato'] }
+ end
+ end
+
+ describe 'searches case insensitively' do
+ it { expect(search('mUsHroom')).to eq ['mushroom'] }
+ it { expect(search('Mushroom')).to eq ['mushroom'] }
+ it { expect(search('MUSHROOM')).to eq ['mushroom'] }
+ end
+
+ it 'finds by alternate names' do
+ expect(search('fungus')).to eq ['mushroom']
+ end
+
+ describe 'finds by scientific names' do
+ it { expect(search('Agaricus bisporus')).to eq ['mushroom'] }
+ it { expect(search('agaricus bisporus')).to eq ['mushroom'] }
+ it { expect(search('Agaricus')).to eq ['mushroom'] }
+ it { expect(search('bisporus')).to eq ['mushroom'] }
+ end
+
+ describe "doesn't find rejected crop" do
+ it { expect(search('rejected')).to eq [] }
+ end
+
+ describe "doesn't find pending crop" do
+ it { expect(search('requested')).to eq [] }
+ end
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9a0b542df..e76b3e55e 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -32,6 +32,22 @@ RSpec.configure do |config|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
+ config.before(:suite) do
+ if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
+ # reindex models
+ Crop.reindex
+
+ # and disable callbacks
+ Searchkick.disable_callbacks
+ end
+ end
+
+ config.around(:each, search: true) do |example|
+ Searchkick.callbacks(true) do
+ example.run
+ end
+ end
+
# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
diff --git a/spec/support/elasticsearch_helpers.rb b/spec/support/elasticsearch_helpers.rb
deleted file mode 100644
index 7cd3fe5f2..000000000
--- a/spec/support/elasticsearch_helpers.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-module ElasticsearchHelpers
- def sync_elasticsearch(crops)
- return unless ENV['GROWSTUFF_ELASTICSEARCH'] == "true"
-
- crops.each { |crop| crop.__elasticsearch__.index_document }
- Crop.__elasticsearch__.refresh_index!
- end
-end
-
-RSpec.configure do |config|
- config.include ElasticsearchHelpers
-
- config.before(:all, elasticsearch: true) do
- Crop.__elasticsearch__.create_index! force: true if ENV['GROWSTUFF_ELASTICSEARCH'] == "true"
- end
-end
diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb
index f11a3a957..836ff35eb 100644
--- a/spec/support/feature_helpers.rb
+++ b/spec/support/feature_helpers.rb
@@ -1,5 +1,7 @@
module FeatureHelpers
def fill_autocomplete(field, options = {})
+ Crop.reindex if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
+
fill_in field, with: options[:with]
page.execute_script " $('##{field}').trigger('focus'); "
diff --git a/spec/views/crops/_planting_advice.html.haml_spec.rb b/spec/views/crops/_planting_advice.html.haml_spec.rb
index 7335fd127..59e635b45 100644
--- a/spec/views/crops/_planting_advice.html.haml_spec.rb
+++ b/spec/views/crops/_planting_advice.html.haml_spec.rb
@@ -13,7 +13,7 @@ describe "crops/_planting_advice" do
context "with no sunniness set" do
include_examples "render planting_advice"
it "doesn't show sunniness" do
- is_expected.to have_content "Plant in: not known."
+ expect(subject).to have_content "Plant in: not known."
end
end
@@ -41,7 +41,7 @@ describe "crops/_planting_advice" do
context "when none are set" do
include_examples "render planting_advice"
it "doesn't show planted_from " do
- is_expected.to have_content "Plant from: not known."
+ expect(subject).to have_content "Plant from: not known."
end
end
diff --git a/spec/views/garden_types/edit.html.haml_spec.rb b/spec/views/garden_types/edit.html.haml_spec.rb
new file mode 100644
index 000000000..b5c69b95f
--- /dev/null
+++ b/spec/views/garden_types/edit.html.haml_spec.rb
@@ -0,0 +1,17 @@
+require 'rails_helper'
+
+describe "garden_types/edit" do
+ before do
+ @owner = FactoryBot.create(:admin_member)
+ sign_in @owner
+ controller.stub(:current_user) { @owner }
+ @garden_type = assign(:garden_type, FactoryBot.create(:garden_type))
+ render
+ end
+
+ it "renders the edit garden_type form" do
+ assert_select "form", action: garden_types_path, method: "post" do
+ assert_select "input#garden_type_name", name: "garden_type[name]"
+ end
+ end
+end
diff --git a/spec/views/garden_types/new.html.haml_spec.rb b/spec/views/garden_types/new.html.haml_spec.rb
new file mode 100644
index 000000000..3241666af
--- /dev/null
+++ b/spec/views/garden_types/new.html.haml_spec.rb
@@ -0,0 +1,17 @@
+require 'rails_helper'
+
+describe "garden_types/new" do
+ before do
+ @owner = FactoryBot.create(:admin_member)
+ sign_in @owner
+ controller.stub(:current_user) { @owner }
+ @garden_type = assign(:garden_type, FactoryBot.create(:garden_type))
+ render
+ end
+
+ it "renders new garden_type form" do
+ assert_select "form", action: garden_types_path, method: "post" do
+ assert_select "input#garden_type_name", name: "garden_type[name]"
+ end
+ end
+end
diff --git a/spec/views/garden_types/show.html.haml_spec.rb b/spec/views/garden_types/show.html.haml_spec.rb
new file mode 100644
index 000000000..10b4d83a8
--- /dev/null
+++ b/spec/views/garden_types/show.html.haml_spec.rb
@@ -0,0 +1,17 @@
+require 'rails_helper'
+
+describe "garden_types/show" do
+ subject { render }
+
+ let!(:garden_type) { FactoryBot.create(:garden_type, name: "Hot Sauce") }
+
+ before do
+ controller.stub(:current_user) { nil }
+ assign(:garden_type, garden_type)
+ render
+ end
+
+ describe "renders a garden_type with no gardens" do
+ it { is_expected.to have_content "There are no gardens to display." }
+ end
+end
diff --git a/spec/views/members/show.rss.haml_spec.rb b/spec/views/members/show.rss.haml_spec.rb
index a0a7414e0..8ad64ab95 100644
--- a/spec/views/members/show.rss.haml_spec.rb
+++ b/spec/views/members/show.rss.haml_spec.rb
@@ -12,20 +12,20 @@ describe 'members/show.rss.haml', type: "view" do
end
it 'shows RSS feed title' do
- is_expected.to have_text("callum's recent posts")
+ expect(subject).to have_text("callum's recent posts")
end
it 'shows content of posts' do
- is_expected.to have_content "This is some text."
+ expect(subject).to have_content "This is some text."
end
it 'renders post bodies to HTML and XML-escapes them' do
# The variable "rendered" has been entity-replaced and tag-stripped
# The literal string output contains "<strong>" etc.
- is_expected.to have_content "strong"
+ expect(subject).to have_content "strong"
end
it 'gives the author in the item title' do
- is_expected.to have_content "#{@post1.subject} by #{@post1.author}"
+ expect(subject).to have_content "#{@post1.subject} by #{@post1.author}"
end
end
diff --git a/spec/views/posts/show.html.haml_spec.rb b/spec/views/posts/show.html.haml_spec.rb
index 2754439d1..bb59f2b47 100644
--- a/spec/views/posts/show.html.haml_spec.rb
+++ b/spec/views/posts/show.html.haml_spec.rb
@@ -71,7 +71,7 @@ describe "posts/show" do
end
it "shows comments" do
- is_expected.to have_content comment.body
+ expect(subject).to have_content comment.body
end
it 'has an anchor to the comments' do
@@ -95,7 +95,7 @@ describe "posts/show" do
end
it "shows the oldest comments first" do
- is_expected.to have_content(/#{@comment1.body}.*#{@comment2.body}.*#{@comment3.body}.*#{@comment4.body}/m)
+ expect(subject).to have_content(/#{@comment1.body}.*#{@comment2.body}.*#{@comment3.body}.*#{@comment4.body}/m)
end
end
@@ -105,7 +105,7 @@ describe "posts/show" do
before { render }
it "shows forum name" do
- is_expected.to have_content "in #{post.forum.name}"
+ expect(subject).to have_content "in #{post.forum.name}"
end
end
@@ -119,7 +119,7 @@ describe "posts/show" do
end
it 'shows a comment button' do
- is_expected.to have_link "Comment", href: new_comment_path(post_id: post.id)
+ expect(subject).to have_link "Comment", href: new_comment_path(post_id: post.id)
end
end
end