class FitnesseNode
@attr_reader [FitnesseRoot] root The root of the Fitnesse tree of which this node is a part. @attr_reader [FitnesseNode,FitnesseRoot] parent The parent of this node (which may be the root object) @attr_reader [Array<FitnesseNode>] children The child nodes of this node. @attr_reader [Pathname] path The path of this node’s folder. @attr_reader [Array<String>] path_as_array
The path relative to the root, as an array of strings. @attr_reader [String] name The name of this node. This is the “short” name of the node itself, not the fully qualified name. @attr_reader [Rexml::Document] properties The properties XML document of this node. @attr_reader [SortedSet<String>] explicit_tags
The set of tags that have been explicitly set on this node.
Attributes
Public Class Methods
# File lib/fitquery/fitnesse_node.rb, line 23 def initialize(root, parent, name) @root = root @parent = parent @children = {} @is_root = name == :root @name = name.to_s @path = name == :root ? parent.path : Pathname.new(parent.path.join(name)) @path_as_array = [] @path.relative_path_from(@root.path).descend{|partial| @path_as_array.push(partial.basename.to_s)} begin File.open(@path.join('properties.xml'), 'r') {|f| @properties = REXML::Document.new f } rescue @properties = nil end begin tags_element = @properties.get_elements('/properties/Suites') unless tags_element.nil? @explicit_tags = SortedSet.new(tags_element.first.text.split(',').map{|tag| tag.strip }) end rescue @explicit_tags = SortedSet.new([]) end @path.children.each do |sub| next unless sub.directory? rel_path = sub.relative_path_from(@root.path) next if @root.blacklist.any? {|blacklisted| rel_path.fnmatch?(blacklisted) } child_node = FitnesseNode.new(@root, self, sub.basename) @children[child_node.name] = child_node unless child_node.nil? end end
Public Instance Methods
# File lib/fitquery/fitnesse_node.rb, line 205 def <=>(other) if depth == other.depth name <=> other.name else depth <=> other.depth end end
Get the content of the node. Uses lazy loading to avoid slowing down the initial parsing of the tree.
# File lib/fitquery/fitnesse_node.rb, line 193 def content @content ||= IO::read(@path.join('content.txt')) end
Gets the depth of this node, i.e. the number of levels down the tree from the root node. @return [Integer] The depth of the node
# File lib/fitquery/fitnesse_node.rb, line 127 def depth @path_as_array.length end
# File lib/fitquery/fitnesse_node.rb, line 121 def dotted_name full_name('.') end
Yield this node and its children.
# File lib/fitquery/fitnesse_node.rb, line 68 def each(&block) traverse(:pre, &block) end
@return [Boolean] Does this node have the Prune property set on it or on any of its ancestors?
# File lib/fitquery/fitnesse_node.rb, line 105 def effectively_skipped? if @parent.respond_to?(:effectively_skipped?) @parent.effectively_skipped? || explicitly_skipped? else explicitly_skipped? end end
@return [Boolean] Does this node have the Prune property explicitly set on it?
# File lib/fitquery/fitnesse_node.rb, line 100 def explicitly_skipped? @properties.nil? ? false : (@properties.get_elements('/properties/Prune').count > 0) end
Yield this node and its children, but provides a way to stop further recursion down this node’s branch of the tree. @example Ignore all nodes that are the children of a node which is marked as skipped.
start_node.find {|node| Find.prune if node.explicitly_skipped? # only gets to here if none of the current node's ancestors have been skipped. }
# File lib/fitquery/fitnesse_node.rb, line 78 def find(&block) catch(:prune) do yield self unless @children.nil? @children.each_value do |child| child.find(&block) end end end end
Gets the fully qualified name of this node. @param sep [String] Sets the preferred separator string for the name. If nil, the name will use the system default file path separator. @return [String] The fully qualified name of the node, consisting of the names of each node in the tree leading to this one.
# File lib/fitquery/fitnesse_node.rb, line 116 def full_name(sep = nil) separator = sep.nil? ? File::SEPARATOR : sep @path_as_array.join(separator) end
Determine whether this node has a particular tag on it. @param tag [String,Regexp] The tag to find. If a string, the search will be case insensitive.
If a regular expression is used, the regex's case sensitivity flag will be respected.
@param explicit_only [Boolean] Specify whether to search within the explicit tags or the effective tags of this node.
# File lib/fitquery/fitnesse_node.rb, line 167 def has_tag?(tag, explicit_only = false) tag_set = explicit_only ? explicit_tags : effective_tags if tag.instance_of?(Regexp) pattern = tag elsif tag.instance_of?(String) pattern = /^#{tag}$/i end tag_set.any? {|t| t.match(pattern) } end
Gets the name of the node, prefixed with a number of characters determined by the node’s depth. Handy for displaying the node in a simple tree representation. @param indent_string [String] The string from which to construct the indentation. @return [String] The indented name. @example A node with a full name of ‘Root/Foo/Bar/Baz’
node.indented_name('-') => '---Baz'
# File lib/fitquery/fitnesse_node.rb, line 137 def indented_name(indent_string = ' ') indent = indent_string * depth indent + @name.to_s end
# File lib/fitquery/fitnesse_node.rb, line 197 def root? @is_root end
@return [Boolean] Is this node runnable? I.e. is it either a test or a suite which is not skipped?
# File lib/fitquery/fitnesse_node.rb, line 158 def runnable? !static? && !effectively_skipped? && (test? || suite?) end
Set a new explicit tag on the node and write it to the properties file immediately. @param tag [String] The tag to add.
# File lib/fitquery/fitnesse_node.rb, line 179 def set_tag(tag) File.open(@path.join('properties.xml'), 'w') do |f| @explicit_tags.add(tag) suites_elements = @properties.get_elements('/properties/Suites') tags_element = suites_elements.empty? ? @properties.root.add_element('Suites') : suites_elements.first tags_element.text = @explicit_tags.to_a.join(', ') formatter = REXML::Formatters::Default.new formatter.write(@properties, f) end rescue => ex STDERR.puts(ex.message) end
@return [Boolean] Is this node defined as a Static page?
# File lib/fitquery/fitnesse_node.rb, line 153 def static? @properties.nil? ? false : (@properties.get_elements('/properties/Static').count > 0) end
@return [Boolean] Is this node defined as a Suite?
# File lib/fitquery/fitnesse_node.rb, line 148 def suite? @properties.nil? ? false : (@properties.get_elements('/properties/Suite').count > 0) end
@return [Boolean] Is this node defined as a Test?
# File lib/fitquery/fitnesse_node.rb, line 143 def test? @properties.nil? ? false : (@properties.get_elements('/properties/Test').count > 0) end
# File lib/fitquery/fitnesse_node.rb, line 201 def to_s full_name end
Yield this node and its children. @param order [Symbol] Use :pre to yield this node before its children, or :post to yield the children first.
# File lib/fitquery/fitnesse_node.rb, line 57 def traverse(order = :pre, &block) yield self if order == :pre unless @children.nil? @children.each_value do |child| child.traverse(&block) end end yield self if order == :post end