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

时间:2022-10-31 22:14:52

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. 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. The issue is that it seems like the controller action simply isn't... ACTING.

问题是我知道正在调用控制器排序操作,并且它正在获得正确的参数来完成它的工作。当我通过UI测试时,我可以看到一切正常,但它不会对我的测试进行排序。我可以看到(在控制器操作中使用“puts”)哈希正确地发送到控制器操作,因此运行良好。问题是控制器动作似乎不是......行动。

The question

How do I test this? I've tried inserting a "sleep 2" after the :post, :sort line in my spec. 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.

我该如何测试?我试过在我的规范中的post:sort行之后插入一个“sleep 2”。您可以看到我在该行前面添加了“xhr”,并且我尝试添加:format =>:js在该行的末尾(未显示)无济于事。

What I'm doing

我在做什么

I'm using JQuery UI's "sortable" plugin to sort jobs on a checklist on-screen. 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.

我正在使用JQuery UI的“可排序”插件来在屏幕上的清单中对作业进行排序。它目前效果很好,我可以通过更改屏幕上的顺序来“测试”这一点,然后刷新页面以查看现在所有内容都在正确的位置(我刚刚刷新之前将其移动到的位置)。显然,这不是严格的测试,但直到现在它已经足够好了。

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. See below in the "code" section for snippets of the models.

有Jobs,Checklists和ChecklistsJobs(联接表)。连接表具有“job_position”字段,该字段使用此排序进行更新。有关模型的片段,请参阅下面的“代码”部分。

Resources used to do this

用于执行此操作的资源

JQuery UI - Sortable

JQuery UI - 可排序

Railscast #147 Sortable Lists (revised)

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

Guard gem

Rails 3.2.11

ruby 1.9.3p374

rspec 2.13.1

Gems in :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

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

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

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

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

<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

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

1 个解决方案

#1


0  

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.

这是一个非常简单的答案:我在前面的块中构建的@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.

#1


0  

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.

这是一个非常简单的答案:我在前面的块中构建的@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.