specific 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 01415a05773b182540b3d27c5f3655e2ef9a7550
4
+ data.tar.gz: 911c22b3cbbd382b056e8379fd7a1f42776a35dd
5
+ SHA512:
6
+ metadata.gz: 97b7e728ab47263d1fa718390efc01c4649fee06d182ad389b46baa7326ef551989d4aea00dc960bd193cca05083c5d03acc51fdce4c78aac5211b6df32b63a4
7
+ data.tar.gz: 4cd47a300b96251f8ed190164563db3dd103b27b1e0bc420ac679deff85898e4701188480920bdaadb54767c3be9057b4a5f115b8b3978528c9830272e5a2707
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ features/*
19
+ templates/*
20
+
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ gherkin-test
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Specific
2
+
3
+ Managing your project-specification programmatically with Gherkin
4
+
5
+ ## Some Words about all of this
6
+
7
+ TODO: spit it out!
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'specific'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install specific
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/specific ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'thor'
5
+
6
+ require 'specific'
7
+
8
+
9
+ class CLI < Thor
10
+ desc "build TYPE",
11
+ "builds your specification into the given type"
12
+ def build(type)
13
+ run :Build, type.to_sym
14
+ end
15
+
16
+ desc 'feature GROUP_NAME FILE_NAME FEATURE_TITLE',
17
+ "adds an empty feature template into the group"
18
+ def feature(group_name, file_name, feature_title)
19
+ run :Feature, group_name, file_name, feature_title
20
+ end
21
+
22
+ private
23
+ def spec
24
+ unless @loader
25
+ @loader = Specific::Loader.new
26
+ @loader.run
27
+ end
28
+ @loader.spec
29
+ end
30
+
31
+ def run(name, *args)
32
+ Specific::Command.const_get(name).new(spec, *args).run
33
+ end
34
+ end
35
+
36
+ CLI.start
37
+
38
+ exit 0
39
+
40
+ cli = Specific::CLI.new(options)
41
+ cli.run
data/lib/specific.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'specific/feature'
2
+ require 'specific/tag'
3
+ require 'specific/group'
4
+ require 'specific/scenario'
5
+ require 'specific/step'
6
+
7
+ require 'specific/processor'
8
+
9
+ require 'specific/renderer'
10
+
11
+ require 'specific/loader'
12
+ require 'specific/command'
13
+
14
+ module Specific
15
+ class Base
16
+ attr_reader :base_path
17
+
18
+ def initialize(base_path)
19
+ @base_path = base_path
20
+ end
21
+
22
+ def add_feature(feature)
23
+ features << feature
24
+ end
25
+
26
+ def features
27
+ @features ||= []
28
+ end
29
+
30
+ def next_id
31
+ highest_id + 1
32
+ end
33
+
34
+ private
35
+ def highest_id
36
+ features.map(&:id).max
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ require 'specific/command/build'
2
+ require 'specific/command/feature'
3
+
4
+ module Specific
5
+ module Command
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module Specific
2
+ module Command
3
+ class Build
4
+ attr_reader :spec, :renderer
5
+
6
+ def initialize(spec, type)
7
+ @spec = spec
8
+ @type = type
9
+ @renderer = Renderer.for(@type)
10
+ end
11
+
12
+ def run
13
+ puts renderer.new(spec).render
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,82 @@
1
+ module Specific
2
+ module Command
3
+ class Feature
4
+ attr_reader :spec, :group_name, :file_name, :title
5
+
6
+ def initialize(spec, group_name, file_name, title)
7
+ @spec = spec
8
+ @group_name = group_name
9
+ @file_name = file_name
10
+ @title = title
11
+ end
12
+
13
+ def run
14
+ mk_group_dir
15
+ write_feature_template
16
+ end
17
+
18
+ private
19
+
20
+ def mk_group_dir
21
+ FileUtils.mkdir_p group_dir_path
22
+ end
23
+
24
+ def sanitized_group_name
25
+ group_name.gsub(' ', '-').downcase
26
+ end
27
+
28
+ def group_dir_path
29
+ dir_name = sanitized_group_name
30
+ File.join spec.base_path, dir_name
31
+ end
32
+
33
+ def feature_file_path
34
+ File.join(group_dir_path, file_name + ".feature")
35
+ end
36
+
37
+ def write_feature_template
38
+ template = <<-EOT
39
+ @id_[ID] @group_[GROUP]
40
+ Feature: [NAME]
41
+ In Order
42
+ As
43
+ I
44
+
45
+ Scenario:
46
+ Given
47
+ When
48
+ Then
49
+ EOT
50
+ template_intendation = template.match(/^(\s*)/)[1]
51
+ template.gsub!(/^#{template_intendation}/, '')
52
+
53
+ subs = {
54
+ 'ID' => next_id,
55
+ 'GROUP' => sanitized_group_name,
56
+ 'NAME' => title,
57
+ }
58
+
59
+ subs.each do |key, value|
60
+ template.gsub!(/\[#{key}\]/, value.to_s)
61
+ end
62
+
63
+ if File.exist?(feature_file_path)
64
+ raise "File #{printable_feature_file_path} already exists"
65
+ end
66
+
67
+ File.open(feature_file_path, 'w')do |f|
68
+ f << template
69
+ end
70
+ puts "File #{printable_feature_file_path} created"
71
+ end
72
+
73
+ def next_id
74
+ spec.next_id
75
+ end
76
+
77
+ def printable_feature_file_path
78
+ feature_file_path.gsub(/^#{Dir.pwd}\//, '')
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,24 @@
1
+ module Specific
2
+ class Feature < Struct.new(:name, :tags, :description, :scenarios)
3
+ attr_reader :id, :group
4
+
5
+ def initialize(*)
6
+ super
7
+ process!
8
+ end
9
+ private
10
+ def process!
11
+ process_tags!
12
+ end
13
+
14
+ def process_tags!
15
+ tags.each do |tag|
16
+ if tag.id?
17
+ @id = tag.id.to_i
18
+ elsif tag.group?
19
+ @group = Group.new(tag.group_name)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,4 @@
1
+ module Specific
2
+ class Group < Struct.new(:name)
3
+ end
4
+ end
@@ -0,0 +1,22 @@
1
+ module Specific
2
+ class Loader
3
+ attr_reader :spec
4
+
5
+ def initialize(path = 'specification')
6
+ base_path = File.join(Dir.pwd, path)
7
+
8
+ @path = File.join(base_path, '**', '*.feature')
9
+ @spec = Specific::Base.new(base_path)
10
+ end
11
+
12
+ def run
13
+ Dir[@path].each do |feature_file|
14
+ feature_definition = File.read(feature_file)
15
+ ast = GherkinRuby.parse(feature_definition)
16
+
17
+ processor = Specific::Processor::Gherkin.new(@spec)
18
+ processor.execute(ast)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ require 'specific/processor/gherkin'
2
+
3
+ module Specific
4
+ module Processor
5
+ end
6
+ end
@@ -0,0 +1,36 @@
1
+ require 'gherkin_ruby'
2
+
3
+ module Specific
4
+ module Processor
5
+ class Gherkin
6
+ def initialize(spec)
7
+ @spec = spec
8
+ end
9
+
10
+ def execute(ast)
11
+ ast.accept(self)
12
+ end
13
+
14
+ def visit_Feature(ast_feature)
15
+ tags = ast_feature.tags.map do |ast_tag|
16
+ Specific::Tag.new(ast_tag.name)
17
+ end
18
+
19
+ scenarios = ast_feature.scenarios.map do |ast_scenario|
20
+ steps = ast_scenario.steps.map do |ast_step|
21
+ Specific::Step.new(ast_step.keyword, ast_step.name)
22
+ end
23
+ Specific::Scenario.new(ast_scenario.name, steps)
24
+ end
25
+
26
+ feature = Specific::Feature.new(
27
+ ast_feature.name,
28
+ tags,
29
+ ast_feature.description,
30
+ scenarios
31
+ )
32
+ @spec.add_feature feature
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ require 'set'
2
+
3
+ module Specific
4
+ module Renderer
5
+
6
+ def self.for(type)
7
+ renderer = Base.registered.detect do |renderer_class|
8
+ renderer_class.types.include? type
9
+ end
10
+
11
+ renderer || raise("No Renderer for #{type.inspect} found")
12
+ end
13
+
14
+ module Base
15
+ def self.registered
16
+ @registered ||= Set.new
17
+ end
18
+ def self.included(cls)
19
+ Base.registered << cls
20
+ cls.send :extend, ClassMethods
21
+ end
22
+
23
+ module ClassMethods
24
+ def types(*types)
25
+ @types = types unless types.empty?
26
+ @types || []
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ require 'specific/renderer/text'
34
+ require 'specific/renderer/markdown'
@@ -0,0 +1,58 @@
1
+ module Specific
2
+ module Renderer
3
+ class Markdown
4
+ include Renderer::Base
5
+
6
+ types :md, :markdown
7
+
8
+ def initialize(spec)
9
+ @spec = spec
10
+ end
11
+
12
+ def render
13
+ out = "# Project Specific\n\n"
14
+
15
+ grouped_features = @spec.features.group_by(&:group)
16
+
17
+ grouped_features.each do |group, features|
18
+ group_title = "## Features '#{group.name}'"
19
+
20
+ out << group_title + "\n\n"
21
+
22
+ features.each do |feature|
23
+ out << "* [#{feature_to_s feature}](#feature-#{feature.id})\n"
24
+ end
25
+
26
+ out << "\n"
27
+
28
+ features.sort_by(&:id).each do |feature|
29
+ out << [
30
+ "### #{feature_to_s feature}",
31
+ "<a href=\"feature-#{feature.id}\"></a>",
32
+ "\n"
33
+ ].join("\n")
34
+ out << feature.description.join(" \n") + "\n\n"
35
+
36
+ feature.scenarios.each do |scenario|
37
+ out << "#### Scenario: #{scenario.name}\n"
38
+ scenario.steps.each do |step|
39
+ out << "* #{step.keyword} #{step.text}\n"
40
+ end
41
+ out << "\n"
42
+ end
43
+
44
+ out << "\n"
45
+ end
46
+ end
47
+
48
+ out
49
+ end
50
+
51
+ private
52
+
53
+ def feature_to_s(feature)
54
+ ("[F%0.4d] - %s" % [feature.id, feature.name])
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,32 @@
1
+ module Specific
2
+ module Renderer
3
+ class Text
4
+ include Renderer::Base
5
+
6
+ types :text
7
+
8
+ def initialize(spec)
9
+ @spec = spec
10
+ end
11
+
12
+ def render
13
+ out = ""
14
+
15
+ grouped_features = @spec.features.group_by(&:group)
16
+
17
+ grouped_features.each do |group, features|
18
+ group_title = "Group '#{group.name}'"
19
+
20
+ out << group_title + "\n"
21
+ out << "="*group_title.size + "\n"
22
+
23
+ features.sort_by(&:id).each do |feature|
24
+ out << (" [F%0.4d] - %s" % [feature.id, feature.name]) + "\n"
25
+ end
26
+ end
27
+
28
+ out
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,4 @@
1
+ module Specific
2
+ class Scenario < Struct.new(:name, :steps)
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Specific
2
+ class Step < Struct.new(:keyword, :text)
3
+ end
4
+ end
@@ -0,0 +1,19 @@
1
+ module Specific
2
+ class Tag < Struct.new(:name)
3
+ def id?
4
+ !!id
5
+ end
6
+
7
+ def group?
8
+ !!group_name
9
+ end
10
+
11
+ def id
12
+ @id ||= (name.match(/^id_(.+)$/) || [])[1]
13
+ end
14
+
15
+ def group_name
16
+ @group_name ||= (name.match(/^group_(.+)$/) || [])[1]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module Specific
2
+ VERSION = '0.0.1'
3
+ end
data/specific.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'specific/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "specific"
8
+ spec.version = Specific::VERSION
9
+ spec.authors = ["Jakob Holderbaum"]
10
+ spec.email = ["jakob@featurefabrik.de"]
11
+ spec.summary = %q{Write your usecases with gherkin.}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "rake"
22
+
23
+ spec.add_dependency "gherkin-ruby"
24
+ spec.add_dependency "thor"
25
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: specific
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jakob Holderbaum
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: gherkin-ruby
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - jakob@featurefabrik.de
72
+ executables:
73
+ - specific
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - .ruby-gemset
79
+ - .ruby-version
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - README.md
83
+ - Rakefile
84
+ - bin/specific
85
+ - lib/specific.rb
86
+ - lib/specific/command.rb
87
+ - lib/specific/command/build.rb
88
+ - lib/specific/command/feature.rb
89
+ - lib/specific/feature.rb
90
+ - lib/specific/group.rb
91
+ - lib/specific/loader.rb
92
+ - lib/specific/processor.rb
93
+ - lib/specific/processor/gherkin.rb
94
+ - lib/specific/renderer.rb
95
+ - lib/specific/renderer/markdown.rb
96
+ - lib/specific/renderer/text.rb
97
+ - lib/specific/scenario.rb
98
+ - lib/specific/step.rb
99
+ - lib/specific/tag.rb
100
+ - lib/specific/version.rb
101
+ - specific.gemspec
102
+ homepage: ''
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.0.3
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Write your usecases with gherkin.
126
+ test_files: []