{% include google-analytics.html %}
activeadmin-arbre-35697e3/docs/index.md 0000664 0000000 0000000 00000007010 15072460023 0017734 0 ustar 00root root 0000000 0000000 ---
redirect_from: /docs/documentation.html
---
# Arbre
HTML Views in Ruby
### Introduction
Arbre is a alternate template system for [Ruby on Rails Action View](http://guides.rubyonrails.org/action_view_overview.html).
Arbre expresses HTML using a Ruby DSL, which makes it similar to the [Builder](https://github.com/tenderlove/builder) gem for XML.
Arbre was extracted from [Active Admin](https://activeadmin.info/).
An example `index.html.arb`:
```ruby
html {
head {
title "Welcome page"
}
body {
para "Hello, world"
}
}
```
The purpose of Arbre is to leave the view as Ruby objects as long as possible,
which allows an object-oriented approach including inheritance, composition, and encapsulation.
### Installation
Add gem `arbre` to your `Gemfile` and `bundle install`.
Arbre registers itself as a Rails template handler for files with an extension `.arb`.
### Tags
Arbre DSL is composed of HTML tags. Tag attributes including `id` and HTML classes are passed as a hash parameter and the tag body is passed as a block. Most HTML5 tags are implemented, including `script`, `embed` and `video`.
A special case is the paragraph tag,
, which is mapped to `para`.
JavaScript can be included by using `script { raw ... }`
To include text that is not immediately part of a tag use `text_node`.
### Components
Arbre DSL can be extended by defining new tags composed of other, simpler tags.
This provides a simpler alternative to nesting partials.
The recommended approach is to subclass Arbre::Component and implement a new builder method.
The builder_method defines the method that will be called to build this component
when using the DSL. The arguments passed into the builder_method will be passed
into the #build method for you.
For example:
```ruby
class Panel < Arbre::Component
builder_method :panel
def build(title, attributes = {})
super(attributes)
h3(title, class: "panel-title")
end
end
```
By default, components are `div` tags. This can be overridden by redefining the `tag_name` method.
Several examples of Arbre components are [included in Active Admin](https://activeadmin.info/12-arbre-components.html)
### Contexts
An [Arbre::Context](http://www.rubydoc.info/gems/arbre/Arbre/Context) is an object in which Arbre DSL is interpreted, providing a root for the Ruby DOM that can be [searched and manipulated](http://www.rubydoc.info/gems/arbre/Arbre/Element). A context is automatically provided when a `.arb` template or partial is loaded. Contexts can be used when developing or testing a component. Contexts are rendered by calling to_s.
```ruby
html = Arbre::Context.new do
panel "Hello World", class: "panel", id: "my-panel" do
span "Inside the panel"
text_node "Plain text"
end
end
puts html.to_s # =>
```
```html
"
#
# The contents of the block are instance eval'd within the Context
# object. This means that you lose context to the outside world from
# within the block. To pass local variables into the Context, use the
# assigns param.
#
# html = Arbre::Context.new({one: 1}) do
# h1 "Your number #{one}"
# end
#
# html.to_s #=> "Your number 1"
#
class Context < Element
# Initialize a new Arbre::Context
#
# @param [Hash] assigns A hash of objects that you would like to be
# available as local variables within the Context
#
# @param [Object] helpers An object that has methods on it which will become
# instance methods within the context.
#
# @yield [] The block that will get instance eval'd in the context
def initialize(assigns = {}, helpers = nil, &block)
assigns = assigns || {}
@_assigns = assigns.symbolize_keys
@_helpers = helpers
@_current_arbre_element_buffer = [self]
super(self)
instance_eval(&block) if block
end
def arbre_context
self
end
def assigns
@_assigns
end
def helpers
@_helpers
end
def indent_level
# A context does not increment the indent_level
super - 1
end
def bytesize
cached_html.bytesize
end
alias :length :bytesize
def respond_to_missing?(method, include_all)
super || cached_html.respond_to?(method, include_all)
end
# Webservers treat Arbre::Context as a string. We override
# method_missing to delegate to the string representation
# of the html.
ruby2_keywords def method_missing(method, *args, &block)
if cached_html.respond_to? method
cached_html.send method, *args, &block
else
super
end
end
def current_arbre_element
@_current_arbre_element_buffer.last
end
def with_current_arbre_element(tag)
raise ArgumentError, "Can't be in the context of nil. #{@_current_arbre_element_buffer.inspect}" unless tag
@_current_arbre_element_buffer.push tag
yield
ensure
@_current_arbre_element_buffer.pop
end
alias_method :within, :with_current_arbre_element
private
# Caches the rendered HTML so that we don't re-render just to
# get the content length or to delegate a method to the HTML
def cached_html
if defined?(@cached_html)
@cached_html
else
html = to_s
@cached_html = html if html.length > 0
html
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/element.rb 0000664 0000000 0000000 00000007641 15072460023 0021204 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'arbre/element/builder_methods'
require 'arbre/element/proxy'
require 'arbre/element_collection'
module Arbre
class Element
include BuilderMethods
attr_reader :parent
attr_reader :children, :arbre_context
def initialize(arbre_context = Arbre::Context.new)
@arbre_context = arbre_context
@children = ElementCollection.new
@parent = nil
end
def assigns
arbre_context.assigns
end
def helpers
arbre_context.helpers
end
def tag_name
@tag_name ||= self.class.name.demodulize.downcase
end
def build(*args, &block)
# Render the block passing ourselves in
append_return_block(block.call(self)) if block
end
def add_child(child)
return unless child
if child.is_a?(Array)
child.each{|item| add_child(item) }
return @children
end
# If its not an element, wrap it in a TextNode
unless child.is_a?(Element)
child = Arbre::HTML::TextNode.from_string(child)
end
if child.respond_to?(:parent)
# Remove the child
child.parent.remove_child(child) if child.parent && child.parent != self
# Set ourselves as the parent
child.parent = self
end
@children << child
end
def remove_child(child)
child.parent = nil if child.respond_to?(:parent=)
@children.delete(child)
end
def <<(child)
add_child(child)
end
def children?
@children.any?
end
def parent=(parent)
@parent = parent
end
def parent?
!@parent.nil?
end
def ancestors
if parent?
[parent] + parent.ancestors
else
[]
end
end
# TODO: Shouldn't grab whole tree
def find_first_ancestor(type)
ancestors.find{|a| a.is_a?(type) }
end
def content=(contents)
clear_children!
add_child(contents)
end
def get_elements_by_tag_name(tag_name)
elements = ElementCollection.new
children.each do |child|
elements << child if child.tag_name == tag_name
elements.concat(child.get_elements_by_tag_name(tag_name))
end
elements
end
alias_method :find_by_tag, :get_elements_by_tag_name
def get_elements_by_class_name(class_name)
elements = ElementCollection.new
children.each do |child|
elements << child if child.class_list.include?(class_name)
elements.concat(child.get_elements_by_class_name(class_name))
end
elements
end
alias_method :find_by_class, :get_elements_by_class_name
def content
children.to_s
end
def html_safe
to_s
end
def indent_level
parent? ? parent.indent_level + 1 : 0
end
def each(&block)
[to_s].each(&block)
end
def inspect
to_s
end
def to_str
to_s
end
def to_s
content
end
def +(element)
case element
when Element, ElementCollection
else
element = Arbre::HTML::TextNode.from_string(element)
end
to_ary + element
end
def to_ary
ElementCollection.new [Proxy.new(self)]
end
alias_method :to_a, :to_ary
private
# Resets the Elements children
def clear_children!
@children.clear
end
# Implements the method lookup chain. When you call a method that
# doesn't exist, we:
#
# 1. Try to call the method on the current DOM context
# 2. Return an assigned variable of the same name
# 3. Call the method on the helper object
# 4. Call super
#
ruby2_keywords def method_missing(name, *args, &block)
if current_arbre_element.respond_to?(name)
current_arbre_element.send name, *args, &block
elsif assigns && assigns.has_key?(name)
assigns[name]
elsif helpers.respond_to?(name)
helpers.send(name, *args, &block)
else
super
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/element/ 0000775 0000000 0000000 00000000000 15072460023 0020647 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/lib/arbre/element/builder_methods.rb 0000664 0000000 0000000 00000004243 15072460023 0024350 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
class Element
module BuilderMethods
def self.included(klass)
klass.extend ClassMethods
end
module ClassMethods
def builder_method(method_name)
BuilderMethods.class_eval <<-EOF, __FILE__, __LINE__
def #{method_name}(*args, &block)
insert_tag ::#{self.name}, *args, &block
end
EOF
end
end
def build_tag(klass, *args, &block)
tag = klass.new(arbre_context)
tag.parent = current_arbre_element
with_current_arbre_element tag do
if block && block.arity > 0
tag.build(*args, &block)
else
tag.build(*args)
append_return_block(yield) if block
end
end
tag
end
def insert_tag(klass, *args, &block)
tag = build_tag(klass, *args, &block)
current_arbre_element.add_child(tag)
tag
end
def current_arbre_element
arbre_context.current_arbre_element
end
def with_current_arbre_element(tag, &block)
arbre_context.with_current_arbre_element(tag, &block)
end
alias_method :within, :with_current_arbre_element
private
# Appends the value to the current DOM element if there are no
# existing DOM Children and it responds to #to_s
def append_return_block(tag)
return nil if current_arbre_element.children?
if appendable_tag?(tag)
current_arbre_element << Arbre::HTML::TextNode.from_string(tag.to_s)
end
end
# Returns true if the object should be converted into a text node
# and appended into the DOM.
def appendable_tag?(tag)
# Array.new.to_s prints out an empty array ("[]"). In
# Arbre, we append the return value of blocks to the output, which
# can cause empty arrays to show up within the output. To get
# around this, we check if the object responds to #empty?
if tag.respond_to?(:empty?) && tag.empty?
false
else
!tag.is_a?(Arbre::Element) && tag.respond_to?(:to_s)
end
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/element/proxy.rb 0000664 0000000 0000000 00000001141 15072460023 0022352 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
class Element
class Proxy < BasicObject
undef_method :==
undef_method :equal?
def initialize(element)
@element = element
end
def respond_to?(method, include_all = false)
if method.to_s == 'to_ary'
false
else
super || @element.respond_to?(method, include_all)
end
end
def method_missing(method, *args, &block)
if method.to_s == 'to_ary'
super
else
@element.__send__ method, *args, &block
end
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/element_collection.rb 0000664 0000000 0000000 00000000615 15072460023 0023411 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
# Stores a collection of Element objects
class ElementCollection < Array
def +(other)
self.class.new(super)
end
def -(other)
self.class.new(super)
end
def &(other)
self.class.new(super)
end
def to_s
self.collect do |element|
element.to_s
end.join('').html_safe
end
end
end
activeadmin-arbre-35697e3/lib/arbre/html/ 0000775 0000000 0000000 00000000000 15072460023 0020162 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/lib/arbre/html/attributes.rb 0000664 0000000 0000000 00000001254 15072460023 0022677 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
module HTML
class Attributes < Hash
def to_s
flatten_hash.compact.map do |name, value|
"#{html_escape(name)}=\"#{html_escape(value)}\""
end.join ' '
end
protected
def flatten_hash(hash = self, old_path = [], accumulator = {})
hash.each do |key, value|
path = old_path + [key]
if value.is_a? Hash
flatten_hash(value, path, accumulator)
else
accumulator[path.join('-')] = value
end
end
accumulator
end
def html_escape(s)
ERB::Util.html_escape(s)
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/html/class_list.rb 0000664 0000000 0000000 00000000702 15072460023 0022646 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'set'
module Arbre
module HTML
# Holds a set of classes
class ClassList < Set
def self.build_from_string(class_names)
new.add(class_names)
end
def add(class_names)
class_names.to_s.split(" ").each do |class_name|
super(class_name)
end
self
end
alias :<< :add
def to_s
to_a.join(" ")
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/html/document.rb 0000664 0000000 0000000 00000001141 15072460023 0022322 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
module HTML
class Document < Tag
def build(*args)
super
build_head
build_body
end
def document
self
end
def tag_name
'html'
end
def doctype
''.html_safe
end
def to_s
doctype + super
end
protected
def build_head
@head = head do
meta "http-equiv": "Content-type", content: "text/html; charset=utf-8"
end
end
def build_body
@body = body
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/html/html5_elements.rb 0000664 0000000 0000000 00000003620 15072460023 0023435 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
module HTML
AUTO_BUILD_ELEMENTS = [
:a,
:abbr,
:address,
:area,
:article,
:aside,
:audio,
:b,
:base,
:bdi,
:bdo,
:blockquote,
:body,
:br,
:button,
:canvas,
:caption,
:cite,
:code,
:col,
:colgroup,
:command,
:data,
:datalist,
:dd,
:del,
:details,
:dfn,
:dialog,
:div,
:dl,
:dt,
:em,
:embed,
:fieldset,
:figcaption,
:figure,
:footer,
:form,
:h1,
:h2,
:h3,
:h4,
:h5,
:h6,
:head,
:header,
:hgroup,
:hr,
:html,
:i,
:iframe,
:img,
:input,
:ins,
:kbd,
:keygen,
:label,
:legend,
:li,
:link,
:main,
:map,
:mark,
:menu,
:menuitem,
:meta,
:meter,
:nav,
:noscript,
:object,
:ol,
:optgroup,
:option,
:output,
:param,
:picture,
:pre,
:progress,
:q,
:rp,
:rt,
:ruby,
:s,
:samp,
:script,
:search,
:section,
:select,
:slot,
:small,
:source,
:span,
:strong,
:style,
:sub,
:summary,
:sup,
:svg,
:table,
:tbody,
:td,
:template,
:textarea,
:tfoot,
:th,
:thead,
:time,
:title,
:tr,
:track,
:u,
:ul,
:var,
:video,
:wbr
]
HTML5_ELEMENTS = [ :p ] + AUTO_BUILD_ELEMENTS
AUTO_BUILD_ELEMENTS.each do |name|
class_eval <<-EOF
class #{name.to_s.capitalize} < Tag
builder_method :#{name}
end
EOF
end
class P < Tag
builder_method :para
end
end
end
activeadmin-arbre-35697e3/lib/arbre/html/tag.rb 0000664 0000000 0000000 00000010371 15072460023 0021264 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'erb'
module Arbre
module HTML
class Tag < Element
attr_reader :attributes
# See: https://html.spec.whatwg.org/multipage/syntax.html#void-elements
SELF_CLOSING_ELEMENTS = [ :area, :base, :br, :col, :embed, :hr, :img, :input, :keygen, :link,
:menuitem, :meta, :param, :source, :track, :wbr ]
def initialize(*)
super
@attributes = Attributes.new
end
def build(*args)
super
attributes = extract_arguments(args)
self.content = args.first if args.first
for_value = attributes[:for]
unless for_value.is_a?(String) || for_value.is_a?(Symbol)
set_for_attribute(attributes.delete(:for))
end
attributes.each do |key, value|
set_attribute(key, value)
end
end
def extract_arguments(args)
if args.last.is_a?(Hash)
args.pop
else
{}
end
end
def set_attribute(name, value)
@attributes[name.to_sym] = value
end
def get_attribute(name)
@attributes[name.to_sym]
end
alias :attr :get_attribute
def has_attribute?(name)
@attributes.has_key?(name.to_sym)
end
def remove_attribute(name)
@attributes.delete(name.to_sym)
end
def id
get_attribute(:id)
end
# Generates and id for the object if it doesn't exist already
def id!
return id if id
self.id = object_id.to_s
id
end
def id=(id)
set_attribute(:id, id)
end
def add_class(class_names)
class_list.add class_names
end
def remove_class(class_names)
class_list.delete(class_names)
end
# Returns a string of classes
def class_names
class_list.to_s
end
def class_list
list = get_attribute(:class)
case list
when ClassList
list
when String
set_attribute(:class, ClassList.build_from_string(list))
else
set_attribute(:class, ClassList.new)
end
end
def to_s
indent(opening_tag, content, closing_tag).html_safe
end
private
def opening_tag
"<#{tag_name}#{attributes_html}>"
end
def closing_tag
"#{tag_name}>"
end
INDENT_SIZE = 2
def indent(open_tag, child_content, close_tag)
spaces = ' ' * indent_level * INDENT_SIZE
html = +""
if no_child? || child_is_text?
if self_closing_tag?
html << spaces << open_tag.sub( />$/, '/>' )
else
# one line
html << spaces << open_tag << child_content << close_tag
end
else
# multiple lines
html << spaces << open_tag << "\n"
html << child_content # the child takes care of its own spaces
html << spaces << close_tag
end
html << "\n"
end
def self_closing_tag?
SELF_CLOSING_ELEMENTS.include?(tag_name.to_sym)
end
def no_child?
children.empty?
end
def child_is_text?
children.size == 1 && children.first.is_a?(TextNode)
end
def attributes_html
" #{attributes}" if attributes.any?
end
def set_for_attribute(record)
return unless record
# set_attribute :id, ActionController::RecordIdentifier.dom_id(record, default_id_for_prefix)
# add_class ActionController::RecordIdentifier.dom_class(record)
set_attribute :id, dom_id_for(record)
add_class dom_class_name_for(record)
end
def dom_class_name_for(record)
if record.class.respond_to?(:model_name)
record.class.model_name.singular
else
record.class.name.underscore.tr("/", "_")
end
end
def dom_id_for(record)
id = if record.respond_to?(:to_key)
record.to_key
elsif record.respond_to?(:id)
record.id
else
record.object_id
end
[default_id_for_prefix, dom_class_name_for(record), id].compact.join("_")
end
def default_id_for_prefix
nil
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/html/text_node.rb 0000664 0000000 0000000 00000001131 15072460023 0022474 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'erb'
module Arbre
module HTML
class TextNode < Element
builder_method :text_node
# Builds a text node from a string
def self.from_string(string)
node = new
node.build(string)
node
end
def add_child(*args)
raise "TextNodes do not have children"
end
def build(string)
@content = string
end
def class_list
[]
end
def tag_name
nil
end
def to_s
ERB::Util.html_escape(@content.to_s)
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/rails/ 0000775 0000000 0000000 00000000000 15072460023 0020330 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/lib/arbre/rails/forms.rb 0000664 0000000 0000000 00000004224 15072460023 0022005 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
module Rails
module Forms
class FormBuilderProxy < Arbre::Component
attr_reader :form_builder
# Since label and select are Arbre Elements already, we must
# override it here instead of letting method_missing
# deal with it
def label(*args)
proxy_call_to_form :label, *args
end
def select(*args)
proxy_call_to_form :select, *args
end
def respond_to_missing?(method, include_all)
if form_builder && form_builder.respond_to?(method, include_all)
true
else
super
end
end
private
def proxy_call_to_form(method, *args, &block)
text_node form_builder.send(method, *args, &block)
end
ruby2_keywords def method_missing(method, *args, &block)
if form_builder && form_builder.respond_to?(method)
proxy_call_to_form(method, *args, &block)
else
super
end
end
end
class FormForProxy < FormBuilderProxy
builder_method :form_for
def build(resource, form_options = {}, &block)
form_string = helpers.form_for(resource, form_options) do |f|
@form_builder = f
end
@opening_tag, @closing_tag = split_string_on(form_string, "")
super(&block)
end
def fields_for(*args, &block)
insert_tag FieldsForProxy, form_builder, *args, &block
end
def split_string_on(string, match)
return "" unless string && match
part_1 = string.split(Regexp.new("#{match}\\z")).first
[part_1, match]
end
def opening_tag
@opening_tag || ""
end
def closing_tag
@closing_tag || ""
end
end
class FieldsForProxy < FormBuilderProxy
def build(form_builder, *args, &block)
form_builder.fields_for(*args) do |f|
@form_builder = f
end
super(&block)
end
def to_s
children.to_s
end
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/rails/rendering.rb 0000664 0000000 0000000 00000000530 15072460023 0022630 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
module Rails
module Rendering
def render(*args, &block)
rendered = helpers.render(*args, &block)
case rendered
when Arbre::Context
current_arbre_element.add_child rendered
else
text_node rendered
end
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/rails/template_handler.rb 0000664 0000000 0000000 00000000461 15072460023 0024166 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
module Rails
class TemplateHandler
def call(template, source = nil)
source = template.source unless source
<<-END
Arbre::Context.new(assigns, self) {
#{source}
}.to_s
END
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/railtie.rb 0000664 0000000 0000000 00000000677 15072460023 0021206 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require_relative 'rails/template_handler'
require_relative 'rails/forms'
require_relative 'rails/rendering'
require 'rails'
Arbre::Element.include(Arbre::Rails::Rendering)
module Arbre
class Railtie < ::Rails::Railtie
initializer "arbre" do
ActiveSupport.on_load(:action_view) do
ActionView::Template.register_template_handler :arb, Arbre::Rails::TemplateHandler.new
end
end
end
end
activeadmin-arbre-35697e3/lib/arbre/version.rb 0000664 0000000 0000000 00000000103 15072460023 0021222 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Arbre
VERSION = "2.2.1"
end
activeadmin-arbre-35697e3/spec/ 0000775 0000000 0000000 00000000000 15072460023 0016307 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/spec/arbre/ 0000775 0000000 0000000 00000000000 15072460023 0017402 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/spec/arbre/integration/ 0000775 0000000 0000000 00000000000 15072460023 0021725 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/spec/arbre/integration/html_spec.rb 0000664 0000000 0000000 00000011006 15072460023 0024226 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre do
let(:helpers){ nil }
let(:assigns){ {} }
it "renders a single element" do
expect(arbre {
span "Hello World"
}.to_s).to eq("Hello World\n")
end
it "renders a child element" do
expect(arbre {
span do
span "Hello World"
end
}.to_s).to eq <<~HTML
Hello World
HTML
end
it "renders an unordered list" do
expect(arbre {
ul do
li "First"
li "Second"
li "Third"
end
}.to_s).to eq <<~HTML
First
Second
Third
HTML
end
it "allows local variables inside the tags" do
expect(arbre {
first = "First"
second = "Second"
ul do
li first
li second
end
}.to_s).to eq <<~HTML
First
Second
HTML
end
it "adds children and nested" do
expect(arbre {
div do
ul
li do
li
end
end
}.to_s).to eq <<~HTML
HTML
end
it "passes the element in to the block if asked for" do
expect(arbre {
div do |d|
d.ul do
li
end
end
}.to_s).to eq <<~HTML
HTML
end
it "moves content tags between parents" do
expect(arbre {
div do
span(ul(li))
end
}.to_s).to eq <<~HTML
HTML
end
it "adds content to the parent if the element is passed into block" do
expect(arbre {
div do |d|
d.id = "my-tag"
ul do
li
end
end
}.to_s).to eq <<~HTML
HTML
end
it "has the parent set on it" do
list, item = nil
arbre {
list = ul do
li "Hello"
item = li "World"
end
}
expect(item.parent).to eq list
end
it "sets a string content return value with no children" do
expect(arbre {
li do
"Hello World"
end
}.to_s).to eq <<~HTML
Hello World
HTML
end
it "turns string return values into text nodes" do
node = nil
arbre {
list = li do
"Hello World"
end
node = list.children.first
}
expect(node).to be_a described_class::HTML::TextNode
end
it "does not render blank arrays" do
expect(arbre {
tbody do
[]
end
}.to_s).to eq <<~HTML
HTML
end
describe "self-closing nodes" do
it "does not self-close script tags" do
expect(arbre {
script type: 'text/javascript'
}.to_s).to eq("\n")
end
it "self-closes meta tags" do
expect(arbre {
meta content: "text/html; charset=utf-8"
}.to_s).to eq("\n")
end
it "self-closes link tags" do
expect(arbre {
link rel: "stylesheet"
}.to_s).to eq("\n")
end
described_class::HTML::Tag::SELF_CLOSING_ELEMENTS.each do |tag|
it "self-closes #{tag} tags" do
expect(arbre {
send(tag)
}.to_s).to eq("<#{tag}/>\n")
end
end
end
describe "html safe" do
it "escapes the contents" do
expect(arbre {
span(" ")
}.to_s).to eq <<~HTML
<br />
HTML
end
it "returns html safe strings" do
expect(arbre {
span(" ")
}.to_s).to be_html_safe
end
it "does not escape html passed in" do
expect(arbre {
span(span(" "))
}.to_s).to eq <<~HTML
<br />
HTML
end
it "escapes string contents when passed in block" do
expect(arbre {
span {
span {
" "
}
}
}.to_s).to eq <<~HTML
<br />
HTML
end
it "escapes the contents of attributes" do
expect(arbre {
span(class: " ")
}.to_s).to eq <<~HTML
HTML
end
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/ 0000775 0000000 0000000 00000000000 15072460023 0020361 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/spec/arbre/unit/component_spec.rb 0000664 0000000 0000000 00000001625 15072460023 0023726 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
# A mock subclass to play with
class MockComponent < Arbre::Component
builder_method :mock_component
def build
h2 "Hello World"
end
end
describe Arbre::Component do
let(:assigns) { {} }
let(:helpers) { nil }
let(:component_class) { MockComponent }
let(:component) { component_class.new }
it "is a subclass of an html div" do
expect(described_class.ancestors).to include(Arbre::HTML::Div)
end
it "renders to a div, even as a subclass" do
expect(component.tag_name).to eq('div')
end
it "does not have a class list" do
expect(component.class_list.to_s).to eq("")
expect(component.class_list.empty?).to be(true)
end
it "renders the object using the builder method name" do
expect(arbre {
mock_component
}.to_s).to eq <<~HTML
Hello World
HTML
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/context_spec.rb 0000664 0000000 0000000 00000002422 15072460023 0023404 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre::Context do
let(:context) do
described_class.new do
h1 "札幌市北区" # Add some HTML to the context
end
end
it "does not increment the indent_level" do
expect(context.indent_level).to eq(-1)
end
it "returns a bytesize" do
expect(context.bytesize).to eq(25)
end
it "returns a length" do
expect(context.length).to eq(25)
end
it "delegates missing methods to the html string" do
expect(context).to respond_to(:index)
expect(context.index('<')).to eq(0)
end
it "uses a cached version of the HTML for method delegation" do
expect(context).to receive(:to_s).once.and_return("
札幌市北区
")
expect(context.index('<')).to eq(0)
expect(context.index('<')).to eq(0)
end
context "when an error is raised in a nested block" do
let(:context) do
described_class.new do
ul do
li do
'item one'
end
li do
raise 'error talking to the db'
end
end
rescue StandardError
para 'Uh oh! DB call failed'
end
end
it "properly resets the element buffer" do
expect(context.current_arbre_element).to be_a(described_class)
end
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/element_finder_methods_spec.rb 0000664 0000000 0000000 00000006111 15072460023 0026422 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre::Element, "Finder Methods" do
let(:assigns){ {} }
let(:helpers){ {} }
describe "finding elements by tag name" do
it "returns 0 when no elements exist" do
expect(arbre {
div
}.get_elements_by_tag_name("li").size).to eq(0)
end
it "returns a child element" do
html = arbre do
ul
li
ul
end
elements = html.get_elements_by_tag_name("li")
expect(elements.size).to eq(1)
expect(elements[0]).to be_instance_of(Arbre::HTML::Li)
end
it "returns multiple child elements" do
html = arbre do
ul
li
ul
li
end
elements = html.get_elements_by_tag_name("li")
expect(elements.size).to eq(2)
expect(elements[0]).to be_instance_of(Arbre::HTML::Li)
expect(elements[1]).to be_instance_of(Arbre::HTML::Li)
end
it "returns children's child elements" do
html = arbre do
ul
li do
li
end
end
elements = html.get_elements_by_tag_name("li")
expect(elements.size).to eq(2)
expect(elements[0]).to be_instance_of(Arbre::HTML::Li)
expect(elements[1]).to be_instance_of(Arbre::HTML::Li)
expect(elements[1].parent).to eq(elements[0])
end
end
#TODO: describe "finding an element by id"
describe "finding an element by a class name" do
it "returns 0 when no elements exist" do
expect(arbre {
div
}.get_elements_by_class_name("my_class").size).to eq(0)
end
it "allows text nodes on tree" do
expect(arbre {
text_node "text"
}.get_elements_by_class_name("my_class").size).to eq(0)
end
it "returns a child element" do
html = arbre do
div class: "some_class"
div class: "my_class"
end
elements = html.get_elements_by_class_name("my_class")
expect(elements.size).to eq(1)
expect(elements[0]).to be_instance_of(Arbre::HTML::Div)
end
it "returns multiple child elements" do
html = arbre do
div class: "some_class"
div class: "my_class"
div class: "my_class"
end
elements = html.get_elements_by_class_name("my_class")
expect(elements.size).to eq(2)
expect(elements[0]).to be_instance_of(Arbre::HTML::Div)
expect(elements[1]).to be_instance_of(Arbre::HTML::Div)
end
it "returns elements that match one of several classes" do
html = arbre do
div class: "some_class this_class"
div class: "some_class"
div class: "other_class"
end
elements = html.get_elements_by_class_name("this_class")
expect(elements.size).to eq(1)
expect(elements[0]).to be_instance_of(Arbre::HTML::Div)
end
it "returns a grandchild element" do
html = arbre do
div class: "some_class" do
div class: "my_class"
end
end
elements = html.get_elements_by_class_name("my_class")
expect(elements.size).to eq(1)
expect(elements[0]).to be_instance_of(Arbre::HTML::Div)
end
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/element_spec.rb 0000664 0000000 0000000 00000016347 15072460023 0023364 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre::Element do
let(:element){ described_class.new }
context "when initialized" do
it "has no children" do
expect(element.children).to be_empty
end
it "has no parent" do
expect(element.parent).to be_nil
end
it "responds to the HTML builder methods" do
expect(element).to respond_to(:span)
end
it "has a set of local assigns" do
context = Arbre::Context.new hello: "World"
element = described_class.new(context)
expect(element.assigns[:hello]).to eq("World")
end
it "has an empty hash with no local assigns" do
expect(element.assigns).to eq({})
end
end
describe "passing in a helper object" do
let(:helper) do
Class.new do
def helper_method
"helper method"
end
end
end
let(:element){ described_class.new(Arbre::Context.new(nil, helper.new)) }
it "calls methods on the helper object and return TextNode objects" do
expect(element.helper_method).to eq("helper method")
end
it "raises a NoMethodError if not found" do
expect {
element.a_method_that_doesnt_exist
}.to raise_error(NoMethodError)
end
end
describe "passing in assigns" do
let(:post) { double }
let(:assigns){ {post: post} }
it "is accessible via a method call" do
element = described_class.new(Arbre::Context.new(assigns))
expect(element.post).to eq(post)
end
end
it "to_a.flatten should not infinitely recurse" do
expect {
Timeout.timeout(1) do
element.to_a.flatten
end
}.not_to raise_error
end
describe "adding a child" do
let(:child){ described_class.new }
before do
element.add_child child
end
it "adds the child to the parent" do
expect(element.children.first).to eq(child)
end
it "sets the parent of the child" do
expect(child.parent).to eq(element)
end
context "when the child is nil" do
let(:child){ nil }
it "does not add the child" do
expect(element.children).to be_empty
end
end
context "when the child is a string" do
let(:child){ "Hello World" }
it "adds as a TextNode" do
expect(element.children.first).to be_instance_of(Arbre::HTML::TextNode)
expect(element.children.first.to_s).to eq("Hello World")
end
end
end
describe "setting the content" do
context "when a string" do
before do
element.add_child "Hello World"
element.content = "Goodbye"
end
it "clears the existing children" do
expect(element.children.size).to eq(1)
end
it "adds the string as a child" do
expect(element.children.first.to_s).to eq("Goodbye")
end
it "htmls escape the string" do
string = "Goodbye "
element.content = string
expect(element.content.to_s).to eq("Goodbye <br />")
end
end
context "when an element" do
let(:content_element){ described_class.new }
before do
element.content = content_element
end
it "sets the content tag" do
expect(element.children.first).to eq(content_element)
end
it "sets the tags parent" do
expect(content_element.parent).to eq(element)
end
end
context "when an array of tags" do
let(:first){ described_class.new }
let(:second){ described_class.new }
before do
element.content = [first, second]
end
it "sets the content tag" do
expect(element.children.first).to eq(first)
end
it "sets the tags parent" do
expect(element.children.first.parent).to eq(element)
end
end
end
describe "rendering to html" do
before { @separator = $, }
after { $, = @separator } # rubocop:disable RSpec/InstanceVariable
let(:collection){ element + "hello world" }
it "renders the children collection" do
expect(element.children).to receive(:to_s).and_return("content")
expect(element.to_s).to eq("content")
end
it "renders collection when is set the default separator" do
suppressing_27_warning { $, = "_" }
expect(collection.to_s).to eq("hello world")
end
it "renders collection when is not set the default separator" do
expect(collection.to_s).to eq("hello world")
end
private
def suppressing_27_warning
return yield unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.a")
begin
old_verbose = $VERBOSE
$VERBOSE = nil
yield
ensure
$VERBOSE = old_verbose
end
end
end
describe "adding elements together" do
context "when both elements are tags" do
let(:first){ described_class.new }
let(:second){ described_class.new }
let(:collection){ first + second }
it "returns an instance of Collection" do
expect(collection).to be_an_instance_of(Arbre::ElementCollection)
end
it "returns the elements in the collection" do
expect(collection.size).to eq(2)
expect(collection.first).to eq(first)
expect(collection[1]).to eq(second)
end
end
context "when the left is a collection and the right is a tag" do
let(:first){ described_class.new }
let(:second){ described_class.new }
let(:third){ described_class.new }
let(:collection){ Arbre::ElementCollection.new([first, second]) + third }
it "returns an instance of Collection" do
expect(collection).to be_an_instance_of(Arbre::ElementCollection)
end
it "returns the elements in the collection flattened" do
expect(collection.size).to eq(3)
expect(collection[0]).to eq(first)
expect(collection[1]).to eq(second)
expect(collection[2]).to eq(third)
end
end
context "when the right is a collection and the left is a tag" do
let(:first){ described_class.new }
let(:second){ described_class.new }
let(:third){ described_class.new }
let(:collection){ first + Arbre::ElementCollection.new([second,third]) }
it "returns an instance of Collection" do
expect(collection).to be_an_instance_of(Arbre::ElementCollection)
end
it "returns the elements in the collection flattened" do
expect(collection.size).to eq(3)
expect(collection[0]).to eq(first)
expect(collection[1]).to eq(second)
expect(collection[2]).to eq(third)
end
end
context "when the left is a tag and the right is a string" do
let(:element){ described_class.new }
let(:collection){ element + "Hello World"}
it "returns an instance of Collection" do
expect(collection).to be_an_instance_of(Arbre::ElementCollection)
end
it "returns the elements in the collection" do
expect(collection.size).to eq(2)
expect(collection[0]).to eq(element)
expect(collection[1]).to be_an_instance_of(Arbre::HTML::TextNode)
end
end
context "when the left is a string and the right is a tag" do
let(:collection){ "hello World" + described_class.new}
it "returns a string" do
expect(collection.strip.chomp).to eq("hello World")
end
end
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/html/ 0000775 0000000 0000000 00000000000 15072460023 0021325 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/spec/arbre/unit/html/class_list_spec.rb 0000664 0000000 0000000 00000000535 15072460023 0025027 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre::HTML::ClassList do
describe ".build_from_string" do
it "builds a new list from a string of classes" do
list = described_class.build_from_string("first second")
expect(list.size).to eq(2)
expect(list).to match_array(%w{first second})
end
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/html/document_spec.rb 0000664 0000000 0000000 00000000451 15072460023 0024502 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre::HTML::Document do
let(:document){ described_class.new }
describe "#to_s" do
subject { document.to_s }
before do
document.build
end
it { is_expected.to eq "\n" }
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/html/tag_attributes_spec.rb 0000664 0000000 0000000 00000006371 15072460023 0025714 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre::HTML::Tag, "Attributes" do
let(:tag){ described_class.new }
describe "attributes" do
before { tag.build id: "my_id" }
it "has an attributes hash" do
expect(tag.attributes).to eq({id: "my_id"})
end
describe "#to_s" do
it "renders the attributes to html" do
expect(tag.to_s).to eq "\n"
end
it "renders attributes that are empty but not nil" do
tag.class_list # initializes an empty ClassList
tag.set_attribute :foo, ''
tag.set_attribute :bar, nil
expect(tag.to_s).to eq "\n"
end
context "with hyphenated attributes" do
before { tag.build id: "my_id", "data-method" => "get", "data-remote" => true }
it "renders the attributes to html" do
expect(tag.to_s).to eq "\n"
end
end
context "when there is a nested attribute" do
before { tag.build id: "my_id", data: { action: 'some_action' } }
it "flattens the attributes when rendering to html" do
expect(tag.to_s).to eq "\n"
end
it "renders attributes that are empty but not nil" do
tag.class_list # initializes an empty ClassList
tag.set_attribute :foo, { bar: '' }
tag.set_attribute :bar, { baz: nil }
expect(tag.to_s).to eq "\n"
end
end
context "when there is a deeply nested attribute" do
before { tag.build id: "my_id", foo: { bar: { bat: nil, baz: 'foozle' } } }
it "flattens the attributes when rendering to html" do
expect(tag.to_s).to eq "\n"
end
end
context "when there are multiple nested attributes" do
before { tag.build id: "my_id", foo: { bar: 'foozle1', bat: nil, baz: '' } }
it "flattens the attributes when rendering to html" do
expect(tag.to_s).to eq "\n"
end
end
end
it "gets an attribute value" do
expect(tag.attr(:id)).to eq("my_id")
end
describe "#has_attribute?" do
context "when the attribute exists" do
it "returns true" do
expect(tag.has_attribute?(:id)).to be(true)
end
end
context "when the attribute does not exist" do
it "returns false" do
expect(tag.has_attribute?(:class)).to be(false)
end
end
end
it "removes an attribute" do
expect(tag.attributes).to eq({id: "my_id"})
expect(tag.remove_attribute(:id)).to eq("my_id")
expect(tag.attributes).to eq({})
end
end
describe "rendering attributes" do
it "escapes attribute values" do
tag.set_attribute(:class, '">bad things!')
expect(tag.to_s).to eq "\n"
end
it "escapes attribute names" do
tag.set_attribute(">bad", "things")
expect(tag.to_s).to eq "\n"
end
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/html/tag_spec.rb 0000664 0000000 0000000 00000005661 15072460023 0023447 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre::HTML::Tag do
let(:tag){ described_class.new }
describe "building a new tag" do
before { tag.build "Hello World", id: "my_id" }
it "sets the contents to a string" do
expect(tag.content).to eq("Hello World")
end
it "sets the hash of options to the attributes" do
expect(tag.attributes).to eq({ id: "my_id" })
end
end
describe "creating a tag 'for' an object" do
# rubocop:disable RSpec/VerifiedDoubles
let(:model_name){ double(singular: "resource_class")}
let(:resource_class){ double(model_name: model_name) }
let(:resource){ double(class: resource_class, to_key: ['5'])}
# rubocop:enable RSpec/VerifiedDoubles
before do
tag.build for: resource
end
it "sets the id to the type and id" do
expect(tag.id).to eq("resource_class_5")
end
it "adds a class name" do
expect(tag.class_list).to include("resource_class")
end
describe "for an object that doesn't have a model_name" do
let(:resource_class){ double(name: 'ResourceClass') } # rubocop:disable RSpec/VerifiedDoubles
before do
tag.build for: resource
end
it "sets the id to the type and id" do
expect(tag.id).to eq("resource_class_5")
end
it "adds a class name" do
expect(tag.class_list).to include("resource_class")
end
end
describe "with a default_id_for_prefix" do
let(:tag) do
Class.new(Arbre::HTML::Tag) do
def default_id_for_prefix
"a_prefix"
end
end.new
end
it "sets the id to the type and id" do
expect(tag.id).to eq("a_prefix_resource_class_5")
end
end
end
describe "creating a tag with a for attribute" do
it "sets the `for` attribute when a string is given" do
tag.build for: "email"
expect(tag.attributes[:for]).to eq "email"
end
it "sets the `for` attribute when a symbol is given" do
tag.build for: :email
expect(tag.attributes[:for]).to eq :email
end
end
describe "css class names" do
it "adds a class" do
tag.add_class "hello_world"
expect(tag.class_names).to eq("hello_world")
end
it "removes classes" do
tag.add_class "hello_world"
expect(tag.class_names).to eq("hello_world")
tag.remove_class "hello_world"
expect(tag.class_names).to eq("")
end
it "does not add a class if it already exists" do
tag.add_class "hello_world"
tag.add_class "hello_world"
expect(tag.class_names).to eq("hello_world")
end
it "separates classes with space" do
tag.add_class "hello world"
expect(tag.class_list.size).to eq(2)
end
it "creates a class list from a string" do
tag = described_class.new
tag.build(class: "first-class")
tag.add_class "second-class"
expect(tag.class_list.size).to eq(2)
end
end
end
activeadmin-arbre-35697e3/spec/arbre/unit/html/text_node_spec.rb 0000664 0000000 0000000 00000000705 15072460023 0024657 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
describe Arbre::HTML::TextNode do
let(:text_node){ described_class.new }
describe '#class_list' do
subject { text_node.class_list }
it { is_expected.to be_empty }
end
describe '#tag_name' do
subject { text_node.tag_name }
it { is_expected.to be_nil }
end
describe '#to_s' do
subject { text_node.build('Test').to_s }
it { is_expected.to eq 'Test' }
end
end
activeadmin-arbre-35697e3/spec/changelog_spec.rb 0000664 0000000 0000000 00000001247 15072460023 0021601 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe "Changelog" do
subject(:changelog) do
path = File.join(File.dirname(__dir__), "CHANGELOG.md")
File.read(path)
end
it 'has definitions for all implicit links' do
implicit_link_names = changelog.scan(/\[([^\]]+)\]\[\]/).flatten.uniq
implicit_link_names.each do |name|
expect(changelog).to include("[#{name}]: https")
end
end
describe 'entry' do
subject(:entries) { lines.grep(/^\*/) }
let(:lines) { changelog.each_line }
it 'does not end with a punctuation' do
entries.each do |entry|
expect(entry).not_to match(/\.$/)
end
end
end
end
activeadmin-arbre-35697e3/spec/gemspec_spec.rb 0000664 0000000 0000000 00000000543 15072460023 0021273 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "spec_helper"
require "open3"
require "arbre/version"
RSpec.describe "Gemspec" do
after do
File.delete("arbre-#{Arbre::VERSION}.gem")
end
let(:build) do
Bundler.with_original_env do
Open3.capture3("gem build arbre")
end
end
it "succeeds" do
expect(build[2]).to be_success
end
end
activeadmin-arbre-35697e3/spec/rails/ 0000775 0000000 0000000 00000000000 15072460023 0017421 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/spec/rails/integration/ 0000775 0000000 0000000 00000000000 15072460023 0021744 5 ustar 00root root 0000000 0000000 activeadmin-arbre-35697e3/spec/rails/integration/forms_spec.rb 0000664 0000000 0000000 00000004510 15072460023 0024431 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'rails/rails_spec_helper'
RSpec.describe "Forms" do
let(:assigns){ {} }
let(:helpers){ mock_action_view }
let(:html) { form.to_s }
describe "building a simple form for" do
let(:form) do
arbre do
form_for MockPerson.new, url: "/" do |f|
f.label :name
f.text_field :name
end
end
end
it "builds a form" do
expect(html).to have_css("form")
end
it "includes the hidden authenticity token" do
expect(html).to have_field("authenticity_token", type: :hidden, with: "AUTH_TOKEN")
end
it "creates a label" do
expect(html).to have_css("form label[for=mock_person_name]")
end
it "creates a text field" do
expect(html).to have_css("form input[type=text]")
end
end
describe "building a form with fields for" do
let(:form) do
arbre do
form_for MockPerson.new, url: "/" do |f|
f.label :name
f.text_field :name
f.fields_for :permission do |pf|
pf.label :admin
pf.check_box :admin
end
end
end
end
it "renders nested label" do
expect(html).to have_css("form label[for=mock_person_permission_admin]", text: "Admin")
end
it "renders nested input" do
expect(html).to have_css("form input[type=checkbox][name='mock_person[permission][admin]']")
end
it "does not render a div for the proxy" do
expect(html).to have_no_css("form div.fields_for_proxy")
end
end
describe "forms with other elements" do
let(:form) do
arbre do
form_for MockPerson.new, url: "/" do |f|
div do
f.label :name
f.text_field :name
end
para do
f.label :name
f.text_field :name
end
div class: "permissions" do
f.fields_for :permission do |pf|
div class: "permissions_label" do
pf.label :admin
end
pf.check_box :admin
end
end
end
end
end
it "nests elements" do
expect(html).to have_css("form > p > label")
end
it "nests elements within fields for" do
expect(html).to have_css("form > div.permissions > div.permissions_label label")
end
end
end
activeadmin-arbre-35697e3/spec/rails/integration/rendering_spec.rb 0000664 0000000 0000000 00000005712 15072460023 0025265 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'rails/rails_spec_helper'
ARBRE_VIEWS_PATH = File.expand_path("../../templates", __FILE__)
class TestController < ActionController::Base
append_view_path ARBRE_VIEWS_PATH
def render_empty
render "arbre/empty"
end
def render_simple_page
render "arbre/simple_page"
end
def render_partial
render "arbre/page_with_partial"
end
def render_erb_partial
render "arbre/page_with_erb_partial"
end
def render_with_instance_variable
@my_instance_var = "From Instance Var"
render "arbre/page_with_assignment"
end
def render_partial_with_instance_variable
@my_instance_var = "From Instance Var"
render "arbre/page_with_arb_partial_and_assignment"
end
def render_with_block
render "arbre/page_with_render_with_block"
end
end
RSpec.describe TestController, "Rendering with Arbre", type: :request do
let(:body){ response.body }
before do
Rails.application.routes.draw do
get 'test/render_empty', controller: "test"
get 'test/render_simple_page', controller: "test"
get 'test/render_partial', controller: "test"
get 'test/render_erb_partial', controller: "test"
get 'test/render_with_instance_variable', controller: "test"
get 'test/render_partial_with_instance_variable', controller: "test"
get 'test/render_page_with_helpers', controller: "test"
get 'test/render_with_block', controller: "test"
end
end
after do
Rails.application.reload_routes!
end
it "renders the empty template" do
get "/test/render_empty"
expect(response).to be_successful
end
it "renders a simple page" do
get "/test/render_simple_page"
expect(response).to be_successful
expect(body).to have_css("h1", text: "Hello World")
expect(body).to have_css("p", text: "Hello again!")
end
it "renders an arb partial" do
get "/test/render_partial"
expect(response).to be_successful
expect(body).to eq <<~HTML
Before Partial
Hello from a partial
After Partial
HTML
end
it "renders an erb (or other) partial" do
get "/test/render_erb_partial"
expect(response).to be_successful
expect(body).to eq <<~HTML
Before Partial
Hello from an erb partial
After Partial
HTML
end
it "renders with instance variables" do
get "/test/render_with_instance_variable"
expect(response).to be_successful
expect(body).to have_css("h1", text: "From Instance Var")
end
it "renders an arbre partial with assignments" do
get "/test/render_partial_with_instance_variable"
expect(response).to be_successful
expect(body).to have_css("p", text: "Partial: From Instance Var")
end
it "renders with a block" do
get "/test/render_with_block"
expect(response).to be_successful
expect(body).to eq <<~HTML