cleanup modules view logic

test plan:
- modules functionality should NOT have changed at all to the user

refs CYOE-234

Change-Id: I02dee3ba4c0d9f8712c920e04cefe05b43434f7c
Reviewed-on: https://gerrit.instructure.com/84327
Tested-by: Jenkins
Reviewed-by: Jeremy Stanley <jeremy@instructure.com>
QA-Review: Alex Morris <amorris@instructure.com>
Product-Review: Felix Milea-Ciobanu <fmileaciobanu@instructure.com>
This commit is contained in:
Felix Milea-Ciobanu 2016-07-05 09:04:56 -06:00
parent 3983e8da1c
commit 6fddd54915
6 changed files with 143 additions and 102 deletions

View File

@ -24,22 +24,37 @@ class ContextModulesController < ApplicationController
before_filter { |c| c.active_tab = "modules" }
module ModuleIndexHelper
include ContextModulesHelper
def load_module_file_details
attachment_tags = @context.module_items_visible_to(@current_user).where(content_type: 'Attachment').preload(:content => :folder)
attachment_tags.inject({}) do |items, file_tag|
items[file_tag.id] = {
id: file_tag.id,
content_id: file_tag.content_id,
content_details: content_details(file_tag, @current_user, :for_admin => true)
id: file_tag.id,
content_id: file_tag.content_id,
content_details: content_details(file_tag, @current_user, :for_admin => true)
}
items
end
end
def modules_cache_key
@modules_cache_key ||= begin
visible_assignments = @current_user.try(:assignment_and_quiz_visibilities, @context)
cache_key_items = [@context.cache_key, @can_edit, 'all_context_modules_draft_8', collection_cache_key(@modules), Time.zone, Digest::MD5.hexdigest(visible_assignments.to_s)]
cache_key = cache_key_items.join('/')
cache_key = add_menu_tools_to_cache_key(cache_key)
end
end
def load_modules
@modules = @context.modules_visible_to(@current_user)
@collapsed_modules = ContextModuleProgression.for_user(@current_user).for_modules(@modules).select([:context_module_id, :collapsed]).select{|p| p.collapsed? }.map(&:context_module_id)
@can_edit = can_do(@context, @current_user, :manage_content)
modules_cache_key
@menu_tools = {}
placements = [:assignment_menu, :discussion_topic_menu, :file_menu, :module_menu, :quiz_menu, :wiki_page_menu]
tools = ContextExternalTool.all_tools_for(@context, placements: placements,
@ -65,7 +80,6 @@ class ContextModulesController < ApplicationController
if @context.grants_right?(@current_user, session, :participate_as_student)
return unless tab_enabled?(@context.class::TAB_MODULES)
ActiveRecord::Associations::Preloader.new.preload(@modules, :content_tags)
@modules.each{|m| m.evaluate_for(@current_user) }
session[:module_progressions_initialized] = true
end

View File

@ -73,6 +73,44 @@ module ContextModulesHelper
item.content.can_unpublish?
end
def preload_modules_content(modules, can_edit)
ActiveRecord::Associations::Preloader.new.preload(modules, :content_tags => :content)
preload_can_unpublish(@context, @modules) if can_edit
end
def process_module_data(mod, is_cyoe_on = false, is_student = false, cyoe_data = nil)
# pre-calculated module view data can be added here
module_data = {
published_status: mod.published? ? 'published' : 'unpublished',
items: mod.content_tags_visible_to(@current_user).map
}
items_data = {}
module_data[:items].each do |item|
# pre-calculated module item view data can be added here
item_data = {
published_status: item.published? ? 'published' : 'unpublished'
}
if is_cyoe_on && is_student
item_data[:is_trigger_assignment] = cyoe_data ? cyoe_data.has_key?(item.id) : false
item_data[:is_in_conditional] = false # TODO: check against cyoe_data
# FIXME: use CYOE data to figure out if
if item.graded?
item_data[:has_submission] = item.content.submissions.length > 0 if defined? item.content.submissions
item_data[:has_submission] = item.content.quiz_submissions.length > 0 if defined? item.content.quiz_submissions
end
end
items_data[item.id] = item_data
end
module_data[:items_data] = items_data
return module_data
end
def module_item_translated_content_type(item)
return '' unless item

View File

@ -1,17 +1,16 @@
<% @body_classes << 'padless-content' %>
<% course_home ||= false %>
<%
@body_classes << 'padless-content'
course_home ||= false
js_env({
:COLLAPSED_MODULES => @collapsed_modules,
:CAN_MANAGE_MODULES => can_do(@context, @current_user, :manage_content),
:CAN_MANAGE_MODULES => @can_edit,
:IS_STUDENT => can_do(@context, @current_user, :participate_as_student),
:COURSE_ID => @context.id,
:NO_MODULE_PROGRESSIONS => @context.large_roster,
})
js_bundle :context_modules
css_bundle :content_next
%>
<% js_bundle :context_modules %>
<% css_bundle :content_next %>
<% if course_home %>
<div class="screenreader-only"><%= @context.name %></div>
<h2 class="context-modules-title screenreader-only"><%= t('headings.course_modules', %{Course Modules}) %></h2>
@ -20,7 +19,7 @@
<% end %>
<div class="header-bar">
<% if can_do(@context, @current_user, :manage_content) %>
<% if @can_edit %>
<div class="header-bar-right">
<a class="btn module_progressions_link" href="<%= progressions_course_context_modules_path(@context) %>"><%= t('links.student_progress', 'View Progress') %></a>
<button class="btn btn-primary add_module_link">
@ -32,7 +31,7 @@
<% end %>
</div>
<% if can_do(@context, @current_user, :manage_content) %>
<% if @can_edit %>
<div class="hidden-readable screenreader-only" aria-label="keyboard instructions">
<%= t('modules_keyboard_hint_updated',
'Warning: For improved accessibility in reordering Modules (or Module items), please use the Move To Dialog option found in the menu.') %>
@ -59,27 +58,21 @@ TEXT
<div
id="context_modules"
aria-label="<%= t('headings.course_modules', %{Course Modules}) %>"
class="ig-list <%= 'editable' if can_do(@context, @current_user, :manage_content) %>"
class="ig-list <%= 'editable' if @can_edit %>"
>
<% editable = can_do(@context, @current_user, :manage_content) %>
<% visible_assignments = @current_user.try(:assignment_and_quiz_visibilities, @context) %>
<% cache_key_items = [@context.cache_key, editable, 'all_context_modules_draft_9', collection_cache_key(@modules), Time.zone, Digest::MD5.hexdigest(visible_assignments.to_s)] %>
<% cache_key = cache_key_items.join('/') %>
<% cache_key = add_menu_tools_to_cache_key(cache_key) %>
<% cache(cache_key) do %>
<% ActiveRecord::Associations::Preloader.new.preload(@modules, :content_tags => :content) %>
<% preload_can_unpublish(@context, @modules) %>
<% cache(@modules_cache_key) do %>
<% preload_modules_content(@modules, @can_edit) %>
<% @modules.each do |m| %>
<%= render :partial => 'context_modules/context_module_next', :object => m, :locals => {:editable => editable} %>
<%= render :partial => 'context_modules/context_module_next', :object => m, :as => :context_module, :locals => { :editable => @can_edit } %>
<% end %>
<% end %>
</div>
</div>
<%= render :partial => 'context_modules/context_module_next', :object => nil %>
<%= render :partial => 'context_modules/module_item_next', :object => nil, :locals => {:editable => editable } %>
<%= render :partial => 'context_modules/context_module_next', :object => nil, :as => :context_module %>
<%= render :partial => 'context_modules/module_item_next', :object => nil, :as => :module_item, :locals => { :editable => @can_edit } %>
<% if can_do(@context, @current_user, :manage_content) %>
<% if @can_edit %>
<form id="move_context_module_form" style="display:none" class="form-dialog" title="Move Module">
<div class="form-dialog-content">
<h2><%= t('move_module.place', "Place ") %> <span id="move_module_name"> </span></h2>

View File

@ -1,14 +1,13 @@
<%
context_module_next ||= nil
context_module = context_module_next
context_module ||= context_module_next
module_data = context_module ? process_module_data(context_module) : { published_status: 'unpublished' }
editable ||= can_do(@context, @current_user, :manage_content)
workflow_state = context_module && context_module.workflow_state
published_status = context_module && context_module.published? ? 'published' : 'unpublished'
@modules ||= []
%>
<% cache_if_module(context_module, editable, @current_user, @context) do %>
<% cache_if_module(context_module, editable, @current_user, @context) do %>
<div
class="item-group-condensed context_module
<%= 'editable_context_module' if editable %>
@ -112,15 +111,15 @@
data-module-type="module"
data-id="<%= context_module && context_module.id %>"
data-course-id="<%= context_module && context_module.context_id %>"
data-published="<%= published_status == 'published' %>"
data-published="<%= module_data[:published_status] == 'published' %>"
data-publishable="<%= true %>"
data-publish-message="<%= t('Unpublished. Click to publish %{module_name}.', {module_name: context_module ? context_module.name : 'module'}) %>"
data-unpublish-message="<%= t('Published. Click to unpublish %{module_name}.', {module_name: context_module ? context_module.name : 'module'}) %>"
title=""
data-tooltip
class="publish-icon module <%= published_status %>"
class="publish-icon module <%= module_data[:published_status] %>"
>
<i class="icon-<%= published_status %>" alt="<%= published_status == 'published' ? t('published') : t('unpublished') %>"></i>
<i class="icon-<%= module_data[:published_status] %>" alt="<%= module_data[:published_status] == 'published' ? t('published') : t('unpublished') %>"></i>
</span>
<button
@ -163,9 +162,9 @@
<div class="content" id="context_module_content_<%= context_module && context_module.id %>">
<ul class="ig-list items context_module_items <%= 'manageable' if editable %>">
<% if context_module %>
<% context_module.content_tags_visible_to(@current_user).each do |tag| %>
<%= render :partial => 'context_modules/module_item_next', :object => tag, :locals => {:completion_criteria => context_module.completion_requirements, :editable => editable} %>
<% if context_module && module_data[:items] %>
<% module_data[:items].each do |item| %>
<%= render :partial => 'context_modules/module_item_next', :object => item, :as => :module_item, :locals => {:completion_criteria => context_module.completion_requirements, :item_data => module_data[:items_data][item.id], :editable => editable} %>
<% end %>
<% end %>
</ul>

View File

@ -1,38 +1,48 @@
<%
module_item_next ||= nil
module_item = module_item_next
published_status = (module_item && module_item.published?) ? 'published' : 'unpublished'
tag = module_item || nil; completion_criteria ||= nil; editable ||= false
@module_item_image_tags ||= {
'indent' => "<i class='icon-arrow-right'></i>".html_safe,
'outdent' => "<i class='icon-arrow-left'></i>".html_safe,
'edit' => "<i class='icon-edit'></i>".html_safe,
'delete' => "<i class='icon-end'></i>".html_safe,
}
%>
<% criterion = completion_criteria && completion_criteria.find{|c| c[:id] == tag.id} %>
module_item ||= module_item_next
item_data ||= { published_status: 'unpublished' }
completion_criteria ||= nil
editable ||= false
@module_item_image_tags ||= {
'indent' => "<i class='icon-arrow-right'></i>".html_safe,
'outdent' => "<i class='icon-arrow-left'></i>".html_safe,
'edit' => "<i class='icon-edit'></i>".html_safe,
'delete' => "<i class='icon-end'></i>".html_safe,
}
menu_type_to_class = {
:assignment_menu => Assignment,
:discussion_topic_menu => DiscussionTopic,
:file_menu => Attachment,
:quiz_menu => Quizzes::Quiz,
:wiki_page_menu => WikiPage
}
criterion = completion_criteria && completion_criteria.find{|c| c[:id] == module_item.id}
%>
<li
id="context_module_item_<%= tag ? tag.id : "blank" %>"
id="context_module_item_<%= module_item ? module_item.id : "blank" %>"
style="<%= hidden unless module_item %>"
class="
context_module_item
<%= module_item.content_type_class if module_item %>
<%= 'also_assignment' if module_item && module_item.graded? %>
indent_<%= tag.try_rescue(:indent) || '0' %>
indent_<%= module_item.try_rescue(:indent) || '0' %>
<%= 'progression_requirement' if criterion %>
<%= criterion[:type] if criterion %>_requirement
<%= module_item.item_class if module_item %>
"
>
<div class="ig-row <%= 'with-completion-requirements' if criterion %> <%= 'ig-published' if module_item && module_item.published? %>">
<a
aria-label='<%= tag && tag.title %>'
aria-label='<%= module_item && module_item.title %>'
tabindex="-1"
class="for-nvda"
href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>">
<%= tag && tag.title %>
href="<%= context_url(@context, :context_url) %>/modules/items/<%= module_item ? module_item.id : "{{ id }}" %>">
<%= module_item && module_item.title %>
</a>
<% if editable || module_item.nil? %>
@ -58,23 +68,22 @@
</span>
<div class="ig-info">
<div class="module-item-title">
<span class="item_name" aria-hidden="true">
<% if tag && tag.content_type == 'ExternalUrl' && tag.new_tab %>
<a aria-label='<%= tag.title %>' class="title external_url_link" target="_blank" href="<%= tag.url %>"
data-item-href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag.id %>"><%= tag.title %></a>
<% if module_item && module_item.content_type == 'ExternalUrl' && module_item.new_tab %>
<a aria-label='<%= module_item.title %>' class="title external_url_link" target="_blank" href="<%= module_item.url %>"
data-item-href="<%= context_url(@context, :context_url) %>/modules/items/<%= module_item.id %>"><%= module_item.title %></a>
<% else %>
<a title="<%= tag && tag.title %>" class="ig-title title"
href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>"><%= tag && tag.title %></a>
<a title="<%= module_item && module_item.title %>" class="ig-title title"
href="<%= context_url(@context, :context_url) %>/modules/items/<%= module_item ? module_item.id : "{{ id }}" %>"><%= module_item && module_item.title %></a>
<% end %>
<span title="<%= tag && tag.title %>" class="title locked_title"><%= tag && tag.title %></span>
<span class="points_possible" style="display: none;"><%= round_if_whole(tag.try_rescue(:assignment).try_rescue(:points_possible)) || nbsp %></span>
<span title="<%= module_item && module_item.title %>" class="title locked_title"><%= module_item && module_item.title %></span>
<span class="points_possible" style="display: none;"><%= round_if_whole(module_item.try_rescue(:assignment).try_rescue(:points_possible)) || nbsp %></span>
<span class="requirement" style="display: none;">&nbsp;</span>
<span class="completion_requirement" style="display: none;">&nbsp;</span>
<span class="position" style="display: none;"><%= tag && tag.position %></span>
<span class="url" style="display: none;"><%= tag.try(:url) if editable %></span>
<span class="new_tab" style="display: none;"><%= tag.try(:new_tab) ? '1' : '0' if editable %></span>
<span class="position" style="display: none;"><%= module_item && module_item.position %></span>
<span class="url" style="display: none;"><%= module_item.try(:url) if editable %></span>
<span class="new_tab" style="display: none;"><%= module_item.try(:new_tab) ? '1' : '0' if editable %></span>
</span>
</div>
@ -85,16 +94,14 @@
<span class="criterion_type" style="display: none;"><%= (criterion && criterion[:type]) || nbsp %></span>
</span>
<!-- /dead code -->
<span class="type" style="display: none;"><%= tag ? tag.content_type_class : nbsp %></span>
<span class="id" style="display: none;"><%= tag ? tag.id : nbsp %></span>
<span class="graded" style="display: none;"><%= tag && tag.graded? ? '1' : '0' %></span>
<span class="type" style="display: none;"><%= module_item ? module_item.content_type_class : nbsp %></span>
<span class="id" style="display: none;"><%= module_item ? module_item.id : nbsp %></span>
<span class="graded" style="display: none;"><%= module_item && module_item.graded? ? '1' : '0' %></span>
</div>
<div class="ig-details">
<div class="due_date_display ig-details__item"></div>
<div class="points_possible_display ig-details__item"></div>
<div class="requirement-description ig-details__item">
<span class="completion_requirement">
<span class="requirement_type min_score_requirement">
@ -158,64 +165,54 @@
<% if editable || module_item.nil? %>
<div class="ig-admin">
<span
data-module-item-name="<%= tag && tag.title %>"
data-module-item-name="<%= module_item && module_item.title %>"
data-module-type="<%= module_item && module_item.content_type_class %>"
data-content-id="<%= module_item && module_item.content_id %>"
data-id="<%= module_item_publishable_id(module_item) %>"
data-course-id="<%= module_item && module_item.context_id %>"
data-module-id="<%= module_item && module_item.context_module_id %>"
data-module-item-id="<%= module_item && module_item.id %>"
data-published="<%= module_item && published_status == 'published' %>"
data-published="<%= module_item && item_data[:published_status] == 'published' %>"
data-publishable="<%= module_item_publishable?(module_item) %>"
data-unpublishable="<%= module_item_unpublishable?(module_item) %>"
data-publish-message="<%= t('Unpublished. Click to publish %{item_name}.', {item_name: tag && tag.title ? tag.title : ''}) %>"
data-unpublish-message="<%= t('Published. Click to unpublish %{item_name}.', {item_name: tag && tag.title ? tag.title : ''}) %>"
data-publish-message="<%= t('Unpublished. Click to publish %{item_name}.', {item_name: module_item && module_item.title ? module_item.title : ''}) %>"
data-unpublish-message="<%= t('Published. Click to unpublish %{item_name}.', {item_name: module_item && module_item.title ? module_item.title : ''}) %>"
title=""
data-tooltip
class="publish-icon <%= published_status %>"
class="publish-icon <%= item_data[:published_status] %>"
>
<i class="icon-<%= published_status %>"></i>
<i class="icon-<%= item_data[:published_status] %>"></i>
</span>
<div class="inline-block cog-menu-container">
<a class="al-trigger al-trigger-gray" role="button" tabindex="0" href="#">
<i class="icon-settings"></i><i class="icon-mini-arrow-down"></i>
<span class="screenreader-only"><%= t('Manage %{item_name}', {item_name: tag && tag.title ? tag.title : 'item'}) %></span>
<span class="screenreader-only"><%= t('Manage %{item_name}', {item_name: module_item && module_item.title ? module_item.title : 'item'}) %></span>
</a>
<ul class="al-options">
<li role="presentation"><a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="outdent_item_link" title="<%= t('links.outdent_item', %{Decrease indent}) %>"><%= @module_item_image_tags['outdent'] %> <%= t('links.outdent', %{Decrease indent}) %></a></li>
<li role="presentation"><a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="indent_item_link" title="<%= t('links.indent_item', %{Increase indent}) %>"><%= @module_item_image_tags['indent'] %> <%= t('links.indent', %{Increase indent}) %></a></li>
<li role="presentation"><a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="edit_item_link edit_link" title="<%= t('links.edit_item_details', %{Edit item details}) %>"><%= @module_item_image_tags['edit'] %> <%= t('links.edit_item', %{Edit}) %></a></li>
<li role="presentation"><a href="<%= context_url(@context, :context_url) %>/modules/items/<%= module_item ? module_item.id : "{{ id }}" %>" class="outdent_item_link" title="<%= t('links.outdent_item', %{Decrease indent}) %>"><%= @module_item_image_tags['outdent'] %> <%= t('links.outdent', %{Decrease indent}) %></a></li>
<li role="presentation"><a href="<%= context_url(@context, :context_url) %>/modules/items/<%= module_item ? module_item.id : "{{ id }}" %>" class="indent_item_link" title="<%= t('links.indent_item', %{Increase indent}) %>"><%= @module_item_image_tags['indent'] %> <%= t('links.indent', %{Increase indent}) %></a></li>
<li role="presentation"><a href="<%= context_url(@context, :context_url) %>/modules/items/<%= module_item ? module_item.id : "{{ id }}" %>" class="edit_item_link edit_link" title="<%= t('links.edit_item_details', %{Edit item details}) %>"><%= @module_item_image_tags['edit'] %> <%= t('links.edit_item', %{Edit}) %></a></li>
<li role="presentation">
<a href="#<%= tag ? tag.id : "{{ id }}" %>"
<a href="#<%= module_item ? module_item.id : "{{ id }}" %>"
aria-label="<%= t('links.move_item_label', %{Move this item}) %>"
class="move_module_item_link icon-updown"
title="<%= t('links.move_item', %{Move this item}) %>"
><%= t('modules_item_move_to', "Move to...") %></a>
</li>
<li role="presentation"><a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="delete_item_link delete_link" title="<%= t('links.remove_item_from_module', %{Remove this item from the module}) %>"><%= @module_item_image_tags['delete'] %> <%= t('links.remove_item', %{Remove}) %></a></li>
<% menu_type_to_class = {
:assignment_menu => Assignment,
:discussion_topic_menu => DiscussionTopic,
:file_menu => Attachment,
:quiz_menu => Quizzes::Quiz,
:wiki_page_menu => WikiPage
}
%>
<li role="presentation"><a href="<%= context_url(@context, :context_url) %>/modules/items/<%= module_item ? module_item.id : "{{ id }}" %>" class="delete_item_link delete_link" title="<%= t('links.remove_item_from_module', %{Remove this item from the module}) %>"><%= @module_item_image_tags['delete'] %> <%= t('links.remove_item', %{Remove}) %></a></li>
<% menu_type_to_class.each do |menu_type, content_class| %>
<% if !tag || tag.content.is_a?(content_class) %>
<% if !module_item || module_item.content.is_a?(content_class) %>
<%
launch_options = {}
if menu_type == :file_menu
launch_options[:files] = [tag ? tag.content_id : "{{ content_id }}"]
launch_options[:files] = [module_item ? module_item.content_id : "{{ content_id }}"]
else
launch_options[:module_items] = [tag ? tag.id : "{{ id }}"]
launch_options[:module_items] = [module_item ? module_item.id : "{{ id }}"]
end
%>
<%= external_tools_menu_items(@menu_tools[menu_type], {link_class: "menu_tool_link", settings_key: menu_type, in_list: true, url_params: launch_options}) %>
<% end %>
<% end %>
</ul>

View File

@ -37,14 +37,14 @@ describe "/context_modules/index" do
it "should show content_tags" do
course
context_module = @course.context_modules.create!
content_tag = context_module.add_item :type => 'context_module_sub_header'
content_tag.publish! if content_tag.unpublished?
module_item = context_module.add_item :type => 'context_module_sub_header'
module_item.publish! if module_item.unpublished?
view_context(@course, @user)
assigns[:modules] = @course.context_modules.active
render 'context_modules/index'
expect(response).not_to be_nil
page = Nokogiri('<document>' + response.body + '</document>')
expect(page.css("#context_module_item_#{content_tag.id}").length).to eq 1
expect(page.css("#context_module_item_#{module_item.id}").length).to eq 1
end
it "should show unpublished content_tags" do
@ -54,8 +54,8 @@ describe "/context_modules/index" do
wiki_page.save!
context_module = @course.context_modules.create!
content_tag = context_module.add_item(:type => 'wiki_page', :id => wiki_page.id)
expect(content_tag.workflow_state).to eq 'unpublished'
module_item = context_module.add_item(:type => 'wiki_page', :id => wiki_page.id)
expect(module_item.workflow_state).to eq 'unpublished'
view_context(@course, @user)
assigns[:modules] = @course.context_modules.active
@ -63,19 +63,19 @@ describe "/context_modules/index" do
expect(response).not_to be_nil
page = Nokogiri('<document>' + response.body + '</document>')
expect(page.css("#context_module_item_#{content_tag.id}").length).to eq 1
expect(page.css("#context_module_item_#{module_item.id}").length).to eq 1
end
it "should not show deleted content_tags" do
course
context_module = @course.context_modules.create!
content_tag = context_module.add_item :type => 'context_module_sub_header'
content_tag.destroy
module_item = context_module.add_item :type => 'context_module_sub_header'
module_item.destroy
view_context(@course, @user)
assigns[:modules] = @course.context_modules.active
render 'context_modules/index'
expect(response).not_to be_nil
page = Nokogiri('<document>' + response.body + '</document>')
expect(page.css("#context_module_item_#{content_tag.id}").length).to eq 0
expect(page.css("#context_module_item_#{module_item.id}").length).to eq 0
end
end