belly 0.0.0 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  coverage
4
4
  rdoc
5
5
  pkg
6
+ tmp
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = belly-gem
2
2
 
3
- Client app for the awesome new belly web service. Coming soon.
3
+ Client app for the incredible new belly web service, coming soon.
4
4
 
5
5
  == Copyright
6
6
 
data/Rakefile CHANGED
@@ -5,8 +5,8 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "belly"
8
- gem.summary = %Q{Client app for the belly web service}
9
- gem.description = %Q{Client app for the belly web service}
8
+ gem.summary = %Q{Client app for the incredible new belly web service, coming soon.}
9
+ gem.description = %Q{Client app for the incredible new belly web service, coming soon.}
10
10
  gem.email = "matt@mattwynne.net"
11
11
  gem.homepage = "http://github.com/mattwynne/belly-mouth"
12
12
  gem.authors = ["Matt Wynne"]
data/TODO ADDED
@@ -0,0 +1,4 @@
1
+ Work out why I can't use cucumber -r, and have to require 'belly' explicitly instead. annoying.
2
+ Replace sinatra FakeHub with a rack app
3
+ CLI tools for initing a project (like heroku)
4
+ default config for host / port pointing to production so gem has it hard-coded
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.2
data/belly.gemspec CHANGED
@@ -1,20 +1,23 @@
1
1
  # Generated by jeweler
2
- # DO NOT EDIT THIS FILE
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{belly}
8
- s.version = "0.0.0"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Matt Wynne"]
12
- s.date = %q{2009-10-12}
13
- s.description = %q{Client app for the belly web service}
12
+ s.date = %q{2010-07-19}
13
+ s.default_executable = %q{belly}
14
+ s.description = %q{Client app for the incredible new belly web service, coming soon.}
14
15
  s.email = %q{matt@mattwynne.net}
16
+ s.executables = ["belly"]
15
17
  s.extra_rdoc_files = [
16
18
  "LICENSE",
17
- "README.rdoc"
19
+ "README.rdoc",
20
+ "TODO"
18
21
  ]
19
22
  s.files = [
20
23
  ".document",
@@ -22,27 +25,41 @@ Gem::Specification.new do |s|
22
25
  "LICENSE",
23
26
  "README.rdoc",
24
27
  "Rakefile",
28
+ "TODO",
25
29
  "VERSION",
26
30
  "belly.gemspec",
31
+ "bin/belly",
32
+ "features/publish_scenario_results.feature",
33
+ "features/step_definitions/belly_steps.rb",
34
+ "features/step_definitions/cucumber_steps.rb",
27
35
  "features/support/env.rb",
36
+ "features/support/fake_hub.rb",
28
37
  "lib/belly.rb",
38
+ "lib/belly/cli.rb",
39
+ "lib/belly/cli/init.rb",
29
40
  "lib/belly/client.rb",
41
+ "lib/belly/client/config.rb",
42
+ "lib/belly/for/cucumber.rb",
43
+ "lib/belly/project_initializer.rb",
44
+ "lib/belly/user_credentials.rb",
45
+ "spec/belly/project_initializer_spec.rb",
30
46
  "spec/spec_helper.rb"
31
47
  ]
32
48
  s.homepage = %q{http://github.com/mattwynne/belly-mouth}
33
49
  s.rdoc_options = ["--charset=UTF-8"]
34
50
  s.require_paths = ["lib"]
35
- s.rubygems_version = %q{1.3.4}
36
- s.summary = %q{Client app for the belly web service}
51
+ s.rubygems_version = %q{1.3.7}
52
+ s.summary = %q{Client app for the incredible new belly web service, coming soon.}
37
53
  s.test_files = [
38
- "spec/spec_helper.rb"
54
+ "spec/belly/project_initializer_spec.rb",
55
+ "spec/spec_helper.rb"
39
56
  ]
40
57
 
41
58
  if s.respond_to? :specification_version then
42
59
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
60
  s.specification_version = 3
44
61
 
45
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
62
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
63
  s.add_development_dependency(%q<rspec>, [">= 0"])
47
64
  s.add_development_dependency(%q<cucumber>, [">= 0"])
48
65
  else
@@ -54,3 +71,4 @@ Gem::Specification.new do |s|
54
71
  s.add_dependency(%q<cucumber>, [">= 0"])
55
72
  end
56
73
  end
74
+
data/bin/belly ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ require "rubygems"
3
+ require "trollop"
4
+
5
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
6
+ require 'belly'
7
+ require 'belly/cli'
8
+
9
+ Trollop::options do
10
+ banner <<-EOS
11
+ === Commands
12
+
13
+ init Create a new project for the current folder
14
+ help <command> Get some help on a particular command
15
+
16
+ EOS
17
+ stop_on Belly::Cli::COMMANDS
18
+ end
19
+
20
+ command = ARGV.shift
21
+
22
+ Trollop.die("You need to tell me what to do") unless command
23
+
24
+ unless Belly::Cli::COMMANDS.include?(command)
25
+ Trollop.die("Don't know that command, sorry")
26
+ end
27
+
28
+ require "belly/cli/#{command}"
@@ -0,0 +1,59 @@
1
+ Feature: Publish scenario results
2
+ In order to allow users to see the history of a particular scenario
3
+ As a developer
4
+ I want the belly gem to publish the results of each scenario to the belly service
5
+
6
+ Background:
7
+ Given a standard Cucumber project directory structure
8
+ And a file named "features/support/belly.rb" with:
9
+ """
10
+ require 'belly' rescue puts("Could not load belly - do you need to install the gem?")
11
+
12
+ """
13
+
14
+ And a file named "features/step_definitions/foo_steps.rb" with:
15
+ """
16
+ Given /^I am a rock$/ do
17
+ end
18
+
19
+ Given /^I am thin ice$/ do
20
+ raise("yikes")
21
+ end
22
+
23
+ """
24
+ And a file named ".belly" with:
25
+ """
26
+ hub: localhost:12345
27
+
28
+ """
29
+ And there is a belly-hub running on localhost:12345
30
+
31
+ Scenario: Run a test with a scenario that passes
32
+ Given a file named "features/foo.feature" with:
33
+ """
34
+ Feature: Test
35
+ Scenario: Solid
36
+ Given I am a rock
37
+
38
+ """
39
+ When I run cucumber -r belly -r features -v
40
+ And the belly-hub should have received the following requests:
41
+ | type | path | data |
42
+ | POST | /scenarios | {"status":"passed","id":{"scenario":"Solid","feature":"Test"}} |
43
+
44
+ Scenario: Run a test with a scenario that fails
45
+ And a file named "features/foo.feature" with:
46
+ """
47
+ Feature: Test
48
+ Scenario: Solid
49
+ Given I am a rock
50
+
51
+ Scenario: Shaky
52
+ Given I am thin ice
53
+
54
+ """
55
+ When I run cucumber -r belly -r features -v
56
+ And the belly-hub should have received the following requests:
57
+ | type | path | data |
58
+ | POST | /scenarios | {"status":"passed","id":{"scenario":"Solid","feature":"Test"}} |
59
+ | POST | /scenarios | {"status":"failed","id":{"scenario":"Shaky","feature":"Test"}} |
@@ -0,0 +1,19 @@
1
+ require 'aruba'
2
+
3
+ Given /^there is a belly\-hub running on localhost:12345$/ do
4
+ @hub = Belly::FakeHub.run(12345)
5
+ end
6
+
7
+ Then /^the belly\-hub should have received the following requests:$/ do |table|
8
+ requests = @hub.requests.map do |r|
9
+ result = r.dup
10
+ result["data"] = JSON.parse(r["data"])
11
+ result
12
+ end
13
+
14
+ table.map_column!('data') do |raw_data|
15
+ JSON.parse(raw_data)
16
+ end
17
+
18
+ table.diff! requests
19
+ end
@@ -0,0 +1,12 @@
1
+ Given /^a standard Cucumber project directory structure$/ do
2
+ in_current_dir do
3
+ FileUtils.rm_rf 'features' if File.directory?('features')
4
+ FileUtils.mkdir_p 'features/support'
5
+ FileUtils.mkdir 'features/step_definitions'
6
+ end
7
+ end
8
+
9
+ When /^I run cucumber (.*)$/ do |cucumber_opts|
10
+ cmd = "#{Cucumber::RUBY_BINARY} -I#{belly_lib_path} #{Cucumber::BINARY} --no-color #{cucumber_opts}"
11
+ run(cmd, false)
12
+ end
@@ -1,4 +1,12 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
- require 'belly/client'
2
+ require 'aruba'
3
3
 
4
4
  require 'spec/expectations'
5
+
6
+ module BellyWorld
7
+ def belly_lib_path
8
+ File.expand_path(File.dirname(__FILE__) + '/../../lib')
9
+ end
10
+ end
11
+
12
+ World(BellyWorld)
@@ -0,0 +1,65 @@
1
+ require 'sinatra/base'
2
+ require 'json'
3
+ require 'open-uri'
4
+
5
+ module Belly
6
+ class FakeHub
7
+ class << self
8
+ def run(port)
9
+ return @instance if @instance
10
+ @instance = new(port)
11
+ end
12
+ end
13
+
14
+ class App < Sinatra::Base
15
+ module Requests
16
+ class << self
17
+ def all
18
+ @requests ||= []
19
+ end
20
+
21
+ def add(data)
22
+ all << data
23
+ end
24
+
25
+ def clear!
26
+ @requests = []
27
+ end
28
+ end
29
+ end
30
+
31
+ get '/requests' do
32
+ Requests.clear! if params['delete']
33
+ Requests.all.to_json
34
+ end
35
+
36
+ post '*' do
37
+ Requests.add({
38
+ 'type' => request.env['REQUEST_METHOD'],
39
+ 'path' => '/scenarios',
40
+ 'data' => request.body.read }
41
+ )
42
+ ''
43
+ end
44
+ end
45
+
46
+ def initialize(port)
47
+ @port = port
48
+ @runner = Thread.new do
49
+ App.run! :host => 'localhost', :port => port
50
+ end
51
+ end
52
+
53
+ def requests
54
+ JSON.parse(open("http://localhost:#{@port}/requests").read)
55
+ end
56
+
57
+ def clear_requests!
58
+ open("http://localhost:#{@port}/requests?delete=yeah")
59
+ end
60
+ end
61
+ end
62
+
63
+ After do
64
+ @hub.clear_requests!
65
+ end
data/lib/belly.rb CHANGED
@@ -0,0 +1,43 @@
1
+ $:.push(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ require 'belly/client'
4
+ require 'belly/client/config'
5
+ require 'json'
6
+
7
+ module Belly
8
+ class << self
9
+ def log(message)
10
+ return unless ENV['BELLY_LOG']
11
+ puts "* [Belly] #{message}"
12
+ end
13
+
14
+ def publish(scenario)
15
+ feature_name = scenario.feature.name.split("\n").first # TODO: only needed for older cucumbers
16
+ data = {
17
+ :id => { :feature => feature_name, :scenario => scenario.name },
18
+ :status => scenario.status,
19
+ :project => config.project
20
+ }.to_json
21
+
22
+ Belly.log("publishing #{data}")
23
+
24
+ # Break out a thread so we don't slow down the tests
25
+ thread = Thread.new { hub.post_test_result(data) }
26
+
27
+ # Make sure the thread gets a chance to finish before the process exits
28
+ at_exit { thread.join }
29
+ end
30
+
31
+ def config
32
+ @config ||= Config.new
33
+ end
34
+
35
+ def user_credentials
36
+ @user_credentials ||= UserCredentials.new(config)
37
+ end
38
+
39
+ def hub
40
+ @hub ||= Belly::Client.new(config)
41
+ end
42
+ end
43
+ end
data/lib/belly/cli.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Belly
2
+ module Cli
3
+ COMMANDS = %w(init)
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'belly/project_initializer'
2
+
3
+ options = Trollop::options do
4
+ banner <<-EOF
5
+ This is the help for the init command. To see all commands availlable, type belly --help
6
+
7
+ Usage: belly init <args>
8
+
9
+ Initialize your project for use with the belly web service
10
+
11
+ EOF
12
+ opt :name, "Name of the project", :default => File.basename(Dir.pwd)
13
+ end
14
+
15
+ Belly::ProjectInitializer.new(options).run(Trollop)
data/lib/belly/client.rb CHANGED
@@ -0,0 +1,23 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
4
+ module Belly
5
+ class Client
6
+ def initialize(config)
7
+ @config = config
8
+ end
9
+
10
+ def get(uri)
11
+
12
+ end
13
+
14
+ def post_test_result(data)
15
+ request = Net::HTTP::Post.new(@config.url + '/test_results', {'Content-Type' =>'application/json'})
16
+ request.body = data
17
+ response = Net::HTTP.new(@config.host, @config.port).start {|http| http.request(request) }
18
+ unless response.code == "200"
19
+ raise("Failed to talk to belly hub: Response #{response.code} #{response.message}: #{response.body}")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ module Belly
2
+ class Config
3
+ class NoConfig
4
+ end
5
+
6
+ attr_reader :host, :port
7
+
8
+ class << self
9
+ def new(*args)
10
+ return NoConfig.new unless File.exists?(path)
11
+ super
12
+ end
13
+
14
+ def path
15
+ File.expand_path('.belly')
16
+ end
17
+ end
18
+
19
+ def initialize
20
+ @host, @port = config_file['hub'].split(':')
21
+ end
22
+
23
+ def url
24
+ "http://#{@host}:#{@port}"
25
+ end
26
+
27
+ def project
28
+ config_file['project']
29
+ end
30
+
31
+ private
32
+
33
+ def config_file
34
+ return @file if @file
35
+ Belly.log("pwd is #{`pwd`}")
36
+ Belly.log("Looking for config in #{Config.path}")
37
+ @file = YAML.load_file(Config.path)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,12 @@
1
+ require 'belly'
2
+
3
+ Before do |scenario|
4
+ Belly.log %{about to run scenario "#{scenario.name}"}
5
+ end
6
+
7
+ After do |scenario|
8
+ Belly.log %{result: #{scenario.status}}
9
+ Belly.publish(scenario)
10
+ end
11
+
12
+ Belly.log("Installed Cucumber hooks")
@@ -0,0 +1,30 @@
1
+ require 'belly/user_credentials'
2
+ require 'belly/client'
3
+
4
+ module Belly
5
+ class ProjectInitializer
6
+ def initialize(options, ui)
7
+ project_name = options[:name] or raise("Need a :name in the options")
8
+ @uri = "/projects/#{project_name}"
9
+ @ui = ui
10
+ end
11
+
12
+ def run
13
+ client.get(@uri, self)
14
+ end
15
+
16
+ def not_found
17
+ client.put(@uri)
18
+ end
19
+
20
+ def not_authorized
21
+ @ui.die("You don't have access to this project. You'll need to contact one of the project's collaborators and ask them to give you access.")
22
+ end
23
+
24
+ private
25
+
26
+ def client
27
+ @client ||= Client.new(Belly.user_credentials)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ module Belly
2
+ class UserCredentials
3
+ def initialize(config)
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'belly/project_initializer'
3
+
4
+ module Belly
5
+ describe ProjectInitializer do
6
+ subject { ProjectInitializer.new(:name => 'foo') }
7
+ let(:ui) { double(:die => nil) }
8
+
9
+ context "when user credentials exist" do
10
+ let(:credentials) do
11
+ double(UserCredentials,
12
+ :username => "matt",
13
+ :password => "foo")
14
+ end
15
+
16
+ class Thing
17
+ attr_reader :string
18
+ def get(string)
19
+ @string = string
20
+ end
21
+ end
22
+
23
+ let(:client) { double.as_null_object }
24
+
25
+ before(:each) do
26
+ Belly.stub(:user_credentials).and_return(credentials)
27
+ Belly::Client.stub(:new => client)
28
+ end
29
+
30
+ it "creates the client with the right credentials" do
31
+ Belly::Client.should_receive(:new).with(Belly.user_credentials).and_return(client)
32
+ subject.run(ui)
33
+ end
34
+
35
+ it "calls the projects web service" do
36
+ client.should_receive(:get).with("/projects/foo")
37
+ subject.run(ui)
38
+ end
39
+
40
+ context "if the web service gives an access denied error" do
41
+ it "tells the UI that the user doesn't have access to the project" do
42
+
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: belly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
5
11
  platform: ruby
6
12
  authors:
7
13
  - Matt Wynne
@@ -9,49 +15,71 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-10-12 00:00:00 +01:00
13
- default_executable:
18
+ date: 2010-07-19 00:00:00 +01:00
19
+ default_executable: belly
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: rspec
17
- type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
23
32
  version: "0"
24
- version:
33
+ type: :development
34
+ version_requirements: *id001
25
35
  - !ruby/object:Gem::Dependency
26
36
  name: cucumber
27
- type: :development
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
30
40
  requirements:
31
41
  - - ">="
32
42
  - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
33
46
  version: "0"
34
- version:
35
- description: Client app for the belly web service
47
+ type: :development
48
+ version_requirements: *id002
49
+ description: Client app for the incredible new belly web service, coming soon.
36
50
  email: matt@mattwynne.net
37
- executables: []
38
-
51
+ executables:
52
+ - belly
39
53
  extensions: []
40
54
 
41
55
  extra_rdoc_files:
42
56
  - LICENSE
43
57
  - README.rdoc
58
+ - TODO
44
59
  files:
45
60
  - .document
46
61
  - .gitignore
47
62
  - LICENSE
48
63
  - README.rdoc
49
64
  - Rakefile
65
+ - TODO
50
66
  - VERSION
51
67
  - belly.gemspec
68
+ - bin/belly
69
+ - features/publish_scenario_results.feature
70
+ - features/step_definitions/belly_steps.rb
71
+ - features/step_definitions/cucumber_steps.rb
52
72
  - features/support/env.rb
73
+ - features/support/fake_hub.rb
53
74
  - lib/belly.rb
75
+ - lib/belly/cli.rb
76
+ - lib/belly/cli/init.rb
54
77
  - lib/belly/client.rb
78
+ - lib/belly/client/config.rb
79
+ - lib/belly/for/cucumber.rb
80
+ - lib/belly/project_initializer.rb
81
+ - lib/belly/user_credentials.rb
82
+ - spec/belly/project_initializer_spec.rb
55
83
  - spec/spec_helper.rb
56
84
  has_rdoc: true
57
85
  homepage: http://github.com/mattwynne/belly-mouth
@@ -63,23 +91,30 @@ rdoc_options:
63
91
  require_paths:
64
92
  - lib
65
93
  required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
66
95
  requirements:
67
96
  - - ">="
68
97
  - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
69
101
  version: "0"
70
- version:
71
102
  required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
72
104
  requirements:
73
105
  - - ">="
74
106
  - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
75
110
  version: "0"
76
- version:
77
111
  requirements: []
78
112
 
79
113
  rubyforge_project:
80
- rubygems_version: 1.3.4
114
+ rubygems_version: 1.3.7
81
115
  signing_key:
82
116
  specification_version: 3
83
- summary: Client app for the belly web service
117
+ summary: Client app for the incredible new belly web service, coming soon.
84
118
  test_files:
119
+ - spec/belly/project_initializer_spec.rb
85
120
  - spec/spec_helper.rb