Разработчик для регистрации и входа пользователя.Проблема с Capybara и администратором Разрешения пользователя (и разработка)
Администраторы устанавливаются с помощью консоли рельсов (установка логического значения admin в true).
Rspec и FactoryGirl.
К сожалению, перед тем, как писать тесты, я написал свое приложение (лучшие уроки усложняются). Теперь я изучаю rspec и пишу тестовый набор для приложения.
У меня есть разрешения на доступ к контроллерам и разрешения на просмотр, для администраторов и не-админов, которые работают на практике (я знаю это путем тщательного ручного тестирования браузера).
В этом случае у меня есть ссылка «Admin» в заголовке, которая отображается при входе пользователя в систему и также является администратором.
My StaticPagesController также имеет эффективную настройку before_action, поэтому никто не может получить доступ к странице администратора, если они не вошли в систему и не являются администраторами.
Я написал несколько тестов для этого и подумал, что я его отсортировал, пока не заметил, что при внесении изменений в спецификационный файл спецификаций/функций, содержащий эти тесты, защита запускает только те тесты и передает их. Однако, когда я запускаю весь набор тестов, те же тесты терпят неудачу. Я полностью смутился этим.
Я думаю, что это может иметь какое-то отношение к Devise, но я просто не знаю.
спецификации/особенности/user_and_role_spec.rb
require 'rails_helper'
def manually_create_user
visit new_user_registration_path
fill_in('user_first_name', :with => 'Test')
fill_in('user_last_name', :with => 'User')
fill_in('user_email', :with => '[email protected]')
fill_in('user_password', :with => 'testuser')
click_button('Sign up')
end
def create_user_and_login_as(type)
user = FactoryGirl.create(type)
visit(new_user_session_path)
fill_in('user_email', :with => user.email)
fill_in('user_password', :with => user.password)
click_button('Log in')
end
describe 'with users and roles' do
context "if user is not an admin" do
it "does not allow any user to visit the admin page if not logged-in" do
visit(admin_path)
expect(current_path).to eq(root_path)
end
it "does not allow a new user to visit the admin page" do
manually_create_user
visit(admin_path)
expect(current_path).to eq(root_path)
end
it "does not allow a student to visit the admin page" do
create_user_and_login_as(:student)
visit admin_path
expect(current_path).to eq(root_path)
end
it "does not allow a teacher to visit the admin page" do
create_user_and_login_as(:teacher)
visit admin_path
expect(current_path).to eq(root_path)
end
end
context "if user is an admin" do
it "allows an admin user to visit the admin page" do
create_user_and_login_as(:admin_user)
click_link 'Admin'
expect(current_path).to eq(admin_path)
end
it "allows a teacher_admin to visit the admin page" do
create_user_and_login_as(:teacher_admin_user)
click_link 'Admin'
expect(current_path).to eq(admin_path)
end
end
end
Испытания в контексте «если пользователь не является администратором» все FAIL при выполнении полного набора тестов. Они не в состоянии с той же ошибкой:
Failure/Error: expect(current_path).to eq(root_path)
expected: "/"
got: "/admin"
(compared using ==)
Который, мне, значит страница администратора была доступна, когда оно не должно быть. В моем браузере ссылка на страницу администратора не может быть видна, и к странице не может быть доступа, вручную набрав URL-адрес, если пользователь не зарегистрирован и не является администратором.
Тестирование в контексте «если пользователь является администратором» все PASS при запуске полного набора тестов.
спецификации/фабрики/users.rb:
require 'faker'
FactoryGirl.define do
factory :user do |f|
f.first_name { Faker::Name.first_name }
f.last_name { Faker::Name.last_name }
f.email { Faker::Internet.email }
f.password { Faker::Internet.password(8) }
f.admin false
trait :student do
type "Student"
end
trait :teacher do
type "Teacher"
end
trait :admin do
admin true
end
factory :admin_user, traits: [:admin]
factory :student, traits: [:student]
factory :teacher, traits: [:teacher]
factory :teacher_admin_user, traits: [:teacher, :admin]
end
end
static_pages_controller.rb:
class StaticPagesController < ApplicationController
before_action :admin?, only: [:admin]
def home
@testimonials = Testimonial.all
end
def admin
@groups = Group.all
@users = User.all
@students = Student.all
@teachers = Teacher.all
end
private
def admin?
unless signed_in? and current_user.admin == true
redirect_to root_path, notice: "You must be a signed-in admin to view this page"
end
end
end
static_pages_helper.rb:
module StaticPagesHelper
def allowed_to_see_admin_link?
signed_in? && current_user.admin
end
end
модели/user.rb:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :first_name, presence: true
validates :last_name, presence: true
validates :admin, inclusion: { in: [true, false] }
scope :newest_first, -> { order("created_at DESC") }
scope :order_by_first_name, -> { order("first_name") }
def full_name
"#{first_name} #{last_name}"
end
def unassigned?
type != "Student" and type != "Teacher"
end
def can_view_materials?
admin || type == "Teacher" || type == "Student" && groups.any? # So only current students can view the Materials page.
end
def testimonial_owner?(testimonial)
id == testimonial.student_id
end
end
Релевантная часть _header.html.Еврорадио: частичный:
<ul class="nav navbar-nav navbar-right">
<% if allowed_to_see_admin_link? %>
<li><%= link_to "Admin", admin_path %></li>
<% end %>
</ul>
Gemfile:
gem 'rails', '4.2.0'
gem 'bootstrap-sass', '~> 3.3.3'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'devise'
group :development, :test do
gem 'sqlite3'
gem 'byebug'
gem 'web-console', '~> 2.0'
gem 'spring'
gem 'better_errors'
gem 'binding_of_caller'
gem 'rspec-rails'
gem 'guard-rspec', require: false
gem 'factory_girl_rails'
end
group :test do
gem 'faker'
gem 'capybara'
gem 'launchy'
gem 'database_cleaner'
end
group :production do
gem 'pg'
gem 'rails_12factor'
end
пользователей в схеме:
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "admin", default: false
t.string "type"
t.string "first_name"
t.string "last_name"
end
routes.rb:
resources :materials
root 'static_pages#home'
devise_for :users, :controllers => { registrations: 'registrations' }
get 'admin' => 'static_pages#admin'
resources :groups
resources :users
resources :students
resources :teachers
resources :testimonials
post 'assign_to_group' => 'students#assign_to_group' # Could have been 'patch', but default in the controller method is 'post', so I left the method as default and changed this route to 'post'. Doesn't NEED to be patch.
post 'remove_from_group' => 'students#remove_from_group'
post 'unassign_teacher' => 'groups#unassign_teacher'
post 'assign_as_student' => 'teachers#assign_as_student'
post 'assign_as_teacher' => 'students#assign_as_teacher'
post 'add_student' => 'groups#add_student'
post 'remove_student_from_group' => 'groups#remove_student_from_group'
В вашей спецификации - попробуйте проверить что-то, что пользователь на самом деле будет/не видеть на странице администратора, например 'ожидать (страница) .not_to has_content (" Welcome Mr Admin ")' или что-то на самом деле на странице входа в систему - если вы видите, что тогда да, вам нужно будет выяснить, почему люди автоматически вошли в админ. В противном случае, возможно, они находятся на странице входа в админ? –
Кроме того, точки стиля: используйте '&&' и '||' вместо 'and' и' or' (читайте, почему здесь: http://devblog.avdi.org/2010/08/02/using-and-and -or-in-ruby /) Во-вторых: 'current_user.admin == true' это довольно опасно ... что, если вы случайно забыли один из' = '- это трудная ошибка, и вы на самом деле не будете код для отказа ... просто чтобы все пользователи могли видеть страницу администратора. Это хорошая привычка * всегда * делать это вместо этого: 'true == current_user.admin' Это будет громко, если вы случайно используете' = 'вместо этого –