New/show mod integration tests. Configured Capybara to use headless Firefox with Selenium. Rewrote routes file.

master
Zequez 2014-11-10 04:24:05 -03:00
parent 44a013bd93
commit 71106a33c0
21 changed files with 248 additions and 95 deletions

View File

@ -24,7 +24,7 @@ group :development, :test, :assets do
gem 'jquery-rails' # Use jquery as the JavaScript library
gem 'turbolinks' # Turbolinks makes following links in your web application faster
gem 'selenium-webdriver'
# gem 'selenium-phantomjs'
gem 'database_cleaner'
end
gem 'font-awesome-sass' # View helper for font-awesome, not really neccesary, but handy

View File

@ -136,6 +136,7 @@ GEM
coffee-script-source (1.7.0)
crack (0.4.2)
safe_yaml (~> 1.0.0)
database_cleaner (1.3.0)
devise (3.2.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
@ -344,6 +345,7 @@ DEPENDENCIES
coffee-rails (~> 4.0.0)
compass!
compass-rails!
database_cleaner
devise
factory_girl_rails
font-awesome-sass

View File

@ -28,7 +28,7 @@
overflow: hidden
&.active
display: block
&-link
&-container
//@extend %thumbnail-hover
display: block
width: 100%
@ -53,7 +53,7 @@
width: rhythm(3)
height: rhythm(3)
margin: 0 space()/2 space() space()/2
&-link
&-container
display: block
width: 100%
height: 100%

View File

@ -75,8 +75,7 @@ class ModsController < ApplicationController
end
def create
@mod = Mod.new mod_params
@mod.author = current_user
@mod = Mod.new(current_user.is_admin? ? mod_params_admin : mod_params)
if @mod.save
redirect_to category_mod_url(@mod.category, @mod)
else
@ -95,8 +94,28 @@ class ModsController < ApplicationController
private
def mod_params
params.require(:mod).permit(:name, :category_id, :github, :forum_url, :description, :summary, :media_links_string)
def mod_params
params.require(:mod).permit(:name,
:category_id,
:github,
:forum_url,
:description,
:summary,
:media_links_string,
versions_attributes: [
:number,
:released_at,
game_version_ids: [],
files_attributes: [
:attachment,
:name
]
])
.merge(author_id: current_user.id)
end
def mod_params_admin
mod_params.merge params.require(:mod).permit(:author_name)
end
# def category

View File

@ -19,9 +19,9 @@ module ApplicationHelper
@empty_asset.image.url(size)
end
def if_na(condition, result = nil)
def if_na(condition, result = nil, &block)
if !result and block_given?
condition ? yield : 'N/A'
condition ? capture(&block) : 'N/A'
else
condition ? result : 'N/A'
end
@ -67,6 +67,10 @@ module ApplicationHelper
polymorphic_path([@sort, @category, :mods], filter_params.merge(q: query))
end
def edit_mod_url(mod)
edit_category_mod_url(mod.category, mod)
end
### Links helpers
####################

View File

@ -23,14 +23,14 @@ class Mod < ActiveRecord::Base
has_many :downloads
has_many :visits
has_many :files, class_name: 'ModFile'
has_many :versions, class_name: 'ModVersion'
has_many :assets, ->{ order 'sort_order asc' }, class_name: 'ModAsset'
has_many :files, class_name: 'ModFile', dependent: :destroy
has_many :versions, class_name: 'ModVersion', dependent: :destroy
has_many :assets, ->{ order 'sort_order asc' }, class_name: 'ModAsset', dependent: :destroy
has_many :tags
has_many :favorites
has_many :forum_posts
has_many :mod_game_versions, -> { uniq }
has_many :mod_game_versions, -> { uniq }, dependent: :destroy
has_many :game_versions, -> { uniq.sort_by_older_to_newer }, through: :mod_game_versions
# has_one :latest_version, -> { sort_by_newer_to_older.limit(1) }, class_name: 'ModVersion'
@ -130,11 +130,7 @@ class Mod < ActiveRecord::Base
end
def author_name
if author
author.name
else
read_attribute :author_name
end
super || (author ? author.name : nil)
end
def github_path
@ -160,6 +156,10 @@ class Mod < ActiveRecord::Base
versions.size > 0
end
def has_files?
files.size > 0
end
private
def set_game_versions_string

View File

@ -7,9 +7,11 @@ class ModFile < ActiveRecord::Base
:content_type => ['application/zip', 'application/x-zip-compressed', 'application/octet-stream/']
validates :mod_version, presence: true
before_save do
self.mod = mod_version.mod if mod_version
end
def delegated_name
name || mod_version.number
name || (mod_version ? mod_version.number : nil)
end
end

View File

@ -14,6 +14,7 @@ class ModVersion < ActiveRecord::Base
#################
validates :number, presence: true
# validates :game_versions, presence: true
validate :validate_non_consecutive_game_versions
def validate_non_consecutive_game_versions

View File

@ -1,4 +1,4 @@
- if mod.has_versions?
- if mod.has_versions? and mod.has_files?
.mod-link.btn.btn-download
%a{href: mod.latest_version.files.first.attachment.url}
= icon 'download'

View File

@ -9,7 +9,7 @@
%td.mod-data-row-name Source code
%td.mod-data-row-value= if_na(@mod.github_url) { link_to(@mod.github_path, @mod.github_url) }
%td.mod-data-row-name Tags
%td.mod-data-row-value
%td.mod-data-row-value N/A
%tr.mod-data-row
%td.mod-data-row-name First version
%td.mod-data-row-value= if_na(@mod.has_versions?) { @mod.versions.first.number }
@ -21,14 +21,16 @@
%td.mod-data-row-name Last release
%td.mod-data-row-value= if_na(@mod.has_versions? && @mod.versions.last.released_at) { @mod.versions.last.released_at.to_s(:rfc822) }
%tr.mod-data-row
%td.mod-data-row-name License
%td.mod-data-row-value= if_na(@mod.license) { link_to(@mod.license, @mod.license_url) }
/ %td.mod-data-row-name License
/ %td.mod-data-row-value= if_na(@mod.license) { link_to(@mod.license, @mod.license_url) }
%td.mod-data-row-name Official forum post
%td.mod-data-row-value
= if_na(!@mod.forum_post_url.blank?) do
= if_na(@mod.forum_post_url.present?) do
%a{href: @mod.forum_post_url}
= @mod.forum_comments_count unless @mod.forum_comments_count.blank?
comments
On the Factorio forums
/ = @mod.forum_comments_count unless @mod.forum_comments_count.blank?
/ comments
%tr.mod-data-row
%td.mod-data-row-name Official site
%td.mod-data-row-value{colspan: 3}= @mod.official_url if @mod.official_url
%td.mod-data-row-value{colspan: 3}
= link_to @mod.official_url, @mod.official_url

View File

@ -4,6 +4,7 @@
= f.inputs do
= f.input :name
= f.input :category
= f.input :author_name if current_user.is_admin?
= f.input :github
= f.input :official_url
= f.input :forum_url

View File

@ -4,19 +4,20 @@
.mod
.mod-images<
%ul.mod-medium-images
- if @mod.assets.empty?
- if @mod.media_links.empty?
.mod-medium-image.active
.mod-medium-image-link
.mod-medium-image-container
%img.mod-medium-image-img{src: mod_asset_missing_image(:medium)}
- @mod.assets.each_with_index do |asset, i|
%li.mod-medium-image{'data-thumb' => asset.id, class: ('active' if i == 0)}
%a.mod-medium-image-link{href: asset.image.url(:full), target: '_blank'}
%img.mod-medium-image-img{src: asset.image.url(:medium)}
%ul.mod-thumb-images{class: ('many-thumbs' if @mod.assets.size > 3)}
- @mod.assets.each do |asset|
%li.mod-thumb-image{'data-thumb-of' => asset.id}<>
%a.mod-thumb-image-link{href: asset.image.url(:full), target: "_blank"}
%img.mod-thumb-image-img{src: asset.image.url(:thumb)}
- @mod.media_links.each_with_index do |media_link, i|
%li.mod-medium-image{class: ('active' if i == 0)}
= media_link.embed
/ %a.mod-medium-image-link{href: media_link.direct_url, target: '_blank'}
/ %img.mod-medium-image-img{src: asset.direct_url}
%ul.mod-thumb-images{class: ('many-thumbs' if @mod.media_links.size > 3)}
- @mod.media_links.each do |media_link|
%li.mod-thumb-image{'data-thumb-of' => media_link.direct_url}<>
%span.mod-thumb-image-container
%img.mod-thumb-image-img{src: media_link.thumbnail_url}
/ .mod-thumbnail-container<
/ - @mod.assets.each_with_index do |asset, i|
@ -31,6 +32,7 @@
.mod-subtitle
on
= link_to @mod.category.name, [@mod.category, :mods]
%a.edit-mod-link{href: edit_mod_url(@mod)} Edit mod
= render partial: 'mod_data_table'
= render partial: 'download_button', locals: { mod: @mod }
.mod-description

View File

@ -42,3 +42,6 @@ en:
labels:
mod:
forum_url: 'Forum URL'
mod_version:
released_at: 'Release day'

View File

@ -5,37 +5,51 @@ Rails.application.routes.draw do
get '/', to: 'admin/dashboard#index'
end
# most_recent_mods_url => 'recently-updated-mods/'
# most_recent_category_mods_url => 'recently-updated-mods/<category_id>'
scope 'recently-updated-mods', sort: 'most_recent', as: :most_recent do
get '/', to: 'mods#index', as: :mods
get '/:category_id', to: 'mods#index', as: :category_mods
# / == /mods/recently-updated
#
# /mods/new
#
# /mods
# /mods/:category_id
# /mods/:category_id/:id
# /mods/:category_id/:id/edit
#
# /mods/recently-updated
# /mods/recently-updated/:category_id
# /mods/most-downloaded
# /mods/most-downloaded/:category_id
def category_scope
resources :categories, path: '/', only: [] do
yield
end
end
def sort_scope(name, path = nil, as_name = false)
scope path, sort: name.to_s, as: (name if as_name) do
yield
end
end
def new_sorting_section(name, path = nil, as_name = false)
sort_scope(name, path, as_name) do
resources :mods, path: '/', only: :index
category_scope do
resources :mods, path: '/', only: :index
end
end
end
scope 'mods' do
get '/new', to: 'mods#new'
get '/:id/edit', to: 'mods#edit'
post '/', to: 'mods#create'
put '/', to: 'mods#update'
end
resources :mods, path: '/', except: [:index, :show, :edit]
# alpha_mods_url => 'mods/'
# alpha_category_mods_url => 'mods/<category_id>'
scope 'mods', sort: 'alpha', as: :alpha do
get '/', to: 'mods#index', as: :mods
get '/:category_id', to: 'mods#index', as: :category_mods
end
new_sorting_section(:most_recent, 'recently-updated', true)
new_sorting_section(:alpha, nil, true) # This is to generate the helper URL
new_sorting_section(:alpha) # The default sorting
# mods_url => 'mods/'
# category_mods_url => 'mods/<category_id>'
scope 'mods', sort: 'alpha' do
get '/', to: 'mods#index', as: :mods
get '/:category_id', to: 'mods#index', as: :category_mods
end
# category_mod_url => 'mods/<category_id>/<mod_id>'
scope 'mods' do
get '/:category_id/:id', to: 'mods#show', as: :category_mod
category_scope do
resources :mods, path: '/', only: [:show, :edit]
end
end
get '/how-to-install' => 'static#how_to_install', as: :how_to_install_static

2
guard_with_virtual_display.sh Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env bash
DISPLAY=localhost:0.0 xvfb-run -a bundle exec guard

View File

@ -75,22 +75,49 @@ feature 'Modder creates a new mod' do
expect(page).to have_content 'Invalid media links'
end
# Fuck this. I'm not gonna install a headless Selenium server today.
# scenario 'user submits mod with a version', js: true do
# sign_in
# create_category 'Potato'
# visit '/mods/new'
# fill_in 'Name', with: 'Valid mod name'
# click_link 'Add version'
# find('.mod-version').fill_in 'Number', with: '123'
# # within '.mod-version:nth-child(1)' do
# # end
# submit_form
# mod = Mod.first
# expect(current_path).to eq '/mods/potato/valid-mod-name'
# expect(mod.versions[0].number).to eq '123'
# end
scenario 'user submits mod with a version and file', js: true do
sign_in
create_category 'Potato'
create :game_version, number: '1.1.x'
create :game_version, number: '1.2.x'
attachment = File.new(Rails.root.join('spec', 'fixtures', 'test.zip'))
visit '/mods/new'
fill_in 'Name', with: 'Valid mod name'
select 'Potato', from: 'Category'
click_link 'Add version'
within('.mod-version:nth-child(1)') do
fill_in 'Number', with: '123'
fill_in 'Release day', with: '2014-11-09'
select '1.1.x', from: 'Game versions'
select '1.2.x', from: 'Game versions'
click_link 'Add file'
within('.mod-version-file:nth-child(1)') do
attach_file 'Attachment', attachment.path
end
end
submit_form
mod = Mod.first
expect(current_path).to eq '/mods/potato/valid-mod-name'
expect(page).to have_content 'Valid mod name'
expect(mod.versions[0].number).to eq '123'
expect(mod.versions[0].released_at).to eq Time.zone.parse('2014-11-09')
expect(mod.versions[0].game_versions[0].number).to eq '1.1.x'
expect(mod.versions[0].game_versions[1].number).to eq '1.2.x'
expect(mod.versions[0].files[0].attachment_file_size).to eq attachment.size
end
scenario 'admin user submits a mod selecting an author' do
sign_in_admin
create_category 'Potato'
visit '/mods/new'
fill_in 'Name', with: 'Mod Name'
select 'Potato', from: 'Category'
fill_in 'Author name', with: 'MangoDev'
submit_form
mod = Mod.first
expect(current_path).to eq '/mods/potato/mod-name'
expect(mod.author_name).to eq 'MangoDev'
end
def submit_form
click_button 'Create Mod'
@ -101,6 +128,11 @@ feature 'Modder creates a new mod' do
login_as @user
end
def sign_in_admin
@user = create :user, is_admin: true
login_as @user
end
def create_category(name)
@category = create :category, name: name
end

View File

@ -2,6 +2,31 @@ require 'rails_helper'
include Warden::Test::Helpers
feature 'Display full mod information' do
scenario 'Mod with just name and category' do
category = create :category, name: 'Potato category'
create :mod, name: 'Super Mod', category: category
visit '/mods/potato-category/super-mod'
expect(page).to have_content 'Super Mod'
expect(page).to have_content 'Potato category'
end
scenario 'Mod with name, category and media links' do
category = create :category, name: 'Potato category'
create :mod, name: 'Super Mod', category: category, media_links_string: "http://i.imgur.com/qLpt6gI.jpg\nhttp://gfycat.com/EthicalZanyHuman"
visit '/mods/potato-category/super-mod'
expect(page).to have_content 'Super Mod'
expect(page).to have_content 'Potato category'
expect(page).to have_css 'img[src="http://i.imgur.com/qLpt6gI.jpg"]'
expect(page).to have_css 'img[src="http://i.imgur.com/qLpt6gIs.jpg"]'
expect(page).to have_css 'img[src="https://thumbs.gfycat.com/EthicalZanyHuman-poster.jpg"]'
end
scenario 'Visiting the mod page as the owner of the mod should display a link to edit the mod' do
category = create :category, name: 'Potato category'
create :mod, name: 'Super Mod', category: category
visit '/mods/potato-category/super-mod'
expect(page).to have_link 'Edit mod', '/mods/super-mod/edit'
end
# expect(page).to have_content 'Mah super mod'
# expect(page).to have_content 'Potato category'
# expect(page).to have_link 'factorio-mods/mah-super-mod', href: 'http://github.com/factorio-mods/mah-super-mod'

View File

@ -65,10 +65,12 @@ RSpec.describe ModFile, :type => :model do
end
context 'empty #mod_version' do
it 'should not be valid' do
it 'should be valid' do
file.mod_version = nil
file.name = nil
expect(file).to be_invalid
expect(file).to be_valid
expect(file.name).to eq nil
expect(file.delegated_name).to eq nil
end
end
end

View File

@ -104,14 +104,29 @@ RSpec.describe Mod, :type => :model do
describe '#has_versions?' do
it 'should return false if the mod has no versions' do
mod = create :mod, versions: []
mod.has_versions?.should eq false
expect(mod.has_versions?).to eq false
end
it 'should return true if the mod has a version' do
mod = create :mod, versions: []
create :mod_version, mod: mod
mod = Mod.first
mod.has_versions?.should eq true
expect(mod.has_versions?).to eq true
end
end
describe '#has_files?' do
it 'should return false if the mod has no files' do
mod = create :mod, versions: []
expect(mod.has_files?).to eq false
end
it 'should return true if the mod has at least a file' do
mod = create :mod, versions: []
mod_version = create :mod_version, mod: mod
mod_file = create :mod_file, mod_version: mod_version
mod = Mod.first
expect(mod.has_files?).to eq true
end
end
@ -493,15 +508,15 @@ RSpec.describe Mod, :type => :model do
end
it 'should work when sorting by recently updated' do
m1 = create(:mod, name: 'C Potato', versions: [create(:mod_version, released_at: 9.days.ago)])
m2 = create(:mod, name: 'B Potato', versions: [create(:mod_version, released_at: 8.days.ago)])
m3 = create(:mod, name: 'A Potato', versions: [create(:mod_version, released_at: 7.days.ago)])
m4 = create(:mod, summary: 'B Potatou', versions: [create(:mod_version, released_at: 5.days.ago)])
m5 = create(:mod, summary: 'A Potatou', versions: [create(:mod_version, released_at: 4.days.ago)])
m6 = create(:mod, summary: 'C Potatou', versions: [create(:mod_version, released_at: 6.days.ago)])
m7 = create(:mod, description: 'A Potatoeiu', versions: [create(:mod_version, released_at: 1.days.ago)])
m8 = create(:mod, description: 'C Potatoeiu', versions: [create(:mod_version, released_at: 3.days.ago)])
m9 = create(:mod, description: 'B Potatoeiu', versions: [create(:mod_version, released_at: 2.days.ago)])
m1 = create(:mod, name: 'C Potato', versions: [build(:mod_version, released_at: 9.days.ago)])
m2 = create(:mod, name: 'B Potato', versions: [build(:mod_version, released_at: 8.days.ago)])
m3 = create(:mod, name: 'A Potato', versions: [build(:mod_version, released_at: 7.days.ago)])
m4 = create(:mod, summary: 'B Potatou', versions: [build(:mod_version, released_at: 5.days.ago)])
m5 = create(:mod, summary: 'A Potatou', versions: [build(:mod_version, released_at: 4.days.ago)])
m6 = create(:mod, summary: 'C Potatou', versions: [build(:mod_version, released_at: 6.days.ago)])
m7 = create(:mod, description: 'A Potatoeiu', versions: [build(:mod_version, released_at: 1.days.ago)])
m8 = create(:mod, description: 'C Potatoeiu', versions: [build(:mod_version, released_at: 3.days.ago)])
m9 = create(:mod, description: 'B Potatoeiu', versions: [build(:mod_version, released_at: 2.days.ago)])
expect(Mod.sort_by_most_recent.filter_by_search_query('potato')).to eq [m3, m2, m1, m5, m4, m6, m7, m9, m8]
end

View File

@ -28,10 +28,30 @@ RSpec.configure do |config|
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
config.use_transactional_fixtures = false
config.include Devise::TestHelpers, type: :controller
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
# RSpec Rails can automatically mix in different behaviours to your tests
# based on their file location, for example enabling you to call `get` and
# `post` in specs under `spec/controllers`.

View File

@ -0,0 +1,7 @@
require 'rails_helper'
describe 'Mods routes' do
it 'should be like this' do
end
end