简体   繁体   English

如何使用RSpec在我的Rails应用程序中测试JQuery-UI Sortable的控制器交互?

[英]How do I test JQuery-UI Sortable's controller interaction in my Rails app using RSpec?

The problem 问题

The problem is that I know the controller sort action is being called, and that it's getting the right params to do its thing. 问题是我知道正在调用控制器排序操作,并且它正在获取正确的参数来执行其操作。 I can see everything is working when I test through the UI, but it won't sort for my tests . 通过UI进行测试时,我可以看到一切正常,但是无法进行测试 I can see (using "puts" in the controller action) that the hash is being sent to the controller action correctly, so that's working well. 我可以看到(在控制器操作中使用“ puts”)哈希值已正确发送到控制器操作,因此可以正常工作。 The issue is that it seems like the controller action simply isn't... ACTING. 问题在于,似乎控制器的动作根本就不是... ACTING。

The question 问题

How do I test this? 我该如何测试? I've tried inserting a "sleep 2" after the :post, :sort line in my spec. 我尝试在规范中的:post,:sort行之后插入“ sleep 2”。 You can see I've added the "xhr" in front of that line, and I've tried adding :format => :js at the end of that line (not shown) to no avail. 您可以看到我已经在该行的前面添加了“ xhr”,并且尝试在该行的末尾添加:format =>:js(未显示)无济于事。

What I'm doing 我在做什么

I'm using JQuery UI's "sortable" plugin to sort jobs on a checklist on-screen. 我正在使用JQuery UI的“可排序”插件在屏幕上的清单上对作业进行排序。 It currently works well, and I can "test" this by just changing the order on screen, and then refreshing the page to see that everything is now in the correct spot (the spot I just moved things to before refreshing). 当前它运行良好,我可以通过更改屏幕顺序来“测试”,然后刷新页面以查看所有内容是否位于正确的位置(刷新之前我刚刚将内容移至该位置)。 Obviously, this isn't rigorous testing, but it's been good enough until now. 显然,这不是严格的测试,但是到目前为止已经足够了。

Now, I'm adding some logic to copy/archive the sorted items in the background, and I need to do some testing to make sure all the data is being manipulated properly when I do a sort. 现在,我添加了一些逻辑来在后台复制/归档已排序的项目,并且我需要进行一些测试以确保在执行排序时所有数据都被正确地操纵。 The old sort-refresh-check testing method won't work here because some stuff happens in the background, and that stuff doesn't show up on screen. 旧的排序刷新检查测试方法在这里不起作用,因为某些东西在后台发生,并且这些东西没有显示在屏幕上。 Before I write those tests, I wanted to write tests for the currently-working setup, but I can't get the tests to pass. 在编写这些测试之前,我想为当前正在使用的设置编写测试,但是我无法通过这些测试。

Notes on associations 关联说明

There are Jobs, Checklists, and ChecklistsJobs (the join table). 有作业,检查表和检查表工作(联接表)。 The join table has the "job_position" field that's being updated using this sort. 联接表具有“ job_position”字段,正在使用这种排序方式对其进行更新。 See below in the "code" section for snippets of the models. 有关模型的摘要,请参见下面的“代码”部分。

Resources used to do this 用于执行此操作的资源

JQuery UI - Sortable jQuery UI-可排序

Railscast #147 Sortable Lists (revised) Railscast#147可排序列表(修订版)

Guard gem 守护宝石

Rails 3.2.11 导轨3.2.11

ruby 1.9.3p374 红宝石1.9.3p374

rspec 2.13.1 规范2.13.1

Gems in :test :test中的宝石

gem "rspec-rails", :group => [:test, :development]
group :test do
  gem "factory_girl_rails", :require => false
  gem "capybara"
  gem "guard-rspec"
  gem 'rb-fsevent', '~> 0.9'
end

Code

job.rb job.rb

class Job < ActiveRecord::Base
  scope :archived_state, lambda {|s| where(:archived => s)}

  belongs_to :creator, :class_name => "Admin", :foreign_key => "creator_id"
  has_many :checklists_jobs, :dependent => :destroy
  has_many :checklists, :through => :checklists_jobs
.
.
.
end

checklist.rb checklist.rb

class Checklist < ActiveRecord::Base
  scope :archived_state, lambda {|s| where(:archived => s) }

  has_many :checklists_jobs, :dependent => :destroy, :order => 'checklists_jobs.job_position'#, :conditions => {'archived_at' => nil}
  has_many :jobs, :through => :checklists_jobs
.
.
.
end

checklists_job.rb checklists_job.rb

class ChecklistsJob < ActiveRecord::Base
  belongs_to :job
  belongs_to :checklist
  attr_accessible :job_position, :job_required
.
.
.
end

application.js application.js

$(function() {
    $('ul[id^="sortable"]').sortable({
        axis: 'y',
        handle: '.handle',
        update: function() {
            return $.post($(this).data('update-url'), $(this).sortable('serialize'));
          }
    });
});

Show.html.erb view Show.html.erb视图

<dd><ul class="unstyled" id="sortable" data-update-url="<%= sort_checklist_path(@checklist) %>">
  <% @checklist.checklists_jobs.archived_state(:false).each do |cj| %>
    <%= content_tag_for :li, cj do %><span class="handle"><i class="icon-move btn btn-mini"></i></span> <strong><%= cj.job.name %></strong><% if cj.job.description? %> - <%= cj.job.description %><% end %>
    <% end %>
  <% end %>
</ul></dd>

checklists_controller.rb checklists_controller.rb

def sort
  @checklist = Checklist.find(params[:id])
  params[:checklists_job].each_with_index do |id, index|
    @checklist.checklists_jobs.update_all({job_position: index+1}, {id: id})
  end
  render nothing: true
end

checklists_controller_spec.rb - I know this isn't super efficient user of space, but I broke everything out into individual lines to make sure I was setting everything up correctly. checklists_controller_spec.rb-我知道这不是超级有效的空间用户,但是我将所有内容分解为几行,以确保正确设置所有内容。

require 'spec_helper'

describe ChecklistsController do
  login_admin  
  describe "POST sort" do
    context "with no submission" do
      before do
        @checklist = FactoryGirl.create(:checklist)
        @job1 = FactoryGirl.create(:job)
        @job2 = FactoryGirl.create(:job)
        @job3 = FactoryGirl.create(:job)
        @job4 = FactoryGirl.create(:job)
        @checklist.jobs << [@job1, @job2, @job3, @job4]
        @checklist.save
        @cj1 = @checklist.checklists_jobs.find_by_job_id(@job1.id)
        @cj2 = @checklist.checklists_jobs.find_by_job_id(@job2.id)
        @cj3 = @checklist.checklists_jobs.find_by_job_id(@job3.id)
        @cj4 = @checklist.checklists_jobs.find_by_job_id(@job4.id)
        @cj1.job_position = 1
        @cj2.job_position = 2
        @cj3.job_position = 3
        @cj4.job_position = 4
        @cj1.save
        @cj2.save
        @cj3.save
        @cj4.save
        @attr = [@job4.id, @job3.id, @job2.id, @job1.id]        
      end

      # format of the params hash that's being passed:
      # {"checklists_job"=>["545", "544", "546", "547"], "id"=>"124"}

      it "sorts the checklist's checklists_jobs" do
        xhr :post, :sort, { :id => @checklist.id, :checklists_job => @attr }
        @checklist.reload
        # The test fails on the next line
        @checklist.checklists_jobs.find_by_job_id(@job1.id).job_position.should == 4
      end
    end
  end
end

Test results - Note that I've marked the failing line in the spec above 测试结果 -请注意,我已经在上面的规范中标记了失败的行

Failures:

  1) ChecklistsController POST sort with no submission sorts the checklist's checklists_jobs
     Failure/Error: @checklist.checklists_jobs.find_by_job_id(@job1.id).job_position.should == 4
       expected: 4
            got: 1 (using ==)
     # ./spec/controllers/checklists_controller_spec.rb:394:in `block (4 levels) in <top (required)>'

Finished in 2.59 seconds
51 examples, 1 failure

Failed examples:

rspec ./spec/controllers/checklists_controller_spec.rb:391 # ChecklistsController POST sort with no submission sorts the checklist's checklists_jobs

This is a pretty simple answer: The @attr array I was building in my before block was an array of job ids, and should've been an array of checklists_job ids. 这是一个非常简单的答案:我在before块中构建的@attr数组是作业ID的数组,应该是checklists_job ID的数组。

This: 这个:

@attr = [@job4.id, @job3.id, @job2.id, @job1.id] 

Should've been this: 应该是这样的:

@attr = [@cj4.id, @cj3.id, @cj2.id, @cj1.id]

Oops. 哎呀。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM