gurk 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.
data/.gitignore ADDED
@@ -0,0 +1,21 @@
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
+ .rvmrc
19
+ .ruby-version
20
+ spec/support/testapp
21
+ **.DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=doc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gurk.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jason Torres
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # Gurk
2
+
3
+ A ruby microframework for the masses. You don't need a programming background all you need is the english language.
4
+
5
+ Perfect for designers or any developers that don't want to write code at all.
6
+
7
+ ## Installation
8
+
9
+ gem install gurk
10
+
11
+ Create a new gurk project by running
12
+
13
+ gurk new <appname>
14
+ cd <appname>
15
+
16
+ You should see a directory with the following structure
17
+
18
+ app/
19
+ assets/
20
+ views/
21
+ views/layouts/application.html.erb
22
+ features/
23
+ public/
24
+ vendor/
25
+ Gemfile
26
+
27
+ ## Features
28
+
29
+ Create a basic feature file with the following
30
+
31
+ Given I have a home page
32
+ And with the path "/"
33
+ And with the title "Home Page"
34
+ And with the layout "
35
+
36
+ More information and examples can be found at the Wiki.
37
+
38
+ ## Template Support
39
+
40
+ Gurk supports Tilt. A template wrapper that gives you the flexibility to choose which
41
+
42
+ If you're using haml, just add the following in your Gemfile
43
+
44
+ gem 'haml'
45
+
46
+ Don't forget to run bundle install
47
+
48
+ ## Overiding generated pages
49
+
50
+ For each page generated from the feature scenarios. We create an object that you can easily override. For this feature.
51
+
52
+
53
+ Given I have a home page
54
+ And with the path "/"
55
+ And with the title "Home Page"
56
+ And with the layout "
57
+
58
+ Add a file called app/home.rb
59
+
60
+ class HomePage
61
+ include Gurk::Methods
62
+
63
+ local :page_title, 'This is the new title'
64
+ local :header, 'The most awesome site ever'
65
+
66
+ path '/homepage'
67
+
68
+ end
69
+
70
+ ## Creating your own pages
71
+
72
+ Ok fine, you don't want to use the features feature. You are free to do so by doing the following
73
+
74
+ Create a file called app/contact.rb
75
+
76
+ class ContactPage
77
+ include Gurk::Methods
78
+
79
+ name 'contact'
80
+ local :title, "Contact Page"
81
+ path '/contact'
82
+
83
+ end
84
+
85
+ Don't forget to create your view. For example: app/views/contact.html.erb
86
+
87
+ Then register it to Gurk in your app.rb file.
88
+
89
+ Gurk::Router.register ContactPage
90
+
91
+ ## Tests
92
+
93
+ Gurk supports tests! In fact we do sanity check per each request during development.
94
+
95
+ ## Contributing
96
+
97
+ 1. Fork it
98
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
99
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
100
+ 4. Push to the branch (`git push origin my-new-feature`)
101
+ 5. Create new Pull Request
102
+
103
+
104
+ ## Contributors
105
+
106
+ Vixon
107
+
108
+ ## License
109
+
110
+ MIT License
111
+
112
+
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
data/bin/gurk ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ # $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
5
+
6
+ require 'gurk/runner'
7
+ Gurk::Runner.start
data/gurk.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gurk/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gurk"
8
+ spec.version = Gurk::VERSION
9
+ spec.authors = ["Vixon"]
10
+ spec.email = ["vixonshow@gmail.com"]
11
+ spec.description = %q{Gurk}
12
+ spec.summary = %q{A plain english ruby microframework that makes sense}
13
+ spec.homepage = "http://github.com/vixon/gurk"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rack-test"
25
+
26
+ spec.add_dependency "gherkin"
27
+ spec.add_dependency 'http_router', '~> 0.11.0'
28
+ spec.add_dependency 'tilt'
29
+ spec.add_dependency 'thor'
30
+ end
data/lib/gurk.rb ADDED
@@ -0,0 +1,65 @@
1
+ require "gurk/version"
2
+ require "gurk/router"
3
+ require "gurk/parser"
4
+ require "gurk/page"
5
+ require "tilt"
6
+ require "tilt/erb"
7
+
8
+ module Gurk
9
+
10
+ Tilt.register Tilt::ERBTemplate, '.html.erb'
11
+
12
+ def self.root
13
+ Dir.pwd
14
+ end
15
+
16
+ # The default template
17
+ @@default_view_engine = :erb
18
+
19
+ def self.default_view_engine
20
+ @@default_view_engine
21
+ end
22
+
23
+ def self.default_view_engine=(new_default_view_engine)
24
+ @@default_view_engine = new_default_view_engine
25
+ end
26
+
27
+ # The default view path
28
+ @@view_path = self.root + "/app/views"
29
+
30
+ def self.view_path
31
+ @@view_path
32
+ end
33
+
34
+ def self.view_path=(new_view_path)
35
+ @@view_path = new_view_path
36
+ end
37
+
38
+ @@feature_paths = Dir.glob("#{Dir.pwd}/features/*.feature")
39
+
40
+ def self.feature_paths
41
+ @@feature_paths
42
+ end
43
+
44
+ def self.feature_paths=(new_feature_path)
45
+ @@feature_paths = new_feature_path
46
+ end
47
+
48
+ @@router ||= Gurk::Router.new
49
+
50
+ def self.router
51
+ @@router
52
+ end
53
+
54
+ def self.run
55
+ puts self.feature_paths
56
+ parsed = Gurk::Parser.new(self.feature_paths).parse!
57
+
58
+ parsed.each do |p|
59
+ router.add Gurk::Page.new(p)
60
+ end
61
+
62
+ self.router
63
+ end
64
+
65
+ end
data/lib/gurk/cli.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'thor'
2
+ module Gurk
3
+ class Cli < Thor::Group
4
+ include Thor::Actions
5
+
6
+ argument :name
7
+
8
+ def self.source_root
9
+ File.dirname(__FILE__)
10
+ end
11
+
12
+ def setup
13
+ directory "../templates", name, recursive: true
14
+ end
15
+
16
+ def bundle_install
17
+ system("cd #{name} && bundle install")
18
+ end
19
+
20
+ end
21
+ end
data/lib/gurk/page.rb ADDED
@@ -0,0 +1,71 @@
1
+ require 'erb'
2
+ require 'tilt'
3
+
4
+ module Gurk
5
+ class Page
6
+ attr_accessor :name, :route, :locals, :layout
7
+
8
+ def initialize(data)
9
+ @name = data[:name].downcase
10
+ @locals = data[:locals]
11
+ @route = data[:route]
12
+ @layout= data[:locals][:layout] if data[:locals] && data[:locals][:layout]
13
+ end
14
+
15
+ def render(env)
16
+ output = nil
17
+
18
+ if @layout
19
+ output = render_template_with_layout(env) do
20
+ render_template(env)
21
+ end
22
+ else
23
+ output = render_template(env)
24
+ end
25
+
26
+ [200, {'content_type' => 'text/html'}, [output]]
27
+
28
+ rescue Errno::ENOENT => e
29
+ raise Gurk::TemplateNotFound.new(e)
30
+ rescue RuntimeError, Exception => e
31
+ # TODO: Make this more sensible
32
+ raise e
33
+ end
34
+
35
+ def render_template_with_layout(env, &block)
36
+ tilt = Tilt.new(layout_path)
37
+ tilt.render(nil, locals) do
38
+ yield
39
+ end
40
+ end
41
+
42
+ def render_template(env)
43
+ tilt = Tilt.new(view_path)
44
+ tilt.render(nil, locals)
45
+ end
46
+
47
+ def view_name
48
+ @view_name ||= @name
49
+ end
50
+
51
+ def view_path
52
+ Gurk.view_path + '/' + view_name + '.' + Gurk.default_view_engine.to_s
53
+ end
54
+
55
+ def layout_name
56
+ @locals[:layout]
57
+ end
58
+
59
+ def layout_path
60
+ if layout_name =~ /\.(erb|haml|)/
61
+ Gurk.view_path + '/' + layout_name
62
+ else
63
+ Gurk.view_path + '/' + layout_name + '.' + Gurk.default_view_engine.to_s
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+
70
+ class Gurk::TemplateNotFound < Exception; end
71
+ class Gurk::TemplateEngineNotFound < Exception; end
@@ -0,0 +1,82 @@
1
+ require 'gherkin/parser/parser'
2
+ require 'gherkin/formatter/json_formatter'
3
+ require 'stringio'
4
+ require 'multi_json'
5
+
6
+ module Gurk
7
+ class Parser
8
+ VALID_STEPS = [
9
+ { "^I have a page called '(.+)'$" => lambda { |k, _| { name: k } } },
10
+ { "^it has a route of '(.+)'$" => lambda { |k, _| { route: k } } },
11
+ { "^it has a (.+) called '(.+)'$" => lambda { |k, v| { k.to_sym => v } } }
12
+ ]
13
+
14
+ attr_accessor :sources
15
+
16
+ def initialize(sources = Dir.glob("#{Dir.pwd}/features/*.feature"))
17
+ @parsed_names = []
18
+ @parsed_data = []
19
+ @sources = sources
20
+ io = StringIO.new
21
+ formatter = Gherkin::Formatter::JSONFormatter.new(io)
22
+ parser = Gherkin::Parser::Parser.new(formatter)
23
+ read_feature_files(io, parser, formatter, sources)
24
+ end
25
+
26
+ def parse!
27
+ @parsed_names.each { |name| parse_names(name) }
28
+ parse_locals(@parsed_data)
29
+ end
30
+
31
+ private
32
+
33
+ def read_feature_files(io, parser, formatter, sources)
34
+ sources.each { |s| parser.parse(IO.read(s), s, 0) }
35
+ formatter.done
36
+ process_data(MultiJson.load(io.string))
37
+ end
38
+
39
+ def process_data(data)
40
+ data.each { |feature| extract_steps_from feature['elements'] }
41
+ end
42
+
43
+ def extract_steps_from(element_nodes)
44
+ element_nodes.each { |element_node| @parsed_names << extract_names_from(element_node['steps']) }
45
+ end
46
+
47
+ def extract_names_from(steps)
48
+ [].tap { |name| steps.each { |step| name << step['name'] } }
49
+ end
50
+
51
+ def parse_names(name)
52
+ @parsed_data << name.map { |match| parse_steps(match) }.flatten.compact
53
+ end
54
+
55
+ def parse_steps(match)
56
+ VALID_STEPS.map { |step| step.values.first.call($1, $2) if /#{step.keys.first}/ =~ match }
57
+ end
58
+
59
+ def parse_locals(steps)
60
+ @parsed_data = [].tap do |data|
61
+ steps.map do |step|
62
+ locals = sanitize(step)
63
+ step << { locals: extract_locals_from(step, locals) }
64
+ data << merge_steps(step)
65
+ end
66
+ end
67
+ end
68
+
69
+ def sanitize(step)
70
+ step.dup.reject! { |h| h.key?(:route) || h.key?(:name) }
71
+ end
72
+
73
+ def extract_locals_from(step, locals)
74
+ step.reject! { |h| h == locals.first }
75
+ locals.first
76
+ end
77
+
78
+ def merge_steps(step)
79
+ {}.tap { |data| step.each { |h| data.merge! h } }
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,31 @@
1
+ require 'http_router'
2
+
3
+ module Gurk
4
+ class Router
5
+
6
+ def initialize
7
+ http_router
8
+ end
9
+
10
+ def http_router
11
+ @http_router ||= HttpRouter.new
12
+ end
13
+
14
+ def add(page)
15
+ routes.push(page)
16
+ http_router.add(page.route).to { |env|
17
+ page.render env
18
+ }
19
+ end
20
+
21
+ def routes
22
+ @routes ||= []
23
+ end
24
+
25
+ def call(env)
26
+ http_router.call(env)
27
+ end
28
+
29
+ end
30
+ end
31
+
@@ -0,0 +1,25 @@
1
+ require 'thor'
2
+ require 'gurk/cli'
3
+
4
+ module Gurk
5
+
6
+ class Runner < Thor
7
+
8
+ map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
9
+
10
+ desc "new app_name", "Generates a new Gurk application"
11
+ method_options :as => :string, :relative => :boolean, :force => :boolean
12
+ def new(name)
13
+ Gurk::Cli.new([name]).setup
14
+ say "New Gurk app generated. Now start Gurkin!"
15
+ end
16
+
17
+ desc "version", "Show Gurk version"
18
+ def version
19
+ require 'thor/version'
20
+ say "Gurk #{Gurk::VERSION}"
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,3 @@
1
+ module Gurk
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'gurk'
4
+
5
+ # Uncomment if you want to use haml
6
+ # gem 'haml'
7
+
8
+ # Uncomment if you want to use cucumber
9
+
10
+ # group :test do
11
+ # gem 'cucumber'
12
+ # gem 'rack-test'
13
+ # end
@@ -0,0 +1,6 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+ Bundler.require
4
+
5
+ require 'gurk'
6
+ App = Gurk.run
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ require './app'
2
+
3
+ run App = Gurk.run
@@ -0,0 +1,15 @@
1
+ Feature: My site
2
+
3
+ Scenario: Home Page
4
+ Given I have a page called 'Home'
5
+ And it has a title called 'home'
6
+ And it has a route of '/'
7
+ When I visit '/'
8
+ Then I should see 'home'
9
+
10
+ Scenario: About
11
+ Given I have a page called 'About'
12
+ And it has a title called 'About Us'
13
+ And it has a route of '/about'
14
+ When I visit '/about'
15
+ Then I should see 'About Us'
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'gurk', path: '../../'
@@ -0,0 +1,6 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+ Bundler.require
4
+
5
+ require 'gurk'
6
+ App = Gurk.run
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <title><%= title %></title>
3
+
4
+ <body>
5
+ <p>Hey You,</p>
6
+ <p>Keep being awesome. Because being awesome is awesome.</p>
7
+ <p>- You</p>
8
+
9
+ </body>
10
+
11
+ </html>
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <title><%= title %></title>
3
+
4
+ <body>
5
+ <p>Hey You,</p>
6
+ <p>Keep being awesome. Because being awesome is awesome.</p>
7
+ <p>- You</p>
8
+
9
+ </body>
10
+
11
+ </html>
@@ -0,0 +1,3 @@
1
+ require './app'
2
+
3
+ run App = Gurk.run
@@ -0,0 +1,15 @@
1
+ Feature: My site
2
+
3
+ Scenario: Home Page
4
+ Given I have a page called 'Home'
5
+ And it has a title called 'home'
6
+ And it has a route of '/'
7
+ When I visit '/'
8
+ Then I should see 'home'
9
+
10
+ Scenario: About
11
+ Given I have a page called 'About'
12
+ And it has a title called 'About Us'
13
+ And it has a route of '/about'
14
+ When I visit '/about'
15
+ Then I should see 'About Us'
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gurk::Cli do
4
+
5
+ let(:sample_directory) {
6
+ File.join(Dir.pwd, "spec", "support", "testapp")
7
+ }
8
+
9
+ before do
10
+ FileUtils.rm_rf sample_directory
11
+
12
+ ARGV.replace []
13
+ ARGV << sample_directory
14
+
15
+ cli = Gurk::Cli.new ARGV
16
+ cli.setup
17
+ end
18
+
19
+ describe "#setup" do
20
+
21
+ it 'creates the app directory' do
22
+ expect(File.exists?(sample_directory)).to be_true
23
+ end
24
+
25
+ it 'creates individual app files' do
26
+ expect(File.exists?(File.join(sample_directory, 'config.ru'))).to be_true
27
+ expect(File.exists?(File.join(sample_directory, 'app.rb'))).to be_true
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
@@ -0,0 +1,27 @@
1
+ require 'rack/test'
2
+ require File.join(File.dirname(__FILE__), '/../example/app.rb')
3
+
4
+ include Rack::Test::Methods
5
+
6
+ describe 'Gurk::Example' do
7
+
8
+ before do
9
+ Gurk.stub(:view_path).and_return File.join('spec', 'example', 'app', 'views')
10
+ Gurk.stub(:feature_paths).and_return Dir.glob("#{Dir.pwd}/spec/example/features/*.feature")
11
+
12
+ request '/'
13
+ end
14
+
15
+ def app
16
+ Gurk.run
17
+ end
18
+
19
+ it 'returns homepage successfully' do
20
+ expect(last_response.status).to eq(200)
21
+ end
22
+
23
+ it 'shows the title' do
24
+ expect(last_response.body).to include ('home')
25
+ end
26
+
27
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ include Rack::Test::Methods
4
+
5
+ describe Gurk do
6
+
7
+ describe '#run' do
8
+
9
+ before do
10
+ Gurk.stub(:feature_paths).and_return Dir.glob("#{Dir.pwd}/spec/support/*.feature")
11
+ Gurk.run
12
+ end
13
+
14
+ it 'creates routes from the array' do
15
+ expect(Gurk.router.routes.length).to_not be_zero
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+
22
+
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gurk::Page do
4
+
5
+ describe '#pages' do
6
+
7
+ Gurk.view_path = File.join(Dir.pwd, 'spec', 'support', 'views')
8
+
9
+ let(:page) {
10
+ Gurk::Page.new({name: 'about', path: '/pages/slug', locals: {title: 'lalala'}})
11
+ }
12
+
13
+ it 'returns the view name' do
14
+ expect(page.view_name).to eq('about')
15
+ end
16
+
17
+ context "nolayout" do
18
+ it 'returns the layout name' do
19
+ expect(page.layout_name).to be_nil
20
+ end
21
+ end
22
+
23
+ context "with a layout" do
24
+ it 'returns the layout name' do
25
+ page.locals.merge!(layout: 'wat')
26
+ expect(page.layout_name).to eq 'wat'
27
+ end
28
+ end
29
+ end
30
+
31
+ describe '#render' do
32
+
33
+ it 'render the page' do
34
+ page = Gurk::Page.new({name: 'about', path: '/pages/slug', locals: {title: 'lalala'}})
35
+ result = page.render nil
36
+ expect(result.last.first).to include 'lalala'
37
+ end
38
+
39
+ it 'renders the page with the layout' do
40
+ page = Gurk::Page.new({name: 'about', path: '/pages/slug', locals: {title: 'lalala', layout: 'layout.erb'}})
41
+ result = page.render nil
42
+
43
+ expect(result.last.first).to include 'This is the layout'
44
+ expect(result.last.first).to include 'lalala'
45
+ end
46
+
47
+ it 'raises an exception if the template is invalid' do
48
+ page = Gurk::Page.new({name: 'aboutlalala', path: '/pages/slug', locals: {title: 'lalala'}})
49
+ expect {
50
+ page.render nil
51
+ }.to raise_exception(Gurk::TemplateNotFound)
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,210 @@
1
+ require 'spec_helper'
2
+
3
+ describe Gurk::Parser do
4
+
5
+ let(:sources) do
6
+ #Dir.glob("#{Dir.pwd}/spec/support/*.feature")
7
+ [ "#{Dir.pwd}/spec/support/another_example.feature", "#{Dir.pwd}/spec/support/example.feature" ]
8
+ end
9
+
10
+ let(:parsed_data) do
11
+ [
12
+ { :name => "About", :route => "/about", :locals => { :title=>"about" } },
13
+ { :name => "Home", :route => "/", :locals => { :title => "home" } }
14
+ ]
15
+ end
16
+
17
+ let(:steps) do
18
+ [ ["I have a page called 'About'",
19
+ "it has a title called 'about'",
20
+ "it has a route of '/about'",
21
+ "I visit '/about'",
22
+ "I should see 'about'",],
23
+ ["I have a page called 'Home'",
24
+ "it has a title called 'home'",
25
+ "it has a route of '/'",
26
+ "I visit '/'",
27
+ "I should see 'home'"] ]
28
+ end
29
+
30
+ let(:parsed_steps) do
31
+ [ {"keyword"=>"Given ", "name"=>"I have a page called 'About'", "line"=>4},
32
+ {"keyword"=>"And ", "name"=>"it has a title called 'about'", "line"=>5},
33
+ {"keyword"=>"And ", "name"=>"it has a route of '/about'", "line"=>6},
34
+ {"keyword"=>"When ", "name"=>"I visit '/about'", "line"=>7},
35
+ {"keyword"=>"Then ", "name"=>"I should see 'about'", "line"=>8}]
36
+ [ {"keyword"=>"Given ", "name"=>"I have a page called 'Home'", "line"=>4},
37
+ {"keyword"=>"And ", "name"=>"it has a title called 'home'", "line"=>5},
38
+ {"keyword"=>"And ", "name"=>"it has a route of '/'", "line"=>6},
39
+ {"keyword"=>"When ", "name"=>"I visit '/'", "line"=>7},
40
+ {"keyword"=>"Then ", "name"=>"I should see 'home'", "line"=>8}]
41
+ end
42
+
43
+ let(:parsed_names) do
44
+ [ ["I have a page called 'About'",
45
+ "it has a title called 'about'",
46
+ "it has a route of '/about'",
47
+ "I visit '/about'",
48
+ "I should see 'about'"],
49
+ ["I have a page called 'Home'",
50
+ "it has a title called 'home'",
51
+ "it has a route of '/'",
52
+ "I visit '/'",
53
+ "I should see 'home'"] ]
54
+ end
55
+
56
+ describe '#initialize' do
57
+ it 'reads existing feature files' do
58
+ Gurk::Parser.any_instance.should_receive(:read_feature_files)
59
+ Gurk::Parser.new(sources)
60
+ end
61
+ end
62
+
63
+ describe '#parse!' do
64
+ it 'parses each set of names extracted from the feature files' do
65
+ Gurk::Parser
66
+ .any_instance
67
+ .should_receive(:parse_names)
68
+ .exactly(parsed_names.length)
69
+ .times
70
+ Gurk::Parser.new(sources).parse!
71
+ end
72
+
73
+ it 'passes the parsed data to #parse_locals' do
74
+ parser = Gurk::Parser.new(sources)
75
+ Gurk::Parser
76
+ .any_instance
77
+ .should_receive(:parse_locals)
78
+ .with(parser.instance_variable_get :@parsed_data)
79
+ parser.parse!
80
+ end
81
+
82
+ it 'returns a hash with the correct format' do
83
+ expect(Gurk::Parser.new(sources).parse!).to eq parsed_data
84
+ end
85
+ end
86
+
87
+ describe 'private methods' do
88
+ let(:parser) { Gurk::Parser.new(sources) }
89
+
90
+ describe '#read_feature_files' do
91
+ it 'parses the feature files' do
92
+ Gherkin::Parser::Parser
93
+ .any_instance
94
+ .should_receive(:parse)
95
+ .exactly(parsed_names.length)
96
+ .times
97
+ Gurk::Parser.new(sources)
98
+ end
99
+
100
+ it 'passes the result to #process_data' do
101
+ Gurk::Parser.any_instance.should_receive(:process_data)
102
+ Gurk::Parser.new(sources)
103
+ end
104
+ end
105
+
106
+ describe '#process_data' do
107
+ it 'finds all "elements" nodes in the given data and passes it to #extract_steps_from' do
108
+ Gurk::Parser
109
+ .any_instance
110
+ .should_receive(:extract_steps_from)
111
+ .twice # Two 'element' nodes
112
+ Gurk::Parser.new(sources)
113
+ end
114
+ end
115
+
116
+ describe '#extract_steps_from' do
117
+ it 'finds all "steps" nodes in the given data and passes it to #extract_names_from' do
118
+ Gurk::Parser
119
+ .any_instance
120
+ .should_receive(:extract_names_from)
121
+ .twice # Two 'steps' nodes
122
+ Gurk::Parser.new(sources)
123
+ end
124
+
125
+ it 'saves the return value of #extract_names_from' do
126
+ expect(parser.instance_variable_get :@parsed_names).to eq parsed_names
127
+ end
128
+ end
129
+
130
+ describe '#extract_names_from' do
131
+ it 'finds and returns all "name" nodes from the given data' do
132
+ expect(parser.send(:extract_names_from, parsed_steps)).to eq parsed_names.last
133
+ end
134
+ end
135
+
136
+ describe '#parse_names' do
137
+ it 'passes the given data to #parse_steps' do
138
+ Gurk::Parser
139
+ .any_instance
140
+ .should_receive(:parse_names)
141
+ .exactly(parsed_names.length)
142
+ .times
143
+ Gurk::Parser.new(sources).parse!
144
+ end
145
+ end
146
+
147
+ describe '#parse_steps' do
148
+ context 'with a matching step' do
149
+ it 'returns the parsed step' do
150
+ expect(parser.send(:parse_steps, "I have a page called 'About'")).to include name: 'About'
151
+ end
152
+ end
153
+
154
+ context 'with a non-matching step' do
155
+ it 'returns an array of nils' do
156
+ expect(parser.send(:parse_steps, "I visit '/about'")).to eq [nil, nil, nil]
157
+ end
158
+ end
159
+ end
160
+
161
+ describe '#parse_locals' do
162
+ let(:step) { [[{:name=>"About"}, {:title=>"about"}, {:route=>"/about"}]] }
163
+
164
+ it 'passes each given step to #sanitize' do
165
+ parser.stub(:extract_locals_from)
166
+ parser.should_receive(:sanitize)
167
+ parser.send :parse_locals, step
168
+ end
169
+
170
+ it 'passes sanitized steps to #extract_locals_from' do
171
+ parser.should_receive(:extract_locals_from)
172
+ parser.send :parse_locals, step
173
+ end
174
+
175
+ it 'passes extracted locals to #merge_steps' do
176
+ parser.should_receive(:merge_steps)
177
+ parser.send :parse_locals, step
178
+ end
179
+
180
+ it 'returns the result of the parsing' do
181
+ result = [{:name=>"About", :route=>"/about", :locals => {:title=>"about"}}]
182
+ parser.instance_variable_set(:@parsed_data, step)
183
+ expect(parser.send :parse_locals, step).to eq result
184
+ end
185
+ end
186
+
187
+ describe '#sanitize' do
188
+ it 'returns local variable pairs' do
189
+ step = [{:name=>"About"}, {:title=>"about"}, {:route=>"/about"}]
190
+ expect(parser.send :sanitize, step).to eq [{:title=>"about"}]
191
+ end
192
+ end
193
+
194
+ describe '#extract_locals_from' do
195
+ it 'returns parsed locals' do
196
+ step = [[{:name=>"About"}, {:title=>"about"}, {:route=>"/about"}]]
197
+ local = [{:title=>"about"}]
198
+ expect(parser.send :extract_locals_from, step, local).to eq local.first
199
+ end
200
+ end
201
+
202
+ describe '#merge_steps' do
203
+ it 'returns merged steps' do
204
+ step = [{:name=>"About"}, {:route=>"/about"}, {:locals=>[{:title=>"about"}]}]
205
+ result = { :name => "About", :route => "/about", :locals => [ { :title=>"about" } ] }
206
+ expect(parser.send :merge_steps, step).to eq result
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,44 @@
1
+ require File.join(File.dirname(__FILE__), '/../', 'spec_helper')
2
+
3
+ include Rack::Test::Methods
4
+
5
+ describe Gurk::Router do
6
+
7
+ before do
8
+ @router = Gurk::Router.new
9
+ end
10
+
11
+ def app
12
+ @router
13
+ end
14
+
15
+ it 'returns a valid instance' do
16
+ expect(@router).to be_instance_of Gurk::Router
17
+ end
18
+
19
+ it 'returns a valid http_router instance' do
20
+ expect(@router.http_router).to be_instance_of HttpRouter
21
+ end
22
+
23
+ it 'adds a page with a valid content' do
24
+ page = Gurk::Page.new({name: 'about', path: '/about', locals: {title: 'lalala'}})
25
+
26
+ @router.add page
27
+
28
+ request "/about"
29
+
30
+ expect(last_response.status).to eq(200)
31
+ end
32
+
33
+ it 'adds a page with a valid content with params' do
34
+
35
+ page = Gurk::Page.new({name: 'about', path: '/pages/slug', locals: {title: 'lalala'}})
36
+
37
+ @router.add page
38
+
39
+ request '/pages/this-is-a-slug'
40
+
41
+ expect(last_response.status).to eq(200)
42
+ end
43
+
44
+ end
@@ -0,0 +1,8 @@
1
+ require 'gurk'
2
+ require 'gurk/router'
3
+ require 'gurk/page'
4
+ require 'gurk/parser'
5
+ require 'gurk/cli'
6
+
7
+ require 'rack/test'
8
+
@@ -0,0 +1,8 @@
1
+ Feature: About Page
2
+
3
+ Scenario:
4
+ Given I have a page called 'About'
5
+ And it has a title called 'about'
6
+ And it has a route of '/about'
7
+ When I visit '/about'
8
+ Then I should see 'about'
@@ -0,0 +1,8 @@
1
+ Feature: Home Page
2
+
3
+ Scenario:
4
+ Given I have a page called 'Home'
5
+ And it has a title called 'home'
6
+ And it has a route of '/'
7
+ When I visit '/'
8
+ Then I should see 'home'
@@ -0,0 +1,10 @@
1
+ Feature: Home Page
2
+
3
+ Scenario:
4
+ Given I have a page called 'Home'
5
+ And it has a title called 'home'
6
+ And it has a layout called 'home'
7
+ And it has a template called 'home.html.erb'
8
+ And it has a route of '/'
9
+ When I visit '/'
10
+ Then I should see 'home'
@@ -0,0 +1 @@
1
+ Title: <%= title %>
@@ -0,0 +1,6 @@
1
+ <html>
2
+ <body>
3
+ <p>This is the layout</p>
4
+ <div><%= yield %></div>
5
+ </body>
6
+ </html>
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gurk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Vixon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-09-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &70173898733100 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70173898733100
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &70173898732340 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70173898732340
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70173898731580 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70173898731580
47
+ - !ruby/object:Gem::Dependency
48
+ name: rack-test
49
+ requirement: &70173898731080 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70173898731080
58
+ - !ruby/object:Gem::Dependency
59
+ name: gherkin
60
+ requirement: &70173898730580 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70173898730580
69
+ - !ruby/object:Gem::Dependency
70
+ name: http_router
71
+ requirement: &70173898729900 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 0.11.0
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *70173898729900
80
+ - !ruby/object:Gem::Dependency
81
+ name: tilt
82
+ requirement: &70173898729400 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: *70173898729400
91
+ - !ruby/object:Gem::Dependency
92
+ name: thor
93
+ requirement: &70173898728840 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *70173898728840
102
+ description: Gurk
103
+ email:
104
+ - vixonshow@gmail.com
105
+ executables:
106
+ - gurk
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - .gitignore
111
+ - .rspec
112
+ - Gemfile
113
+ - LICENSE.txt
114
+ - README.md
115
+ - Rakefile
116
+ - bin/gurk
117
+ - gurk.gemspec
118
+ - lib/gurk.rb
119
+ - lib/gurk/cli.rb
120
+ - lib/gurk/page.rb
121
+ - lib/gurk/parser.rb
122
+ - lib/gurk/router.rb
123
+ - lib/gurk/runner.rb
124
+ - lib/gurk/version.rb
125
+ - lib/templates/Gemfile
126
+ - lib/templates/app.rb
127
+ - lib/templates/app/views/home.erb
128
+ - lib/templates/app/views/layout.erb
129
+ - lib/templates/config.ru
130
+ - lib/templates/features/home.feature
131
+ - spec/example/Gemfile
132
+ - spec/example/app.rb
133
+ - spec/example/app/views/about.erb
134
+ - spec/example/app/views/home.erb
135
+ - spec/example/config.ru
136
+ - spec/example/features/home.feature
137
+ - spec/gurk/cli_spec.rb
138
+ - spec/gurk/example_spec.rb
139
+ - spec/gurk/gurk_spec.rb
140
+ - spec/gurk/page_spec.rb
141
+ - spec/gurk/parser_spec.rb
142
+ - spec/gurk/router_spec.rb
143
+ - spec/spec_helper.rb
144
+ - spec/support/another_example.feature
145
+ - spec/support/example.feature
146
+ - spec/support/example_with_layout.feature
147
+ - spec/support/views/about.erb
148
+ - spec/support/views/layout.erb
149
+ homepage: http://github.com/vixon/gurk
150
+ licenses:
151
+ - MIT
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ none: false
158
+ requirements:
159
+ - - ! '>='
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ! '>='
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubyforge_project:
170
+ rubygems_version: 1.8.15
171
+ signing_key:
172
+ specification_version: 3
173
+ summary: A plain english ruby microframework that makes sense
174
+ test_files:
175
+ - spec/example/Gemfile
176
+ - spec/example/app.rb
177
+ - spec/example/app/views/about.erb
178
+ - spec/example/app/views/home.erb
179
+ - spec/example/config.ru
180
+ - spec/example/features/home.feature
181
+ - spec/gurk/cli_spec.rb
182
+ - spec/gurk/example_spec.rb
183
+ - spec/gurk/gurk_spec.rb
184
+ - spec/gurk/page_spec.rb
185
+ - spec/gurk/parser_spec.rb
186
+ - spec/gurk/router_spec.rb
187
+ - spec/spec_helper.rb
188
+ - spec/support/another_example.feature
189
+ - spec/support/example.feature
190
+ - spec/support/example_with_layout.feature
191
+ - spec/support/views/about.erb
192
+ - spec/support/views/layout.erb