diff --git a/Gemfile b/Gemfile index 825b14006..6f77dc00d 100644 --- a/Gemfile +++ b/Gemfile @@ -9,10 +9,9 @@ git_source(:github) do |repo_name| end group :production do - gem 'nakayoshi_fork', '~> 0.0.4' # solves CoW friendly problem on MRI 2.2 and later + gem "nakayoshi_fork", "~> 0.0.4" # solves CoW friendly problem on MRI 2.2 and later end - gem "actionpack-action_caching", "~> 1.2" # Action caching for Action Pack (removed from core in Rails 4.0) gem "active_record_union", "~> 1.3" # Adds proper union and union_all methods to ActiveRecord::Relation gem "activerecord-import", "~> 1.0" # Adds ability to bulk create activerecord objects diff --git a/app/controllers/classified_listings_controller.rb b/app/controllers/classified_listings_controller.rb index 421213172..7034b20f3 100644 --- a/app/controllers/classified_listings_controller.rb +++ b/app/controllers/classified_listings_controller.rb @@ -1,18 +1,20 @@ class ClassifiedListingsController < ApplicationController - before_action :set_classified_listing, only: [:show, :edit, :update] + before_action :set_classified_listing, only: %i[show edit update] before_action :set_cache_control_headers, only: %i[index] after_action :verify_authorized, only: %i[edit update] before_action :authenticate_user!, only: %i[edit update new] def index - if params[:category].blank? - @classified_listings = ClassifiedListing.where(published: true).order("bumped_at DESC").limit(12) - else - @classified_listings = [] - end + @classified_listings = if params[:category].blank? + ClassifiedListing.where(published: true).order("bumped_at DESC").limit(12) + else + [] + end set_surrogate_key_header "classified-listings-#{params[:category]}" end + def show; end + def new @classified_listing = ClassifiedListing.new @credits = current_user.credits.where(spent: false) @@ -68,14 +70,15 @@ class ClassifiedListingsController < ApplicationController end private - # Use callbacks to share common setup or constraints between actions. - def set_classified_listing - @classified_listing = ClassifiedListing.find(params[:id]) - end - # Never trust parameters from the scary internet, only allow the white list through. - def classified_listing_params - accessible = %i[title body_markdown category tag_list contact_via_connect post_as_organization action] - params.require(:classified_listing).permit(accessible) - end + # Use callbacks to share common setup or constraints between actions. + def set_classified_listing + @classified_listing = ClassifiedListing.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def classified_listing_params + accessible = %i[title body_markdown category tag_list contact_via_connect post_as_organization action] + params.require(:classified_listing).permit(accessible) + end end diff --git a/app/controllers/credits_controller.rb b/app/controllers/credits_controller.rb index d3186e16b..36c04ebdf 100644 --- a/app/controllers/credits_controller.rb +++ b/app/controllers/credits_controller.rb @@ -19,6 +19,7 @@ class CreditsController < ApplicationController @number_to_purchase.times do if params[:user_type] == "organization" raise unless current_user.org_admin + credit_objects << Credit.new(organization_id: current_user.organization_id, cost: cost_per_credit / 100.0) else credit_objects << Credit.new(user_id: current_user.id, cost: cost_per_credit / 100.0) @@ -42,23 +43,21 @@ class CreditsController < ApplicationController @customer = if current_user.stripe_id_code Stripe::Customer.retrieve(current_user.stripe_id_code) else - Stripe::Customer.create({ - email: current_user.email - }) + Stripe::Customer.create( + email: current_user.email, + ) end end def find_or_create_card - if params[:stripe_token] - @card = Stripe::Customer.create_source( - @customer.id, - { - source: params[:stripe_token], - } - ) - else - @card = @customer.sources.retrieve(params[:selected_card]) - end + @card = if params[:stripe_token] + Stripe::Customer.create_source( + @customer.id, + source: params[:stripe_token], + ) + else + @customer.sources.retrieve(params[:selected_card]) + end end def update_user_stripe_info @@ -67,13 +66,13 @@ class CreditsController < ApplicationController def create_charge @amount = generate_cost - Stripe::Charge.create({ + Stripe::Charge.create( customer: @customer.id, source: @card || @customer.default_source, amount: @amount, description: "Purchase of #{@number_to_purchase} credits.", - currency: "usd" - }) + currency: "usd", + ) end def generate_cost diff --git a/app/models/classified_listing.rb b/app/models/classified_listing.rb index a1b7c8378..212265e92 100644 --- a/app/models/classified_listing.rb +++ b/app/models/classified_listing.rb @@ -1,5 +1,4 @@ class ClassifiedListing < ApplicationRecord - include AlgoliaSearch attr_accessor :post_as_organization, :action @@ -12,9 +11,9 @@ class ClassifiedListing < ApplicationRecord acts_as_taggable_on :tags validates :title, presence: true, - length: { maximum: 128 } + length: { maximum: 128 } validates :body_markdown, presence: true, - length: { maximum: 400 } + length: { maximum: 400 } validate :restrict_markdown_input validate :validate_tags validate :validate_category @@ -58,14 +57,14 @@ class ClassifiedListing < ApplicationRecord def self.categories_available { - "cfp" => { cost: 1, name: "Conference CFP", rules: "Currently open for proposals, with link to form" }, - "contractors" => { cost: 1, name: "Contractor for Hire", rules: "You are available for hire." }, - "collabs" => { cost: 1, name: "Contributors/Collaborators Wanted" }, - "education" => { cost: 1, name: "Education/Courses", rules: "Educational material and/or schools/bootcamps" }, - "jobs" => { cost: 10, name: "Job Listings", rules: "Companies offering employment right now." }, - "products" => { cost: 1, name: "Products/Tools", rules: "Must be availabel right now" }, - "events" => { cost: 1, name: "Upcoming Events", rules: "Live or online events with date included" }, - "misc" => { cost: 1, name: "Miscellaneous", rules: "Must not fit in any other category." } + "cfp" => { cost: 1, name: "Conference CFP", rules: "Currently open for proposals, with link to form" }, + "contractors" => { cost: 1, name: "Contractor for Hire", rules: "You are available for hire." }, + "collabs" => { cost: 1, name: "Contributors/Collaborators Wanted" }, + "education" => { cost: 1, name: "Education/Courses", rules: "Educational material and/or schools/bootcamps" }, + "jobs" => { cost: 10, name: "Job Listings", rules: "Companies offering employment right now." }, + "products" => { cost: 1, name: "Products/Tools", rules: "Must be availabel right now" }, + "events" => { cost: 1, name: "Upcoming Events", rules: "Live or online events with date included" }, + "misc" => { cost: 1, name: "Miscellaneous", rules: "Must not fit in any other category." } } end @@ -83,15 +82,9 @@ class ClassifiedListing < ApplicationRecord end def restrict_markdown_input - if body_markdown.to_s.scan(/(?=\n)/).count > 12 - errors.add(:body_markdown, "has too many linebreaks. No no more than 12 allowed.") - end - if body_markdown.to_s.include?("![") - errors.add(:body_markdown, "is not allowed to include images.") - end - if body_markdown.to_s.include?("{% ") - errors.add(:body_markdown, "is not allowed to include liquid tags.") - end + errors.add(:body_markdown, "has too many linebreaks. No no more than 12 allowed.") if body_markdown.to_s.scan(/(?=\n)/).count > 12 + errors.add(:body_markdown, "is not allowed to include images.") if body_markdown.to_s.include?("![") + errors.add(:body_markdown, "is not allowed to include liquid tags.") if body_markdown.to_s.include?("{% ") end def validate_tags diff --git a/app/models/credit.rb b/app/models/credit.rb index 89f204aae..f5aef9ea9 100644 --- a/app/models/credit.rb +++ b/app/models/credit.rb @@ -1,5 +1,4 @@ class Credit < ApplicationRecord - attr_accessor :number_to_purchase belongs_to :user, optional: true diff --git a/spec/factories/credits.rb b/spec/factories/credits.rb index 1327f82d9..876d93b6a 100644 --- a/spec/factories/credits.rb +++ b/spec/factories/credits.rb @@ -1,5 +1,4 @@ FactoryBot.define do - factory :credit do - end + factory :credit do end - \ No newline at end of file +end diff --git a/spec/models/classified_listing_spec.rb b/spec/models/classified_listing_spec.rb index 802043ca4..97146ae2c 100644 --- a/spec/models/classified_listing_spec.rb +++ b/spec/models/classified_listing_spec.rb @@ -1,12 +1,12 @@ -require 'rails_helper' +require "rails_helper" RSpec.describe ClassifiedListing, type: :model do + let(:classified_listing) { create(:classified_listing, user_id: user.id) } + let(:user) { create(:user) } + it { is_expected.to validate_presence_of(:title) } it { is_expected.to validate_presence_of(:body_markdown) } - let(:user) { create(:user)} - let(:classified_listing) { create(:classified_listing, user_id: user.id)} - describe "body html" do it "converts markdown to html" do expect(classified_listing.processed_html).to include("

") @@ -16,10 +16,13 @@ RSpec.describe ClassifiedListing, type: :model do classified_listing.tag_list = "a, b, c, d, e, f, g" expect(classified_listing.valid?).to eq(true) end - it "accepts 8 tags or less" do + + it "doesn't accept more than 8 tags" do classified_listing.tag_list = "a, b, c, d, e, f, g, h, z, t, s, p" expect(classified_listing.valid?).to eq(false) + expect(classified_listing.errors[:tag_list]).to be_truthy end + it "parses away spaces" do classified_listing.tag_list = "the best, tag list" classified_listing.save diff --git a/spec/models/credit_spec.rb b/spec/models/credit_spec.rb index cc412bb9d..db6988d6c 100644 --- a/spec/models/credit_spec.rb +++ b/spec/models/credit_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require "rails_helper" RSpec.describe Credit, type: :model do pending "add some examples to (or delete) #{__FILE__}" diff --git a/spec/requests/credits_spec.rb b/spec/requests/credits_spec.rb index a6563a69b..41b6e5bc6 100644 --- a/spec/requests/credits_spec.rb +++ b/spec/requests/credits_spec.rb @@ -2,25 +2,31 @@ require "rails_helper" RSpec.describe "Credits", type: :request do describe "GET /credits" do - let(:user) {create(:user)} + let(:user) { create(:user) } + before do sign_in user end + it "shows credits page" do get "/credits" expect(response.body).to include("You have") end end + describe "POST credits" do - let(:user) {create(:user)} + let(:user) { create(:user) } let(:stripe_helper) { StripeMock.create_test_helper } + before do StripeMock.start sign_in user end + after do StripeMock.stop end + xit "creates unspent credits" do post "/credits", params: { credit: { diff --git a/spec/requests/listings_spec.rb b/spec/requests/listings_spec.rb index 20b307e5e..4a5464cc7 100644 --- a/spec/requests/listings_spec.rb +++ b/spec/requests/listings_spec.rb @@ -1,6 +1,8 @@ require "rails_helper" RSpec.describe "/listings", type: :request do + let(:user) { create(:user) } + let(:organization) { create(:organization) } describe "GETS /listings" do it "has page content" do @@ -12,6 +14,7 @@ RSpec.describe "/listings", type: :request do expect(response.body).to include("classified-filters") end end + describe "GETS /listings/new" do it "has page content" do get "/listings" @@ -21,101 +24,92 @@ RSpec.describe "/listings", type: :request do describe "POST /listings" do before do - @organization = create(:organization) - @user = create(:user) - 20.times do - create(:credit, user_id: @user.id) - end - sign_in @user + create_list(:credit, 20, user_id: user.id) + sign_in user end + it "creates proper listing if credits are available" do post "/listings", params: { classified_listing: { title: "Hey", category: "education", body_markdown: "hey hey my my" - }} + } } expect(ClassifiedListing.last.processed_html).to include("hey my") end it "spends credits" do num_credits = Credit.where(spent: true).size post "/listings", params: { classified_listing: { title: "Hey", category: "education", body_markdown: "hey hey my my" - }} + } } expect(Credit.where(spent: true).size).to be > num_credits end it "adds tags" do - num_credits = Credit.where(spent: true).size post "/listings", params: { classified_listing: { title: "Hey", category: "education", body_markdown: "hey hey my my", tag_list: "ruby, rails, go" - }} + } } expect(ClassifiedListing.last.cached_tag_list).to include("rails") end it "creates the listing for the user" do - @user.update(organization_id: @organization.id) + user.update_column(:organization_id, organization.id) post "/listings", params: { classified_listing: { title: "Hey", category: "education", body_markdown: "hey hey my my", tag_list: "ruby, rails, go", post_as_organization: 0 - }} - expect(ClassifiedListing.last.organization_id).not_to eq(@organization.id) + } } + expect(ClassifiedListing.last.organization_id).not_to eq(organization.id) end it "creates the listing for the organization" do - @user.update(organization_id: @organization.id) + user.update_column(:organization_id, organization.id) post "/listings", params: { classified_listing: { title: "Hey", category: "education", body_markdown: "hey hey my my", tag_list: "ruby, rails, go", post_as_organization: 1 - }} - expect(ClassifiedListing.last.organization_id).to eq(@organization.id) + } } + expect(ClassifiedListing.last.organization_id).to eq(organization.id) end end describe "GETS /listings/edit" do + let(:classified_listing) { create(:classified_listing, user_id: user.id) } + before do - @organization = create(:organization) - @user = create(:user) - @classified_listing = create(:classified_listing, user_id: @user.id) - 20.times do - create(:credit, user_id: @user.id) - end - sign_in @user + create_list(:credit, 20, user_id: user.id) + sign_in user end + it "has page content" do - get "/listings/#{@classified_listing.id}/edit" + get "/listings/#{classified_listing.id}/edit" expect(response.body).to include("You can bump your listing") end end - describe "PUT /listings/:id" do + let(:classified_listing) { create(:classified_listing, user_id: user.id) } + before do - @organization = create(:organization) - @user = create(:user) - @classified_listing = create(:classified_listing, user_id: @user.id) - 20.times do - create(:credit, user_id: @user.id) - end - sign_in @user + create_list(:credit, 20, user_id: user.id) + sign_in user end + it "updates bumped_at if action is bump" do # block = create(:block, user_id: user.id, input_css: ".blue { color: blue;}") - put "/listings/#{@classified_listing.id}", params: { - classified_listing: { action: "bump"} + put "/listings/#{classified_listing.id}", params: { + classified_listing: { action: "bump" } } expect(ClassifiedListing.last.bumped_at).to be > 10.seconds.ago end it "updates publish if action is unpublish" do - put "/listings/#{@classified_listing.id}", params: { - classified_listing: { action: "unpublish"} + put "/listings/#{classified_listing.id}", params: { + classified_listing: { action: "unpublish" } } expect(ClassifiedListing.last.published).to eq(false) end it "updates body_markdown" do - put "/listings/#{@classified_listing.id}", params: { - classified_listing: { body_markdown: "hello new markdown"} + put "/listings/#{classified_listing.id}", params: { + classified_listing: { body_markdown: "hello new markdown" } } expect(ClassifiedListing.last.body_markdown).to eq("hello new markdown") end it "does not update body_markdown if not bumped/created recently" do - @classified_listing.update_column(:bumped_at, 50.hours.ago) - put "/listings/#{@classified_listing.id}", params: { - classified_listing: { body_markdown: "hello new markdown"} + classified_listing.update_column(:bumped_at, 50.hours.ago) + put "/listings/#{classified_listing.id}", params: { + classified_listing: { body_markdown: "hello new markdown" } } expect(ClassifiedListing.last.body_markdown).not_to eq("hello new markdown") end