(PDOC-206) support for Puppet Tasks

Currently, puppet-strings does not know how to generate documentation
for Puppet Tasks. This does all the work to add support for Tasks
including a new JSON parser, a task handler, task statement, and task code
object. Basically, Strings reads the JSON using the native ruby json
parser and sends values through in a way it understands. It is only
passing json key/value pairs through, nothing is happening with tags at
this time. You can now document Tasks and generate HTML, Markdown, or
JSON output.
This commit is contained in:
Eric Putnam 2018-02-16 09:27:26 -08:00
parent 7900b73a35
commit 738275b9e7
No known key found for this signature in database
GPG Key ID: 3FB595AA224A7751
35 changed files with 883 additions and 4 deletions

View File

@ -6,6 +6,7 @@ module PuppetStrings
functions/**/*.pp
types/**/*.pp
lib/**/*.rb
tasks/*.json
).freeze
# Generates documentation.

View File

@ -12,6 +12,7 @@ module PuppetStrings::Json
resource_types: YARD::Registry.all(:puppet_type).sort_by!(&:name).map!(&:to_hash),
providers: YARD::Registry.all(:puppet_provider).sort_by!(&:name).map!(&:to_hash),
puppet_functions: YARD::Registry.all(:puppet_function).sort_by!(&:name).map!(&:to_hash),
puppet_tasks: YARD::Registry.all(:puppet_task).sort_by!(&:name).map!(&:to_hash),
# TODO: Need Ruby documentation?
}

View File

@ -6,6 +6,7 @@ module PuppetStrings::Markdown
require_relative 'markdown/functions'
require_relative 'markdown/defined_types'
require_relative 'markdown/resource_types'
require_relative 'markdown/puppet_tasks'
require_relative 'markdown/table_of_contents'
# generates markdown documentation
@ -17,6 +18,7 @@ module PuppetStrings::Markdown
final << PuppetStrings::Markdown::DefinedTypes.render
final << PuppetStrings::Markdown::ResourceTypes.render
final << PuppetStrings::Markdown::Functions.render
final << PuppetStrings::Markdown::PuppetTasks.render
final
end

View File

@ -0,0 +1,24 @@
require 'puppet-strings/markdown/base'
module PuppetStrings::Markdown
class PuppetTask < Base
def initialize(registry)
@template = 'puppet_task.erb'
@registry = registry
super(registry, 'task')
end
def render
super(@template)
end
def supports_noop
@registry[:supports_noop]
end
def input_method
@registry[:input_method]
end
end
end

View File

@ -0,0 +1,34 @@
require_relative 'puppet_task'
module PuppetStrings::Markdown
module PuppetTasks
# @return [Array] list of classes
def self.in_tasks
arr = YARD::Registry.all(:puppet_task).sort_by!(&:name).map!(&:to_hash)
arr.map! { |a| PuppetStrings::Markdown::PuppetTask.new(a) }
end
def self.contains_private?
false
end
def self.render
final = in_tasks.length > 0 ? "## Tasks\n\n" : ""
in_tasks.each do |task|
final << task.render unless task.private?
end
final
end
def self.toc_info
final = ["Tasks"]
in_tasks.each do |task|
final.push(task.toc_info)
end
final
end
end
end

View File

@ -6,7 +6,8 @@ module PuppetStrings::Markdown
[PuppetStrings::Markdown::PuppetClasses,
PuppetStrings::Markdown::DefinedTypes,
PuppetStrings::Markdown::ResourceTypes,
PuppetStrings::Markdown::Functions].each do |r|
PuppetStrings::Markdown::Functions,
PuppetStrings::Markdown::PuppetTasks].each do |r|
toc = r.toc_info
group_name = toc.shift
group = toc

View File

@ -0,0 +1,28 @@
### <%= name %>
<% if text -%>
<%= text %>
<% elsif summary -%>
<%= summary %>
<% else -%>
<%= "The #{name} task." %>
<% end -%>
**Supports noop?** <%= supports_noop %>
<% if params -%>
#### Parameters
<% params.each do |param| -%>
##### `<%= param[:name] %>`
<% if param[:types] -%>
Data type: `<%= param[:types].join(', ') -%>`
<% end -%>
<%= param[:text] %>
<% end -%>
<% end -%>

View File

@ -15,10 +15,12 @@ module PuppetStrings::Yard
# Register the Puppet parser
YARD::Parser::SourceParser.register_parser_type(:puppet, PuppetStrings::Yard::Parsers::Puppet::Parser, ['pp'])
YARD::Parser::SourceParser.register_parser_type(:json, PuppetStrings::Yard::Parsers::JSON::Parser, ['json'])
# Register our handlers
YARD::Handlers::Processor.register_handler_namespace(:puppet, PuppetStrings::Yard::Handlers::Puppet)
YARD::Handlers::Processor.register_handler_namespace(:puppet_ruby, PuppetStrings::Yard::Handlers::Ruby)
YARD::Handlers::Processor.register_handler_namespace(:json, PuppetStrings::Yard::Handlers::JSON)
# Register the tag directives
PuppetStrings::Yard::Tags::ParameterDirective.register!
@ -46,7 +48,8 @@ class YARD::CLI::Yardoc
:puppet_defined_type,
:puppet_type,
:puppet_provider,
:puppet_function
:puppet_function,
:puppet_task
)
end
end
@ -75,6 +78,10 @@ class YARD::CLI::Stats
output 'Puppet Functions', *type_statistics_all(:puppet_function)
end
def stats_for_puppet_tasks
output 'Puppet Tasks', *type_statistics_all(:puppet_task)
end
def output(name, data, undoc = nil)
# Monkey patch output to accommodate our larger header widths
@total += data if data.is_a?(Integer) && undoc

View File

@ -5,4 +5,5 @@ module PuppetStrings::Yard::CodeObjects
require 'puppet-strings/yard/code_objects/type'
require 'puppet-strings/yard/code_objects/provider'
require 'puppet-strings/yard/code_objects/function'
require 'puppet-strings/yard/code_objects/task'
end

View File

@ -0,0 +1,70 @@
require 'puppet-strings/yard/code_objects/group'
# Implements the group for Puppet tasks.
class PuppetStrings::Yard::CodeObjects::Tasks < PuppetStrings::Yard::CodeObjects::Group
# Gets the singleton instance of the group.
# @return Returns the singleton instance of the group.
def self.instance
super(:puppet_tasks)
end
# Gets the display name of the group.
# @param [Boolean] prefix whether to show a prefix.
# @return [String] Returns the display name of the group.
def name(prefix = false)
'Puppet Tasks'
end
end
# Implements the Puppet task code object.
class PuppetStrings::Yard::CodeObjects::Task < PuppetStrings::Yard::CodeObjects::Base
attr_reader :statement
# Initializes a JSON task code object.
# @param statement TaskStatement object
# @return [void]
def initialize(statement)
@name = statement.name
@statement = statement
super(PuppetStrings::Yard::CodeObjects::Tasks.instance, name)
end
# Gets the type of the code object.
# @return Returns the type of the code object.
def type
:puppet_task
end
# Gets the source of the code object.
# @return Returns the source of the code object.
def source
@statement.source
end
def parameters
parameters = []
statement.json['parameters'].each do |name,props|
parameters.push({ name: name.to_s,
tag_name: 'param',
text: props['description'] || "",
types: [props['type']] || "" })
end
parameters
end
# Converts the code object to a hash representation.
# @return [Hash] Returns a hash representation of the code object.
def to_hash
{ name: name.to_s,
file: statement.file,
line: statement.line,
docstring: {
text: statement.docstring,
tags: parameters
},
source: statement.source,
supports_noop: statement.json['supports_noop'] || false,
input_method: statement.json['input_method']
}
end
end

View File

@ -8,6 +8,11 @@ module PuppetStrings::Yard::Handlers
require 'puppet-strings/yard/handlers/ruby/function_handler'
end
# The module for custom JSON YARD handlers.
module JSON
require 'puppet-strings/yard/handlers/json/task_handler'
end
# The module for custom Puppet YARD handlers.
module Puppet
require 'puppet-strings/yard/handlers/puppet/class_handler'

View File

@ -0,0 +1,5 @@
class PuppetStrings::Yard::Handlers::JSON::Base < YARD::Handlers::Base
def self.handles?(statement)
handlers.any? {|handler| statement.is_a?(handler)}
end
end

View File

@ -0,0 +1,31 @@
require 'puppet-strings/yard/handlers/json/base'
require 'puppet-strings/yard/parsers'
require 'puppet-strings/yard/parsers/json/parser'
class PuppetStrings::Yard::Handlers::JSON::TaskHandler < PuppetStrings::Yard::Handlers::JSON::Base
handles PuppetStrings::Yard::Parsers::JSON::TaskStatement
namespace_only
process do
object = PuppetStrings::Yard::CodeObjects::Task.new(statement)
register object
@kind = "Puppet Task #{object.name}."
@statement = statement
validate_description
validate_params
end
def validate_description
log.warn "Missing a description for #{@kind}." if @statement.docstring.empty?
end
def validate_params
unless @statement.parameters.empty?
@statement.parameters.each do |param, val|
log.warn "Missing description for param '#{param}' in #{@kind}" if val['description'].nil?
end
end
end
end

View File

@ -1,5 +1,9 @@
# The module for custom YARD parsers.
module PuppetStrings::Yard::Parsers
# The module for custom YARD parsers for JSON.
module JSON
require 'puppet-strings/yard/parsers/json/parser'
end
# The module for custom YARD parsers for the Puppet language.
module Puppet
require 'puppet-strings/yard/parsers/puppet/parser'

View File

@ -0,0 +1,33 @@
require 'puppet-strings/yard/parsers/json/task_statement'
class PuppetStrings::Yard::Parsers::JSON::Parser < YARD::Parser::Base
attr_reader :file, :source
# Initializes the parser.
# @param [String] source The source being parsed.
# @param [String] filename The file name of the file being parsed.
# @return [void]
def initialize(source, filename)
@file = filename
@source = source
@statements = []
end
def enumerator
@statements
end
# Parses the source
# @return [void]
def parse
begin
json = JSON.parse(source)
@statements.push(PuppetStrings::Yard::Parsers::JSON::TaskStatement.new(json, @source, @file))
rescue
log.error "Failed to parse #{@file}: "
@statements = []
end
@statements.freeze
self
end
end

View File

@ -0,0 +1,35 @@
module PuppetStrings::Yard::Parsers::JSON
# Represents the Puppet Task statement.
class TaskStatement
attr_reader :line, :comments, :comments_range, :json, :file, :source, :docstring
def initialize(json, source, file)
@file = file
@source = source
@json = json
@line = 0
@comments_range = nil
@docstring = YARD::Docstring.new(@json['description'])
end
def parameters
json['parameters'] || {}
end
def comments_hash_flag
false
end
def show
""
end
def comments
docstring.all
end
def name
File.basename(@file).gsub('.json','') || ""
end
end
end

View File

@ -0,0 +1,9 @@
<% even = false %>
<% @items.each do |item| %>
<li id="object_<%=item.path%>" class="<%= even ? 'even' : 'odd' %>">
<div class="item">
<%= linkify item, h(item.name(true)) %>
</div>
</li>
<% even = !even %>
<% end %>

View File

@ -62,3 +62,12 @@ def generate_class_list
@list_type = 'class'
generate_list_contents
end
# Generates the searchable Puppet Task list.
# @return [void]
def generate_puppet_task_list
@items = Registry.all(:puppet_task).sort_by {|t| t.name.to_s }
@list_title = 'Puppet Task List'
@list_type = 'puppet_task'
generate_list_contents
end

View File

@ -4,7 +4,7 @@ def init
case object
when '_index.html'
@page_title = options.title
sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :functions, :files, :objects]]]
sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :functions, :tasks, :files, :objects]]]
else
super
end
@ -46,6 +46,10 @@ def layout
@nav_url = url_for_list('puppet_function')
@page_title = "Puppet Function: #{object.name} (#{object.function_type})"
@path = object.path
when PuppetStrings::Yard::CodeObjects::Task
@nav_url = url_for_list('puppet_task')
@page_title = "Puppet Task: #{object.name}"
@path = object.path
else
@path = object.path
end
@ -82,6 +86,11 @@ def create_menu_lists
title: 'Puppet Functions',
search_title: 'Puppet Functions'
},
{
type: 'puppet_task',
title: 'Puppet Tasks',
search_totle: 'Puppet Tasks'
},
{
type: 'class',
title: 'Ruby Classes',
@ -163,6 +172,14 @@ def functions
erb(:objects)
end
# Renders the tasks section.
# @return [String] Returns the rendered section.
def tasks
@title = 'Puppet Task Listing A-Z'
@objects_by_letter = objects_by_letter(:puppet_task)
erb(:objects)
end
# Renders the objects section.
# @return [String] Returns the rendered section.
def objects

View File

@ -0,0 +1,9 @@
<div class="box_info">
<dl>
<dt>Defined in:</dt>
<dd>
<%= object.file %>,<br />
<%= object.file.gsub('json','rb') %><br/></div>
</dd>
</dl>
</div>

View File

@ -0,0 +1 @@
<h1>Puppet Task: <%= object.name %></h1>

View File

@ -0,0 +1,5 @@
<% if json['input_method'] || json['supports_noop'] %>
<div class="tags">
<p><strong>Supports noop?</strong> <%= json['supports_noop'] ? "true" : "false" %></p>
</div>
<% end %>

View File

@ -0,0 +1,6 @@
<h2>Overview</h2>
<div class="docstring">
<div class="discussion">
<%= description %>
</div>
</div>

View File

@ -0,0 +1,16 @@
<% if @parameters && !@parameters.empty? %>
<div class="tags">
<p class="tag_title"><%= @tag_title %></p>
<ul>
<% @parameters.each do |parameter, values| %>
<li>
<span class="name"><%= parameter %></span>
<span class="type">
<tt>(<%= values['type'] %>)</tt>
</span>
<% if values['description'] %> &mdash; <%= values['description'] %><% end %>
</li>
<% end %>
</ul>
</div>
<% end %>

View File

@ -0,0 +1,22 @@
# Initializes the template.
# @return [void]
def init
sections :header, :box_info, T('tags'), :overview, :input, :parameters
end
def json
object.statement.json
end
def description
json['description']
end
# Renders the parameters section.
# @return [String] Returns the rendered section.
def parameters
@parameters = json['parameters'] || []
@parameters.to_a.sort!
@tag_title = 'Parameters'
erb(:parameters)
end

View File

@ -0,0 +1,3 @@
<% if json['supports_noop'] %>
<strong>Supports noop?</strong> <%= json['supports_noop'] %>
<% end %>

View File

@ -5,7 +5,8 @@ def param
object.type == :method ||
object.type == :puppet_class ||
object.type == :puppet_defined_type ||
object.type == :puppet_function
object.type == :puppet_function ||
object.type == :puppet_task
end
# Renders the overload section.

View File

@ -598,5 +598,52 @@
},
"source": "Puppet::Functions.create_function(:func4x_1) do\n # @param param1 The first parameter.\n # @return [Undef] Returns nothing.\n dispatch :foobarbaz do\n param 'Integer', :param1\n end\nend"
}
],
"puppet_tasks": [
{
"name": "(stdin)",
"file": "(stdin)",
"line": 0,
"docstring": {
"text": "Allows you to backup your database to local file.",
"tags": [
{
"name": "database",
"tag_name": "param",
"text": "Database to connect to",
"types": [
"Optional[String[1]]"
]
},
{
"name": "user",
"tag_name": "param",
"text": "The user",
"types": [
"Optional[String[1]]"
]
},
{
"name": "password",
"tag_name": "param",
"text": "The password",
"types": [
"Optional[String[1]]"
]
},
{
"name": "sql",
"tag_name": "param",
"text": "Path to file you want backup to",
"types": [
"String[1]"
]
}
]
},
"source": "{\n \"description\": \"Allows you to backup your database to local file.\",\n \"input_method\": \"stdin\",\n \"parameters\": {\n \"database\": {\n \"description\": \"Database to connect to\",\n \"type\": \"Optional[String[1]]\"\n },\n \"user\": {\n \"description\": \"The user\",\n \"type\": \"Optional[String[1]]\"\n },\n \"password\": {\n \"description\": \"The password\",\n \"type\": \"Optional[String[1]]\"\n },\n \"sql\": {\n \"description\": \"Path to file you want backup to\",\n \"type\": \"String[1]\"\n }\n }\n}\n",
"supports_noop": false,
"input_method": "stdin"
}
]
}

View File

@ -15,6 +15,8 @@
* [`func3x`](#func3x): Documentation for an example 3.x function.
* [`func4x`](#func4x): An example 4.x function.
* [`func4x_1`](#func4x_1): An example 4.x function with only one signature.
## Tasks
* [`(stdin)`](#(stdin)): Allows you to backup your database to local file.
## Classes
### klass
@ -381,3 +383,37 @@ Data type: `Integer`
The first parameter.
## Tasks
### (stdin)
Allows you to backup your database to local file.
**Supports noop?** false
#### Parameters
##### `database`
Data type: `Optional[String[1]]`
Database to connect to
##### `user`
Data type: `Optional[String[1]]`
The user
##### `password`
Data type: `Optional[String[1]]`
The password
##### `sql`
Data type: `String[1]`
Path to file you want backup to

View File

@ -30,6 +30,31 @@ SOURCE
# @return [Undef] Returns nothing.
function func(Integer $param1, $param2, String $param3 = hi) {
}
SOURCE
YARD::Parser::SourceParser.parse_string(<<-SOURCE, :json)
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby)

View File

@ -63,6 +63,55 @@ define klass::dt (
Boolean $param4 = true
) {
}
SOURCE
YARD::Parser::SourceParser.parse_string(<<-SOURCE, :json)
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
YARD::Parser::SourceParser.parse_string(<<-SOURCE, :json)
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet)

View File

@ -0,0 +1,92 @@
require 'spec_helper'
require 'puppet-strings/yard/code_objects/task'
require 'puppet-strings/yard/parsers/json/task_statement'
describe PuppetStrings::Yard::CodeObjects::Task do
let(:source) { <<-SOURCE
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
}
let(:json) { JSON.parse(source) }
let(:statement) { PuppetStrings::Yard::Parsers::JSON::TaskStatement.new(json, source, "test.json") }
subject { PuppetStrings::Yard::CodeObjects::Task.new(statement) }
describe '#type' do
it 'returns the correct type' do
expect(subject.type).to eq(:puppet_task)
end
end
describe '#source' do
it 'returns the source' do
expect(subject.source).to eq(source)
end
end
describe '#to_hash' do
let(:expected) do
{
:name => "test",
:supports_noop => false,
:docstring => {
:text=>"Allows you to backup your database to local file.",
:tags=> [
{
:name=>"database",
:tag_name=>"param",
:text=>"Database to connect to",
:types=> ["Optional[String[1]]"]
},
{
:name=>"user",
:tag_name=>"param",
:text=>"The user",
:types=> ["Optional[String[1]]"]
},
{
:name=>"password",
:tag_name=>"param",
:text=>"The password",
:types=> ["Optional[String[1]]"]
},
{
:name=>"sql",
:tag_name=>"param",
:text=>"Path to file you want backup to",
:types=>["String[1]"]
}
]
},
:file => "test.json",
:input_method => "stdin",
:line => 0,
:source => "{\n \"description\": \"Allows you to backup your database to local file.\",\n \"input_method\": \"stdin\",\n \"parameters\": {\n \"database\": {\n \"description\": \"Database to connect to\",\n \"type\": \"Optional[String[1]]\"\n },\n \"user\": {\n \"description\": \"The user\",\n \"type\": \"Optional[String[1]]\"\n },\n \"password\": {\n \"description\": \"The password\",\n \"type\": \"Optional[String[1]]\"\n },\n \"sql\": {\n \"description\": \"Path to file you want backup to\",\n \"type\": \"String[1]\"\n }\n }\n}\n"
}
end
it 'returns the correct hash' do
expect(subject.to_hash).to eq(expected)
end
end
end

View File

@ -0,0 +1,124 @@
require 'spec_helper'
require 'puppet-strings/yard'
describe PuppetStrings::Yard::Handlers::JSON::TaskHandler do
subject {
YARD::Parser::SourceParser.parse_string(source, :json)
YARD::Registry.all(:puppet_task)
}
describe 'parsing source without a task definition' do
let(:source) { 'notice hi' }
it 'no defined types should be in the registry' do
expect(subject.empty?).to eq(true)
end
end
describe 'parsing source with a syntax error' do
let(:source) { <<-SOURCE
{
"input_method": "stdin",
"parameters":
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
}
}
}
SOURCE
}
it 'should log an error' do
expect{ subject }.to output(/\[error\]: Failed to parse \(stdin\):/).to_stdout_from_any_process
expect(subject.empty?).to eq(true)
end
end
describe 'parsing a defined type with a missing docstring' do
let(:source) { <<-SOURCE
{
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
}
it 'should log a warning' do
expect{ subject }.to output(/\[warn\]: Missing a description for Puppet Task \(stdin\)/).to_stdout_from_any_process
end
end
describe 'parsing a defined type with a docstring' do
let(:source) { <<-SOURCE
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
}
it 'should register a task object' do
expect(subject.size).to eq(1)
object = subject.first
expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Task)
expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Tasks.instance)
end
end
describe 'parsing a Task with a missing parameter description' do
let(:source) { <<-SOURCE
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"type": "Optional[String[1]]"
}
}
}
SOURCE
}
it 'should output a warning' do
expect{ subject }.to output(/\[warn\]: Missing description for param 'database' in Puppet Task \(stdin\)/).to_stdout_from_any_process
end
end
end

View File

@ -0,0 +1,70 @@
require 'spec_helper'
require 'puppet-strings/yard'
describe PuppetStrings::Yard::Parsers::JSON::Parser do
subject { PuppetStrings::Yard::Parsers::JSON::Parser.new(source, file) }
let(:file) { 'test.json' }
describe 'initialization of the parser' do
let(:source) { 'notice hi' }
it 'should store the original source' do
expect(subject.source).to eq(source)
end
it 'should store the original file name' do
expect(subject.file).to eq(file)
end
it 'should have no relevant statements' do
subject.parse
expect(subject.enumerator.empty?).to be_truthy
end
end
describe 'parsing invalid JSON' do
let(:source) { <<SOURCE
class foo {
SOURCE
}
it 'should raise an exception' do
expect{ subject.parse }.to output(/\[error\]: Failed to parse test.json/).to_stdout_from_any_process
end
end
describe 'parsing puppet functions with return type in defintion', if: TEST_FUNCTION_RETURN_TYPE do
let(:source) { <<SOURCE
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
}
it 'should parse the puppet function statement' do
subject.parse
expect(subject.enumerator.size).to eq(1)
statement = subject.enumerator.first
expect(statement).to be_instance_of(PuppetStrings::Yard::Parsers::JSON::TaskStatement)
end
end
end

View File

@ -0,0 +1,56 @@
require 'spec_helper'
describe PuppetStrings::Yard::Parsers::JSON::TaskStatement do
let(:source) { <<-SOURCE
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin",
"parameters": {
"database": {
"description": "Database to connect to",
"type": "Optional[String[1]]"
},
"user": {
"description": "The user",
"type": "Optional[String[1]]"
},
"password": {
"description": "The password",
"type": "Optional[String[1]]"
},
"sql": {
"description": "Path to file you want backup to",
"type": "String[1]"
}
}
}
SOURCE
}
let(:json) { JSON.parse(source) }
subject { PuppetStrings::Yard::Parsers::JSON::TaskStatement.new(json, source, "test.json") }
describe '#comments' do
it 'returns docstring' do
expect(subject.comments).to eq "Allows you to backup your database to local file."
end
end
describe '#parameters' do
context 'with params' do
it 'returns params' do
expect(subject.parameters.size > 0).to be true
end
end
context 'no params' do
let(:source) { <<-SOURCE
{
"description": "Allows you to backup your database to local file.",
"input_method": "stdin"
}
SOURCE
}
it 'returns an empty hash' do
expect(subject.parameters).to eq({})
end
end
end
end