sr-integrity 0.1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +73 -0
- data/Rakefile +91 -0
- data/VERSION.yml +4 -0
- data/bin/integrity +4 -0
- data/config/config.sample.ru +21 -0
- data/config/config.sample.yml +41 -0
- data/config/thin.sample.yml +13 -0
- data/integrity.gemspec +55 -0
- data/lib/integrity/app.rb +137 -0
- data/lib/integrity/author.rb +39 -0
- data/lib/integrity/build.rb +84 -0
- data/lib/integrity/commit.rb +71 -0
- data/lib/integrity/core_ext/object.rb +6 -0
- data/lib/integrity/helpers/authorization.rb +33 -0
- data/lib/integrity/helpers/breadcrumbs.rb +20 -0
- data/lib/integrity/helpers/forms.rb +28 -0
- data/lib/integrity/helpers/pretty_output.rb +45 -0
- data/lib/integrity/helpers/rendering.rb +14 -0
- data/lib/integrity/helpers/resources.rb +13 -0
- data/lib/integrity/helpers/urls.rb +49 -0
- data/lib/integrity/helpers.rb +16 -0
- data/lib/integrity/installer.rb +121 -0
- data/lib/integrity/migrations.rb +140 -0
- data/lib/integrity/notifier/base.rb +65 -0
- data/lib/integrity/notifier.rb +50 -0
- data/lib/integrity/project.rb +142 -0
- data/lib/integrity/project_builder.rb +56 -0
- data/lib/integrity/scm/git/uri.rb +57 -0
- data/lib/integrity/scm/git.rb +84 -0
- data/lib/integrity/scm.rb +19 -0
- data/lib/integrity.rb +80 -0
- data/public/buttons.css +82 -0
- data/public/reset.css +7 -0
- data/public/spinner.gif +0 -0
- data/test/helpers/acceptance/git_helper.rb +99 -0
- data/test/helpers/acceptance/textfile_notifier.rb +26 -0
- data/test/helpers/acceptance.rb +80 -0
- data/test/helpers/expectations/be_a.rb +23 -0
- data/test/helpers/expectations/change.rb +90 -0
- data/test/helpers/expectations/have.rb +105 -0
- data/test/helpers/expectations/have_tag.rb +128 -0
- data/test/helpers/expectations/predicates.rb +37 -0
- data/test/helpers/expectations.rb +5 -0
- data/test/helpers/fixtures.rb +107 -0
- data/test/helpers/initial_migration_fixture.sql +44 -0
- data/test/helpers.rb +70 -0
- data/views/_commit_info.haml +24 -0
- data/views/build.haml +2 -0
- data/views/error.haml +37 -0
- data/views/home.haml +21 -0
- data/views/integrity.sass +400 -0
- data/views/layout.haml +28 -0
- data/views/new.haml +51 -0
- data/views/not_found.haml +31 -0
- data/views/notifier.haml +7 -0
- data/views/project.builder +21 -0
- data/views/project.haml +30 -0
- data/views/unauthorized.haml +38 -0
- metadata +190 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require "webrat/sinatra"
|
2
|
+
require "helpers/acceptance/git_helper"
|
3
|
+
|
4
|
+
module AcceptanceHelper
|
5
|
+
include FileUtils
|
6
|
+
|
7
|
+
def export_directory
|
8
|
+
File.dirname(__FILE__) + "/../../exports"
|
9
|
+
end
|
10
|
+
|
11
|
+
def enable_auth!
|
12
|
+
Integrity.config[:use_basic_auth] = true
|
13
|
+
Integrity.config[:admin_username] = "admin"
|
14
|
+
Integrity.config[:admin_password] = "test"
|
15
|
+
Integrity.config[:hash_admin_password] = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def login_as(user, password)
|
19
|
+
def AcceptanceHelper.logged_in; true; end
|
20
|
+
basic_auth user, password
|
21
|
+
visit "/login"
|
22
|
+
Integrity::App.before { login_required if AcceptanceHelper.logged_in }
|
23
|
+
end
|
24
|
+
|
25
|
+
def log_out
|
26
|
+
def AcceptanceHelper.logged_in; false; end
|
27
|
+
@_webrat_session = Webrat::SinatraSession.new(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def disable_auth!
|
31
|
+
Integrity.config[:use_basic_auth] = false
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_and_create_export_directory!
|
35
|
+
FileUtils.rm_r(export_directory) if File.directory?(export_directory)
|
36
|
+
FileUtils.mkdir(export_directory)
|
37
|
+
Integrity.config[:export_directory] = export_directory
|
38
|
+
end
|
39
|
+
|
40
|
+
def setup_log!
|
41
|
+
log_file = Pathname(File.dirname(__FILE__) + "/../../integrity.log")
|
42
|
+
log_file.delete if log_file.exist?
|
43
|
+
Integrity.config[:log] = log_file
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Test::Unit::AcceptanceTestCase < Test::Unit::TestCase
|
48
|
+
include AcceptanceHelper
|
49
|
+
include Test::Storyteller
|
50
|
+
include GitHelper
|
51
|
+
include Webrat::Methods
|
52
|
+
|
53
|
+
# TODO: does this belongs in Webrat::SinatraSession?
|
54
|
+
Webrat::Methods.delegate_to_session :response_code
|
55
|
+
|
56
|
+
def app
|
57
|
+
Integrity::App.tap { |app|
|
58
|
+
app.set :environment, :test
|
59
|
+
app.disable :raise_errors, :run, :reload
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
before(:all) do
|
64
|
+
Integrity.config[:base_uri] = "http://www.example.com"
|
65
|
+
end
|
66
|
+
|
67
|
+
before(:each) do
|
68
|
+
# ensure each scenario is run in a clean sandbox
|
69
|
+
enable_auth!
|
70
|
+
setup_log!
|
71
|
+
set_and_create_export_directory!
|
72
|
+
log_out
|
73
|
+
end
|
74
|
+
|
75
|
+
after(:each) do
|
76
|
+
destroy_all_git_repos
|
77
|
+
rm_r export_directory if File.directory?(export_directory)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Matchy::Expectations
|
2
|
+
class BeAExpectation < Base
|
3
|
+
def matches?(receiver)
|
4
|
+
@receiver = receiver
|
5
|
+
@receiver.is_a?(@expected)
|
6
|
+
end
|
7
|
+
|
8
|
+
def failure_message
|
9
|
+
"Expected #{@receiver.inspect} to be a #{@expected.inspect}."
|
10
|
+
end
|
11
|
+
|
12
|
+
def negative_failure_message
|
13
|
+
"Expected #{@receiver.inspect} to not be a #{@expected.inspect}."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module TestCaseExtensions
|
18
|
+
def be_a(obj)
|
19
|
+
Matchy::Expectations::BeAExpectation.new(obj, self)
|
20
|
+
end
|
21
|
+
alias :be_an :be_a
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Matchy::Expectations
|
2
|
+
class ChangeExpectation < Base
|
3
|
+
def initialize(receiver=nil, message=nil, test_case=nil, &block)
|
4
|
+
@message = message || "result"
|
5
|
+
@value_proc = block || lambda {
|
6
|
+
receiver.__send__(message)
|
7
|
+
}
|
8
|
+
@test_case = test_case
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches?(event_proc)
|
12
|
+
raise_block_syntax_error if block_given?
|
13
|
+
|
14
|
+
@before = evaluate_value_proc
|
15
|
+
event_proc.call
|
16
|
+
@after = evaluate_value_proc
|
17
|
+
|
18
|
+
return false if @from unless @from == @before
|
19
|
+
return false if @to unless @to == @after
|
20
|
+
return (@before + @amount == @after) if @amount
|
21
|
+
return ((@after - @before) >= @minimum) if @minimum
|
22
|
+
return ((@after - @before) <= @maximum) if @maximum
|
23
|
+
return @before != @after
|
24
|
+
end
|
25
|
+
|
26
|
+
def raise_block_syntax_error
|
27
|
+
raise ArgumentError, "block passed to should or should_not change must use {} instead of do/end"
|
28
|
+
end
|
29
|
+
|
30
|
+
def evaluate_value_proc
|
31
|
+
@value_proc.call
|
32
|
+
end
|
33
|
+
|
34
|
+
def failure_message
|
35
|
+
if @to
|
36
|
+
"#{@message} should have been changed to #{@to.inspect}, but is now #{@after.inspect}"
|
37
|
+
elsif @from
|
38
|
+
"#{@message} should have initially been #{@from.inspect}, but was #{@before.inspect}"
|
39
|
+
elsif @amount
|
40
|
+
"#{@message} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}"
|
41
|
+
elsif @minimum
|
42
|
+
"#{@message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}"
|
43
|
+
elsif @maximum
|
44
|
+
"#{@message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}"
|
45
|
+
else
|
46
|
+
"#{@message} should have changed, but is still #{@before.inspect}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def actual_delta
|
51
|
+
@after - @before
|
52
|
+
end
|
53
|
+
|
54
|
+
def negative_failure_message
|
55
|
+
"#{@message} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def by(amount)
|
59
|
+
@amount = amount
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def by_at_least(minimum)
|
64
|
+
@minimum = minimum
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def by_at_most(maximum)
|
69
|
+
@maximum = maximum
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def to(to)
|
74
|
+
@to = to
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
def from (from)
|
79
|
+
@from = from
|
80
|
+
self
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
module TestCaseExtensions
|
86
|
+
def change(receiver=nil, message=nil, &block)
|
87
|
+
Matchy::Expectations::ChangeExpectation.new(receiver, message, self, &block)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Matchy::Expectations
|
2
|
+
class HaveExpectation < Base
|
3
|
+
def initialize(expected, relativity=:exactly, test_case = nil)
|
4
|
+
@expected = (expected == :no ? 0 : expected)
|
5
|
+
@relativity = relativity
|
6
|
+
@test_case = test_case
|
7
|
+
end
|
8
|
+
|
9
|
+
def relativities
|
10
|
+
@relativities ||= {
|
11
|
+
:exactly => "",
|
12
|
+
:at_least => "at least ",
|
13
|
+
:at_most => "at most "
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches?(collection_owner)
|
18
|
+
if collection_owner.respond_to?(@collection_name)
|
19
|
+
collection = collection_owner.__send__(@collection_name, *@args, &@block)
|
20
|
+
elsif (@plural_collection_name && collection_owner.respond_to?(@plural_collection_name))
|
21
|
+
collection = collection_owner.__send__(@plural_collection_name, *@args, &@block)
|
22
|
+
elsif (collection_owner.respond_to?(:length) || collection_owner.respond_to?(:size))
|
23
|
+
collection = collection_owner
|
24
|
+
else
|
25
|
+
collection_owner.__send__(@collection_name, *@args, &@block)
|
26
|
+
end
|
27
|
+
@given = collection.size if collection.respond_to?(:size)
|
28
|
+
@given = collection.length if collection.respond_to?(:length)
|
29
|
+
raise not_a_collection if @given.nil?
|
30
|
+
return @given >= @expected if @relativity == :at_least
|
31
|
+
return @given <= @expected if @relativity == :at_most
|
32
|
+
return @given == @expected
|
33
|
+
end
|
34
|
+
|
35
|
+
def not_a_collection
|
36
|
+
"expected #{@collection_name} to be a collection but it does not respond to #length or #size"
|
37
|
+
end
|
38
|
+
|
39
|
+
def failure_message
|
40
|
+
"expected #{relative_expectation} #{@collection_name}, got #{@given}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def negative_failure_message
|
44
|
+
if @relativity == :exactly
|
45
|
+
return "expected target not to have #{@expected} #{@collection_name}, got #{@given}"
|
46
|
+
elsif @relativity == :at_most
|
47
|
+
return <<-EOF
|
48
|
+
Isn't life confusing enough?
|
49
|
+
Instead of having to figure out the meaning of this:
|
50
|
+
should_not have_at_most(#{@expected}).#{@collection_name}
|
51
|
+
We recommend that you use this instead:
|
52
|
+
should have_at_least(#{@expected + 1}).#{@collection_name}
|
53
|
+
EOF
|
54
|
+
elsif @relativity == :at_least
|
55
|
+
return <<-EOF
|
56
|
+
Isn't life confusing enough?
|
57
|
+
Instead of having to figure out the meaning of this:
|
58
|
+
should_not have_at_least(#{@expected}).#{@collection_name}
|
59
|
+
We recommend that you use this instead:
|
60
|
+
should have_at_most(#{@expected - 1}).#{@collection_name}
|
61
|
+
EOF
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def description
|
66
|
+
"have #{relative_expectation} #{@collection_name}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def respond_to?(sym)
|
70
|
+
@expected.respond_to?(sym) || super
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def method_missing(sym, *args, &block)
|
76
|
+
@collection_name = sym
|
77
|
+
if inflector = (defined?(ActiveSupport::Inflector) ? ActiveSupport::Inflector : (defined?(Inflector) ? Inflector : nil))
|
78
|
+
@plural_collection_name = inflector.pluralize(sym.to_s)
|
79
|
+
end
|
80
|
+
@args = args
|
81
|
+
@block = block
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
def relative_expectation
|
86
|
+
"#{relativities[@relativity]}#{@expected}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
module TestCaseExtensions
|
92
|
+
def have(n)
|
93
|
+
HaveExpectation.new(n, :exactly, self)
|
94
|
+
end
|
95
|
+
alias :have_exactly :have
|
96
|
+
|
97
|
+
def have_at_least(n)
|
98
|
+
HaveExpectation.new(n, :at_least, self)
|
99
|
+
end
|
100
|
+
|
101
|
+
def have_at_most(n)
|
102
|
+
HaveExpectation.new(n, :at_most, self)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'hpricot'
|
2
|
+
|
3
|
+
# evil hack to duck-type CgiResponse so that nested shoulds can use
|
4
|
+
# +rspec_on_rails+ matchers without remembering to call to_s on it
|
5
|
+
#
|
6
|
+
# e.g.
|
7
|
+
#
|
8
|
+
# response.should have_tag("li") do |ul|
|
9
|
+
# ul.should have_text("List Item") # with hack
|
10
|
+
# ul.to_s.should have_text("List Item") # without hack
|
11
|
+
# end
|
12
|
+
class Hpricot::Elem
|
13
|
+
alias body to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
module Matchy::Expectations
|
17
|
+
class HaveTag < Base
|
18
|
+
def initialize(test_case, selector, inner_text_or_options, options, &block)
|
19
|
+
#@expected = expected
|
20
|
+
@test_case = test_case
|
21
|
+
@selector = selector
|
22
|
+
|
23
|
+
if Hash === inner_text_or_options
|
24
|
+
@inner_text = nil
|
25
|
+
@options = inner_text_or_options
|
26
|
+
else
|
27
|
+
@inner_text = inner_text_or_options
|
28
|
+
@options = options
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def matches?(actual, &block)
|
33
|
+
@actual = actual
|
34
|
+
@doc = hpricot_document(@actual)
|
35
|
+
|
36
|
+
matched_elements = @doc.search(@selector)
|
37
|
+
|
38
|
+
return @options[:count] == 0 if matched_elements.empty?
|
39
|
+
|
40
|
+
matched_elements = filter_on_inner_text(matched_elements) if @inner_text
|
41
|
+
matched_elements = filter_on_nested_expectations(matched_elements, block) if block
|
42
|
+
|
43
|
+
@actual_count = matched_elements.length
|
44
|
+
|
45
|
+
return false unless acceptable_count?(@actual_count)
|
46
|
+
|
47
|
+
!matched_elements.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
def failure_message
|
51
|
+
explanation = @actual_count ? "but found #{@actual_count}" : "but did not"
|
52
|
+
"expected\n#{@doc.to_s}\nto have #{failure_count_phrase} #{failure_selector_phrase}, #{explanation}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def negative_failure_message
|
56
|
+
explanation = @actual_count ? "but found #{@actual_count}" : "but did"
|
57
|
+
"expected\n#{@doc.to_s}\nnot to have #{failure_count_phrase} #{failure_selector_phrase}, #{explanation}"
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def hpricot_document(input)
|
62
|
+
if Hpricot === input
|
63
|
+
input
|
64
|
+
elsif input.respond_to?(:body)
|
65
|
+
Hpricot(input.body)
|
66
|
+
else
|
67
|
+
Hpricot(input.to_s)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def filter_on_inner_text(elements)
|
72
|
+
elements.select do |element|
|
73
|
+
next(element.inner_text =~ @inner_text) if @inner_text.is_a?(Regexp)
|
74
|
+
element.inner_text == @inner_text
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def filter_on_nested_expectations(elements, block)
|
79
|
+
elements.select do |el|
|
80
|
+
begin
|
81
|
+
block.call(el)
|
82
|
+
rescue NoMethodError
|
83
|
+
false
|
84
|
+
else
|
85
|
+
true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def acceptable_count?(actual_count)
|
91
|
+
if @options[:count]
|
92
|
+
return false unless @options[:count] === actual_count
|
93
|
+
end
|
94
|
+
if @options[:minimum]
|
95
|
+
return false unless actual_count >= @options[:minimum]
|
96
|
+
end
|
97
|
+
if @options[:maximum]
|
98
|
+
return false unless actual_count <= @options[:maximum]
|
99
|
+
end
|
100
|
+
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
104
|
+
def failure_count_phrase
|
105
|
+
if @options[:count]
|
106
|
+
"#{@options[:count]} elements matching"
|
107
|
+
elsif @options[:minimum] || @options[:maximum]
|
108
|
+
count_explanations = []
|
109
|
+
count_explanations << "at least #{@options[:minimum]}" if @options[:minimum]
|
110
|
+
count_explanations << "at most #{@options[:maximum]}" if @options[:maximum]
|
111
|
+
"#{count_explanations.join(' and ')} elements matching"
|
112
|
+
else
|
113
|
+
"an element matching"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def failure_selector_phrase
|
118
|
+
phrase = @selector.inspect
|
119
|
+
phrase << (@inner_text ? " with inner text #{@inner_text.inspect}" : "")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
module TestCaseExtensions
|
124
|
+
def have_tag(selector, inner_text_or_options = nil, options = {}, &block)
|
125
|
+
Matchy::Expectations::HaveTag.new(self, selector, inner_text_or_options, options, &block)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Matchy::Expectations
|
2
|
+
class PredicateExpectation < Base
|
3
|
+
def initialize(predicate, *arguments)
|
4
|
+
@test_case = arguments.pop
|
5
|
+
@predicate = predicate
|
6
|
+
@arguments = arguments
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(receiver)
|
10
|
+
@receiver = receiver
|
11
|
+
@receiver.send("#{@predicate}?", *@arguments)
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_message
|
15
|
+
message = "Expected #{@receiver.inspect} to be #{@predicate}"
|
16
|
+
message << " with #{@arguments.map {|e| e.inspect }.join(", ")}" unless @arguments.empty?
|
17
|
+
message
|
18
|
+
end
|
19
|
+
|
20
|
+
def negative_failure_message
|
21
|
+
message = "Expected #{@receiver.inspect} not to be #{@predicate}"
|
22
|
+
message << " with #{@arguments.map {|e| e.inspect }.join(", ")}" unless @arguments.empty?
|
23
|
+
message
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module TestCaseExtensions
|
28
|
+
def method_missing(method, *args, &block)
|
29
|
+
if method.to_s =~ /^be_(.*)/
|
30
|
+
args << self
|
31
|
+
Matchy::Expectations::PredicateExpectation.new($1, *args)
|
32
|
+
else
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/expectations/be_a"
|
2
|
+
require File.dirname(__FILE__) + "/expectations/change"
|
3
|
+
require File.dirname(__FILE__) + "/expectations/have"
|
4
|
+
require File.dirname(__FILE__) + "/expectations/predicates"
|
5
|
+
require File.dirname(__FILE__) + "/expectations/have_tag"
|
@@ -0,0 +1,107 @@
|
|
1
|
+
include DataMapper::Sweatshop::Unique
|
2
|
+
|
3
|
+
class Array
|
4
|
+
def pick
|
5
|
+
self[rand(self.length)]
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_notifier!(name)
|
10
|
+
klass = Class.new(Integrity::Notifier::Base) do
|
11
|
+
def self.to_haml; ""; end
|
12
|
+
def deliver!; nil; end
|
13
|
+
end
|
14
|
+
|
15
|
+
unless Integrity::Notifier.const_defined?(name)
|
16
|
+
Integrity::Notifier.const_set(name, klass)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
Integrity::Project.fixture do
|
22
|
+
{ :name => (name = unique { /\w+/.gen }),
|
23
|
+
:uri => "git://github.com/#{/\w+/.gen}/#{name}.git",
|
24
|
+
:branch => ["master", "test-refactoring", "lh-34"].pick,
|
25
|
+
:command => ["rake", "make", "ant -buildfile test.xml"].pick,
|
26
|
+
:public => [true, false].pick,
|
27
|
+
:building => [true, false].pick }
|
28
|
+
end
|
29
|
+
|
30
|
+
Integrity::Project.fixture(:integrity) do
|
31
|
+
{ :name => "Integrity",
|
32
|
+
:uri => "git://github.com/foca/integrity.git",
|
33
|
+
:branch => "master",
|
34
|
+
:command => "rake",
|
35
|
+
:public => true,
|
36
|
+
:building => false }
|
37
|
+
end
|
38
|
+
|
39
|
+
Integrity::Project.fixture(:my_test_project) do
|
40
|
+
{ :name => "My Test Project",
|
41
|
+
:uri => File.dirname(__FILE__) + "/../../",
|
42
|
+
:branch => "master",
|
43
|
+
:command => "./test",
|
44
|
+
:public => true,
|
45
|
+
:building => false }
|
46
|
+
end
|
47
|
+
|
48
|
+
Integrity::Commit.fixture do
|
49
|
+
project = Integrity::Project.first || Integrity::Project.gen
|
50
|
+
|
51
|
+
{ :identifier => Digest::SHA1.hexdigest(/[:paragraph:]/.gen),
|
52
|
+
:message => /[:sentence:]/.gen,
|
53
|
+
:author => /\w+ \w+ <\w+@example.org>/.gen,
|
54
|
+
:committed_at => unique {|i| Time.mktime(2008, 12, 15, 18, (59 - i) % 60) },
|
55
|
+
:project_id => project.id }
|
56
|
+
end
|
57
|
+
|
58
|
+
Integrity::Commit.fixture(:successful) do
|
59
|
+
Integrity::Commit.generate_attributes.update(:build => Integrity::Build.gen(:successful))
|
60
|
+
end
|
61
|
+
|
62
|
+
Integrity::Commit.fixture(:failed) do
|
63
|
+
Integrity::Commit.generate_attributes.update(:build => Integrity::Build.gen(:failed))
|
64
|
+
end
|
65
|
+
|
66
|
+
Integrity::Commit.fixture(:pending) do
|
67
|
+
Integrity::Commit.generate_attributes.update(:build => Integrity::Build.gen(:pending))
|
68
|
+
end
|
69
|
+
|
70
|
+
Integrity::Build.fixture do
|
71
|
+
commit = Integrity::Commit.first || Integrity::Commit.gen
|
72
|
+
|
73
|
+
{ :output => /[:paragraph:]/.gen,
|
74
|
+
:successful => true,
|
75
|
+
:started_at => unique {|i| Time.mktime(2008, 12, 15, 18, i % 60) },
|
76
|
+
:created_at => unique {|i| Time.mktime(2008, 12, 15, 18, i % 60) },
|
77
|
+
:completed_at => unique {|i| Time.mktime(2008, 12, 15, 18, i % 60) },
|
78
|
+
:commit_id => commit.id }
|
79
|
+
end
|
80
|
+
|
81
|
+
Integrity::Build.fixture(:successful) do
|
82
|
+
Integrity::Build.generate_attributes.update(:successful => true)
|
83
|
+
end
|
84
|
+
|
85
|
+
Integrity::Build.fixture(:failed) do
|
86
|
+
Integrity::Build.generate_attributes.update(:successful => false)
|
87
|
+
end
|
88
|
+
|
89
|
+
Integrity::Build.fixture(:pending) do
|
90
|
+
Integrity::Build.generate_attributes.update(:successful => nil, :started_at => nil, :completed_at => nil)
|
91
|
+
end
|
92
|
+
|
93
|
+
Integrity::Notifier.fixture(:irc) do
|
94
|
+
create_notifier! "IRC"
|
95
|
+
|
96
|
+
{ :project => Integrity::Project.generate,
|
97
|
+
:name => "IRC",
|
98
|
+
:config => { :uri => "irc://irc.freenode.net/integrity" }}
|
99
|
+
end
|
100
|
+
|
101
|
+
Integrity::Notifier.fixture(:twitter) do
|
102
|
+
create_notifier! "Twitter"
|
103
|
+
|
104
|
+
{ :project => Integrity::Project.generate,
|
105
|
+
:name => "Twitter",
|
106
|
+
:config => { :email => "foo@example.org", :pass => "secret" }}
|
107
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
CREATE TABLE "integrity_builds" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "output" TEXT NOT NULL DEFAULT '', "successful" BOOLEAN NOT NULL DEFAULT 'f', "commit_identifier" VARCHAR(50) NOT NULL, "commit_metadata" TEXT NOT NULL, "created_at" DATETIME, "updated_at" DATETIME, "project_id" INTEGER);
|
2
|
+
INSERT INTO "integrity_builds" VALUES(1,'rake aborted!
|
3
|
+
Don''t know how to build task ''default''
|
4
|
+
/home/simon/.gems/gems/rake-0.8.3/lib/rake.rb:1706:in `[]''
|
5
|
+
(See full trace by running task with --trace)
|
6
|
+
(in /home/simon/bar/builds/sr-shout-bot-master)
|
7
|
+
','f','348e9e27fa72645518fc539b77f1c37fcc20ab11','---
|
8
|
+
:message: had to allow for registration time
|
9
|
+
:date: 2009-01-04 06:19:30 +0800
|
10
|
+
:author: syd <syd@teh.magicha.us>
|
11
|
+
','2009-02-17T19:48:31+01:00','2009-02-17T19:48:31+01:00',1);
|
12
|
+
INSERT INTO "integrity_builds" VALUES(2,'....*...........
|
13
|
+
|
14
|
+
Pending:
|
15
|
+
ShoutBot When using Shouter.shout passes given block to join (TODO)
|
16
|
+
Called from shout-bot.rb:113
|
17
|
+
|
18
|
+
Finished in 10.222458 seconds
|
19
|
+
|
20
|
+
16 examples, 0 failures, 1 pending
|
21
|
+
','t','348e9e27fa72645518fc539b77f1c37fcc20ab11','---
|
22
|
+
:message: had to allow for registration time
|
23
|
+
:date: 2009-01-04 06:19:30 +0800
|
24
|
+
:author: syd <syd@teh.magicha.us>
|
25
|
+
','2009-02-17T19:49:05+01:00','2009-02-17T19:49:05+01:00',1);
|
26
|
+
INSERT INTO "integrity_builds" VALUES(3,'(in /home/simon/bar/builds/sinatra-sinatra-master)
|
27
|
+
Loaded suite /home/simon/.gems/gems/rake-0.8.3/lib/rake/rake_test_loader
|
28
|
+
Started
|
29
|
+
.......................................................................................................................................................................................................................................
|
30
|
+
Finished in 1.097704 seconds.
|
31
|
+
|
32
|
+
231 tests, 437 assertions, 0 failures, 0 errors
|
33
|
+
','t','a2f5803ec642c43ece86ad96676c45f44fe3746e','---
|
34
|
+
:message: Allow dot in named param capture [#153]
|
35
|
+
:date: 2009-02-17 09:32:58 -0800
|
36
|
+
:author: Ryan Tomayko <rtomayko@gmail.com>
|
37
|
+
','2009-02-17T19:50:11+01:00','2009-02-17T19:50:11+01:00',2);
|
38
|
+
DELETE FROM sqlite_sequence;
|
39
|
+
INSERT INTO "sqlite_sequence" VALUES('integrity_projects',2);
|
40
|
+
INSERT INTO "sqlite_sequence" VALUES('integrity_builds',3);
|
41
|
+
CREATE TABLE "integrity_notifiers" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "name" VARCHAR(50) NOT NULL, "config" TEXT NOT NULL, "project_id" INTEGER);
|
42
|
+
CREATE TABLE "integrity_projects" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "name" VARCHAR(50) NOT NULL, "permalink" VARCHAR(50), "uri" VARCHAR(255) NOT NULL, "branch" VARCHAR(50) NOT NULL DEFAULT 'master', "command" VARCHAR(255) NOT NULL DEFAULT 'rake', "public" BOOLEAN DEFAULT 't', "building" BOOLEAN DEFAULT 'f', "created_at" DATETIME, "updated_at" DATETIME);
|
43
|
+
INSERT INTO "integrity_projects" VALUES(1,'Shout Bot','shout-bot','git://github.com/sr/shout-bot.git','master','ruby shout-bot.rb','t','f','2009-02-17T19:48:23+01:00','2009-02-17T19:49:05+01:00');
|
44
|
+
INSERT INTO "integrity_projects" VALUES(2,'Sinatra','sinatra','git://github.com/sinatra/sinatra.git','master','rake compat test','t','f','2009-02-17T19:49:48+01:00','2009-02-17T19:50:22+01:00');
|
data/test/helpers.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib", File.dirname(__FILE__),
|
2
|
+
File.dirname(__FILE__) + "/../vendor/webrat/lib"
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "test/unit"
|
6
|
+
require "redgreen"
|
7
|
+
require "context"
|
8
|
+
require "storyteller"
|
9
|
+
require "pending"
|
10
|
+
require "matchy"
|
11
|
+
require "rr"
|
12
|
+
require "mocha"
|
13
|
+
require "ruby-debug"
|
14
|
+
require "test/zentest_assertions"
|
15
|
+
require "dm-sweatshop"
|
16
|
+
rescue LoadError
|
17
|
+
puts "You're missing some gems required to run the tests."
|
18
|
+
puts "Please run `rake test:install_dependencies`"
|
19
|
+
puts "You'll probably need to run that command as root or with sudo."
|
20
|
+
puts
|
21
|
+
puts "Thanks :)"
|
22
|
+
puts
|
23
|
+
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
|
27
|
+
require "integrity"
|
28
|
+
require "helpers/expectations"
|
29
|
+
require "helpers/fixtures"
|
30
|
+
|
31
|
+
module TestHelper
|
32
|
+
def ignore_logs!
|
33
|
+
Integrity.config[:log] = "/tmp/integrity.test.log"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Test::Unit::TestCase
|
38
|
+
class << self
|
39
|
+
alias_method :specify, :test
|
40
|
+
end
|
41
|
+
|
42
|
+
include RR::Adapters::TestUnit
|
43
|
+
include Integrity
|
44
|
+
include TestHelper
|
45
|
+
|
46
|
+
before(:all) do
|
47
|
+
DataMapper.setup(:default, "sqlite3::memory:")
|
48
|
+
end
|
49
|
+
|
50
|
+
before(:each) do
|
51
|
+
RR.reset
|
52
|
+
DataMapper.auto_migrate!
|
53
|
+
Integrity.instance_variable_set(:@config, nil)
|
54
|
+
|
55
|
+
repository(:default) do
|
56
|
+
transaction = DataMapper::Transaction.new(repository)
|
57
|
+
transaction.begin
|
58
|
+
repository.adapter.push_transaction(transaction)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
after(:each) do
|
63
|
+
repository(:default) do
|
64
|
+
while repository.adapter.current_transaction
|
65
|
+
repository.adapter.current_transaction.rollback
|
66
|
+
repository.adapter.pop_transaction
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|