cukebase 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.
@@ -0,0 +1,17 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cukebase.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Emil Loer
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.
@@ -0,0 +1,56 @@
1
+ # Cukebase
2
+
3
+ This gem provides integration betweeen Cucumber and the Codebase ticketing
4
+ system. Whenever scenarios are run Cukebase will create tickets for any
5
+ scenarios it encounters. It sets the ticket status to the test result of the
6
+ scenario.
7
+
8
+ When you run Cucumber again, these tickets are updated to reflect the new
9
+ result status.
10
+
11
+ ## Usage
12
+
13
+ Add this to your Gemfile:
14
+
15
+ ```ruby
16
+ group :test do
17
+ gem 'cukebase'
18
+ end
19
+ ```
20
+
21
+ Then go to Codebase to find your API credentials and add the following to your
22
+ `features/support/env.rb` file:
23
+
24
+ ```ruby
25
+ Cukebase.config do |c|
26
+ c.project = "your-project-name"
27
+ c.username = "yourcompany/youruser"
28
+ c.api_key = "YOUR_API_KEY"
29
+ end
30
+ ```
31
+
32
+ And next time when you run Cucumber, there will be tickets made for every
33
+ scenario.
34
+
35
+ ## Future work
36
+
37
+ Here are some ideas you can send pull requests for:
38
+
39
+ * Add an option to enable/disable Cukebase, e.g. to run it only on a CI server
40
+ but not on your development machine.
41
+ * Add the ability to read credentials from a file.
42
+ * Mark tickets as obsolete when a scenario is removed instead of being
43
+ completed.
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create new Pull Request
52
+
53
+ ## License
54
+
55
+ Cukebase is MIT-licensed. I'm sure you can find a copy somewhere if you aren't
56
+ able to recite it by heart.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/cukebase/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Emil Loer"]
6
+ gem.email = ["emil@bartune.nl"]
7
+ gem.description = %q{Cukebase provides integration between Cucumber and the Codebase ticketing system}
8
+ gem.summary = %q{Cukebase provides integration between Cucumber and the Codebase ticketing system}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "cukebase"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Cukebase::VERSION
17
+
18
+ gem.add_dependency 'httparty'
19
+ gem.add_dependency 'activemodel'
20
+ gem.add_dependency 'active_attr'
21
+ end
@@ -0,0 +1,45 @@
1
+ require "httparty"
2
+ require "active_model"
3
+ require "active_attr"
4
+ require "cukebase/version"
5
+ require "cukebase/config"
6
+ require "cukebase/request"
7
+ require "cukebase/project"
8
+ require "cukebase/ticketing_category"
9
+ require "cukebase/ticketing_status"
10
+ require "cukebase/ticket"
11
+
12
+ module Cukebase
13
+ def self.current_project
14
+ @current_project ||= Project.new Cukebase.config.project
15
+ end
16
+ end
17
+
18
+ if defined? Cucumber
19
+ Around do |scenario, block|
20
+ ticket_name = "#{scenario.title} (#{scenario.feature.title})"
21
+ project = Cukebase.current_project
22
+ ticket = project.ticket_for_name ticket_name
23
+
24
+ block.call
25
+
26
+ ticket.status_id = case scenario.status
27
+ when :undefined
28
+ project.undefined_status
29
+ when :pending
30
+ project.pending_status
31
+ when :passed
32
+ project.passed_status
33
+ when :failed
34
+ project.failed_status
35
+ else
36
+ project.invalid_status
37
+ end
38
+
39
+ # We want empty features to be undefined instead of completed (which is
40
+ # what Cucumber tells us)
41
+ ticket.status_id = project.undefined_status if scenario.raw_steps.empty?
42
+
43
+ ticket.save
44
+ end
45
+ end
@@ -0,0 +1,43 @@
1
+ module Cukebase
2
+ class Config
3
+ attr_accessor :host
4
+ attr_accessor :protocol
5
+
6
+ attr_accessor :username
7
+ attr_accessor :api_key
8
+
9
+ attr_accessor :project
10
+ attr_accessor :category
11
+
12
+ attr_accessor :normal_type
13
+ attr_accessor :regression_type
14
+
15
+ attr_accessor :undefined_status
16
+ attr_accessor :pending_status
17
+ attr_accessor :failed_status
18
+ attr_accessor :passed_status
19
+ attr_accessor :invalid_status
20
+
21
+ def initialize
22
+ @host = "api3.codebasehq.com"
23
+ @protocol = "https"
24
+
25
+ @category = "Cucumber"
26
+
27
+ @normal_type = "Feature"
28
+ @regression_type = "Regression"
29
+
30
+ @undefined_status = "Open (undefined steps)"
31
+ @pending_status = "Open (pending steps)"
32
+ @failed_status = "Open (failing steps)"
33
+ @passed_status = "Completed"
34
+ @invalid_status = "Invalid"
35
+ end
36
+ end
37
+
38
+ def self.config
39
+ @config ||= Config.new
40
+ yield @config if block_given?
41
+ @config
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ module Cukebase
2
+ class Project
3
+ attr_reader :undefined_status
4
+ attr_reader :pending_status
5
+ attr_reader :failed_status
6
+ attr_reader :passed_status
7
+ attr_reader :invalid_status
8
+
9
+ def initialize name
10
+ @name = name
11
+
12
+ @category = ticketing_category_id_for_name Cukebase.config.category
13
+
14
+ @undefined_status = ticketing_status_id_for_name Cukebase.config.undefined_status
15
+ @pending_status = ticketing_status_id_for_name Cukebase.config.pending_status
16
+ @failed_status = ticketing_status_id_for_name Cukebase.config.failed_status
17
+ @passed_status = ticketing_status_id_for_name Cukebase.config.passed_status
18
+ @invalid_status = ticketing_status_id_for_name Cukebase.config.invalid_status
19
+ end
20
+
21
+ def ticketing_categories
22
+ @ticketing_categories ||= Request.get("#{@name}/tickets/categories").parsed_response["ticketing_categories"].map do |hash|
23
+ TicketingCategory.new hash
24
+ end
25
+ end
26
+
27
+ def ticketing_statuses
28
+ @ticketing_statuses ||= Request.get("#{@name}/tickets/statuses").parsed_response["ticketing_statuses"].map do |hash|
29
+ TicketingStatus.new hash
30
+ end
31
+ end
32
+
33
+ def ticket_for_name name
34
+ data = Request.get("#{@name}/tickets", query: { query: "subject:\"#{name}\" category:\"#{Cukebase.config.category}\"" }).parsed_response["tickets"].first
35
+
36
+ if data
37
+ Ticket.new data
38
+ else
39
+ Ticket.new summary: name, category_id: @category, ticket_type: Cukebase.config.normal_type
40
+ end
41
+ end
42
+
43
+ def ticketing_category_id_for_name name
44
+ ticketing_categories.find do |ticketing_category|
45
+ ticketing_category.name == name
46
+ end.try(:id) or raise "Could not find a Codebase ticket category with name \"#{name}\". Please create it first."
47
+ end
48
+
49
+ def ticketing_status_id_for_name name
50
+ ticketing_statuses.find do |ticketing_status|
51
+ ticketing_status.name == name
52
+ end.try(:id) or raise "Could not find a Codebase ticket status with name \"#{name}\". Please create it first."
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,16 @@
1
+ module Cukebase
2
+ class Request
3
+ include HTTParty
4
+
5
+ format :xml
6
+ headers 'Accept' => 'application/xml'
7
+ headers 'Content-type' => 'application/xml'
8
+
9
+ [:get, :post, :put, :delete].each do |method_name|
10
+ define_singleton_method method_name do |url, *args, &block|
11
+ basic_auth Cukebase.config.username, Cukebase.config.api_key
12
+ super "#{Cukebase.config.protocol}://#{Cukebase.config.host}/#{url}", *args, &block
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,82 @@
1
+ module Cukebase
2
+ class Ticket
3
+ include ActiveAttr::Model
4
+
5
+ attribute :ticket_id
6
+ attribute :summary
7
+ attribute :ticket_type
8
+ attribute :reporter_id
9
+ attribute :assignee_id
10
+ attribute :assignee
11
+ attribute :reporter
12
+ attribute :category_id
13
+ attribute :category
14
+ attribute :priority_id
15
+ attribute :priority
16
+ attribute :status_id
17
+ attribute :status
18
+ attribute :milestone_id
19
+ attribute :milestone
20
+ attribute :deadline
21
+ attribute :tags
22
+ attribute :estimated_time
23
+ attribute :project_id
24
+
25
+ attribute :created_at
26
+ attribute :updated_at
27
+
28
+ def self.wrap_setter name
29
+ define_method "#{name}=" do |value|
30
+ @changes[name] = value if @changes && value != send(name)
31
+ super value
32
+ end
33
+ end
34
+
35
+ def initialize *args, &block
36
+ super
37
+
38
+ @changes = {}
39
+ end
40
+
41
+ wrap_setter :status_id
42
+ wrap_setter :priority_id
43
+ wrap_setter :category_id
44
+ wrap_setter :assignee_id
45
+ wrap_setter :milestone_id
46
+ wrap_setter :summary
47
+ wrap_setter :tags
48
+
49
+ def update_ticket content
50
+ data = {}
51
+
52
+ data[:changes] = @changes if @changes.any?
53
+ data[:content] = content if content && self.content != content
54
+
55
+ if data.any?
56
+ Request.post "#{Cukebase.config.project}/tickets/#{ticket_id}/notes", body: data.to_xml(root: "ticket-note", skip_types: true, skip_instruct: true)
57
+ end
58
+ end
59
+
60
+ def create_ticket content
61
+ data = {}
62
+ data[:summary] = summary if summary?
63
+ data[:description] = content if content
64
+ data[:ticket_type] = ticket_type if ticket_type?
65
+ data[:category_id] = category_id if category_id?
66
+ data[:priority_id] = priority_id if priority_id?
67
+ data[:status_id] = status_id if status_id?
68
+ data[:assignee_id] = assignee_id if assignee_id?
69
+ data[:milestone_id] = milestone_id if milestone_id?
70
+
71
+ Request.post "#{Cukebase.config.project}/tickets", body: data.to_xml(root: "ticket", skip_types: true, skip_instruct: true)
72
+ end
73
+
74
+ def save content=nil
75
+ if ticket_id?
76
+ update_ticket content
77
+ else
78
+ create_ticket content
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,8 @@
1
+ module Cukebase
2
+ class TicketingCategory
3
+ include ActiveAttr::Model
4
+
5
+ attribute :id
6
+ attribute :name
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Cukebase
2
+ class TicketingStatus
3
+ include ActiveAttr::Model
4
+
5
+ attribute :id
6
+ attribute :name
7
+ attribute :background_colour
8
+ attribute :order
9
+ attribute :treat_as_closed
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Cukebase
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cukebase
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Emil Loer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: activemodel
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: active_attr
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Cukebase provides integration between Cucumber and the Codebase ticketing
63
+ system
64
+ email:
65
+ - emil@bartune.nl
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - .gitignore
71
+ - Gemfile
72
+ - LICENSE
73
+ - README.md
74
+ - Rakefile
75
+ - cukebase.gemspec
76
+ - lib/cukebase.rb
77
+ - lib/cukebase/config.rb
78
+ - lib/cukebase/project.rb
79
+ - lib/cukebase/request.rb
80
+ - lib/cukebase/ticket.rb
81
+ - lib/cukebase/ticketing_category.rb
82
+ - lib/cukebase/ticketing_status.rb
83
+ - lib/cukebase/version.rb
84
+ homepage: ''
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.24
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Cukebase provides integration between Cucumber and the Codebase ticketing
108
+ system
109
+ test_files: []