require 'rails_helper' RSpec.describe ActiveAdmin::Views::AttributesTable do describe "creating with the dsl" do let(:helpers) { action_view } let(:post) do post = Post.new title: "Hello World", body: nil allow(post).to receive(:id){ 1 } allow(post).to receive(:new_record?){ false } post end let(:assigns){ { post: post } } # Loop through a few different ways to make the same table # and ensure that they produce the same results { "when attributes are passed in to the builder methods" => proc { render_arbre_component(assigns) { attributes_table_for post, :id, :title, :body } }, "when attributes are built using the block" => proc { render_arbre_component(assigns) { attributes_table_for post do rows :id, :title, :body end } }, "when each attribute is passed in by itself" => proc { render_arbre_component(assigns) { attributes_table_for post do row :id row :title row :body end } }, "when you create each row with a custom block" => proc { render_arbre_component(assigns) { attributes_table_for post do row("Id") { post.id } row("Title"){ post.title } row("Body") { post.body } end } }, "when you create each row with a custom block that returns nil" => proc { render_arbre_component(assigns) { attributes_table_for post do row("Id") { text_node post.id; nil } row("Title"){ text_node post.title; nil } row("Body") { text_node post.body; nil } end } }, }.each do |context_title, table_decleration| context context_title do let(:table) { instance_eval &table_decleration } it "should render a div wrapper with the class '.attributes_table'" do expect(table.tag_name).to eq 'div' expect(table.attr(:class)).to include('attributes_table') end it "should add id and type class" do expect(table.class_names).to include("post") expect(table.id).to eq "attributes_table_post_1" end it "should render 3 rows" do expect(table.find_by_tag("tr").size).to eq 3 end describe "rendering the rows" do [ ["Id" , "1"], ["Title" , "Hello World"], ["Body" , "Empty"] ].each_with_index do |(title, content), i| describe "for #{title}" do let(:current_row){ table.find_by_tag("tr")[i] } it "should have the title '#{title}'" do expect(current_row.find_by_tag("th").first.content).to eq title end it "should have the content '#{content}'" do expect(current_row.find_by_tag("td").first.content.chomp.strip).to eq content end end end end # describe rendering rows end end # describe dsl styles it "should add a class for each row based on the col name" do table = render_arbre_component(assigns) { attributes_table_for(post) do row :title row :created_at end } expect(table.find_by_tag("tr").first.to_s. split("\n").first.lstrip). to eq '' expect(table.find_by_tag("tr").last.to_s. split("\n").first.lstrip). to eq '' end it "should allow html options for the row itself" do table = render_arbre_component(assigns) { attributes_table_for(post) do row("Wee", class: "custom_row", style: "custom_style") { } end } expect(table.find_by_tag("tr").first.to_s.split("\n").first.lstrip). to eq '' end it "should allow html content inside the attributes table" do table = render_arbre_component(assigns) { attributes_table_for(post) do row("ID"){ span(post.id, class: 'id') } end } expect(table.find_by_tag("td").first.content.chomp.strip).to eq "1" end context 'an attribute ending in _id' do before do post.foo_id = 23 post.author = User.new username: 'john_doe', first_name: 'John', last_name: 'Doe' end it 'should call the association if one exists' do table = render_arbre_component assigns do attributes_table_for post, :author_id end expect(table.find_by_tag('th').first.content).to eq 'Author' expect(table.find_by_tag('td').first.content).to eq 'John Doe' end it 'should not attempt to call a nonexistant association' do table = render_arbre_component assigns do attributes_table_for post, :foo_id end expect(table.find_by_tag('th').first.content).to eq 'Foo' expect(table.find_by_tag('td').first.content).to eq '23' end end context "with a collection" do let(:posts) do [Post.new(title: "Hello World", id: 1), Post.new(title: "Multi Column", id: 2)].each_with_index do |post, index| allow(post).to receive(:id).and_return(index + 1) allow(post).to receive(:new_record?).and_return(false) end end let(:assigns) { { posts: posts } } let(:table) do render_arbre_component(assigns) do attributes_table_for posts, :id, :title end end it "does not set id on the table" do expect(table.attr(:id)).to eq nil end context "colgroup" do let(:cols) { table.find_by_tag "col" } it "contains a col for each record (plus headers)" do expect(cols.size).to eq (2 + 1) end it "assigns an id to each col" do cols[1..-1].each_with_index do |col, index| expect(col.id).to eq "attributes_table_post_#{index + 1}" end end it "assigns a class to each col" do cols[1..-1].each_with_index do |col, index| expect(col.class_names).to include("post") end end it "assigns alternation classes to each col" do cols[1..-1].each_with_index do |col, index| expect(col.class_names).to include(["even", "odd"][index % 2]) end end end context "when rendering the rows" do it "should contain 3 columns" do expect(table.find_by_tag("tr").first.children.size).to eq 3 end [ ["Id" , "1", "2"], ["Title", "Hello World", "Multi Column"], ].each_with_index do |set, i| describe "for #{set[0]}" do let(:title){ set[0] } let(:content){ set[1] } let(:current_row){ table.find_by_tag("tr")[i] } it "should have the title '#{set[0]}'" do expect(current_row.find_by_tag("th").first.content).to eq title end context "with defined attribute name translation" do it "should have the translated attribute name in the title" do with_translation activerecord: {attributes: {post: {title: 'Translated Title', id: 'Translated Id'}}} do expect(current_row.find_by_tag("th").first.content).to eq "Translated #{title}" end end end set[1..-1].each_with_index do |content, index| it "column #{index} should have the content '#{content}'" do expect(current_row.find_by_tag("td")[index].content.chomp.strip).to eq content end end end end end # describe rendering rows end # with a collection context "when using a single Hash" do let(:table) do render_arbre_component nil, helpers do attributes_table_for foo: 1, bar: 2 do row :foo row :bar end end end it "should render" do expect(table.find_by_tag("th")[0].content).to eq "Foo" expect(table.find_by_tag("th")[1].content).to eq "Bar" expect(table.find_by_tag("td")[0].content).to eq "1" expect(table.find_by_tag("td")[1].content).to eq "2" end end context "when using an Array of Hashes" do let(:table) do render_arbre_component nil, helpers do attributes_table_for [{foo: 1},{foo: 2}] do row :foo end end end it "should render" do expect(table.find_by_tag("th")[0].content).to eq "Foo" expect(table.find_by_tag("td")[0].content).to eq "1" expect(table.find_by_tag("td")[1].content).to eq "2" end end end end