alphasights-integrity 0.1.9.3

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.
Files changed (93) hide show
  1. data/.gitignore +13 -0
  2. data/CHANGES +48 -0
  3. data/README.md +82 -0
  4. data/Rakefile +58 -0
  5. data/bin/integrity +4 -0
  6. data/config/config.sample.ru +21 -0
  7. data/config/config.sample.yml +41 -0
  8. data/config/heroku/.gems +1 -0
  9. data/config/heroku/Rakefile +6 -0
  10. data/config/heroku/config.ru +7 -0
  11. data/config/heroku/integrity-config.rb +14 -0
  12. data/config/thin.sample.yml +13 -0
  13. data/integrity.gemspec +137 -0
  14. data/lib/integrity.rb +77 -0
  15. data/lib/integrity/app.rb +138 -0
  16. data/lib/integrity/author.rb +39 -0
  17. data/lib/integrity/build.rb +52 -0
  18. data/lib/integrity/commit.rb +61 -0
  19. data/lib/integrity/core_ext/object.rb +6 -0
  20. data/lib/integrity/helpers.rb +16 -0
  21. data/lib/integrity/helpers/authorization.rb +33 -0
  22. data/lib/integrity/helpers/breadcrumbs.rb +20 -0
  23. data/lib/integrity/helpers/gravatar.rb +16 -0
  24. data/lib/integrity/helpers/pretty_output.rb +45 -0
  25. data/lib/integrity/helpers/rendering.rb +49 -0
  26. data/lib/integrity/helpers/resources.rb +19 -0
  27. data/lib/integrity/helpers/urls.rb +59 -0
  28. data/lib/integrity/installer.rb +138 -0
  29. data/lib/integrity/migrations.rb +153 -0
  30. data/lib/integrity/notifier.rb +44 -0
  31. data/lib/integrity/notifier/base.rb +74 -0
  32. data/lib/integrity/notifier/test.rb +52 -0
  33. data/lib/integrity/notifier/test/fixtures.rb +108 -0
  34. data/lib/integrity/notifier/test/hpricot_matcher.rb +38 -0
  35. data/lib/integrity/project.rb +94 -0
  36. data/lib/integrity/project/notifiers.rb +31 -0
  37. data/lib/integrity/project/push.rb +43 -0
  38. data/lib/integrity/project_builder.rb +56 -0
  39. data/lib/integrity/scm.rb +19 -0
  40. data/lib/integrity/scm/git.rb +84 -0
  41. data/lib/integrity/scm/git/uri.rb +57 -0
  42. data/public/buttons.css +82 -0
  43. data/public/reset.css +7 -0
  44. data/public/spinner.gif +0 -0
  45. data/test/acceptance/api_test.rb +97 -0
  46. data/test/acceptance/browse_project_builds_test.rb +65 -0
  47. data/test/acceptance/browse_project_test.rb +99 -0
  48. data/test/acceptance/build_notifications_test.rb +114 -0
  49. data/test/acceptance/create_project_test.rb +97 -0
  50. data/test/acceptance/delete_project_test.rb +53 -0
  51. data/test/acceptance/edit_project_test.rb +117 -0
  52. data/test/acceptance/error_page_test.rb +21 -0
  53. data/test/acceptance/installer_test.rb +81 -0
  54. data/test/acceptance/manual_build_project_test.rb +82 -0
  55. data/test/acceptance/not_found_page_test.rb +29 -0
  56. data/test/acceptance/project_syndication_test.rb +30 -0
  57. data/test/acceptance/stylesheet_test.rb +26 -0
  58. data/test/acceptance/unauthorized_page_test.rb +20 -0
  59. data/test/helpers.rb +75 -0
  60. data/test/helpers/acceptance.rb +82 -0
  61. data/test/helpers/acceptance/email_notifier.rb +52 -0
  62. data/test/helpers/acceptance/git_helper.rb +99 -0
  63. data/test/helpers/acceptance/notifier_helper.rb +47 -0
  64. data/test/helpers/acceptance/textfile_notifier.rb +26 -0
  65. data/test/helpers/expectations.rb +4 -0
  66. data/test/helpers/expectations/be_a.rb +23 -0
  67. data/test/helpers/expectations/change.rb +90 -0
  68. data/test/helpers/expectations/have.rb +105 -0
  69. data/test/helpers/expectations/predicates.rb +37 -0
  70. data/test/helpers/initial_migration_fixture.sql +44 -0
  71. data/test/unit/build_test.rb +72 -0
  72. data/test/unit/commit_test.rb +66 -0
  73. data/test/unit/helpers_test.rb +103 -0
  74. data/test/unit/integrity_test.rb +35 -0
  75. data/test/unit/migrations_test.rb +57 -0
  76. data/test/unit/notifier/base_test.rb +43 -0
  77. data/test/unit/notifier_test.rb +96 -0
  78. data/test/unit/project_builder_test.rb +118 -0
  79. data/test/unit/project_test.rb +344 -0
  80. data/test/unit/scm_test.rb +54 -0
  81. data/views/_commit_info.haml +30 -0
  82. data/views/build.haml +2 -0
  83. data/views/error.haml +37 -0
  84. data/views/home.haml +22 -0
  85. data/views/integrity.sass +424 -0
  86. data/views/layout.haml +29 -0
  87. data/views/new.haml +50 -0
  88. data/views/not_found.haml +31 -0
  89. data/views/notifier.haml +7 -0
  90. data/views/project.builder +21 -0
  91. data/views/project.haml +31 -0
  92. data/views/unauthorized.haml +38 -0
  93. metadata +324 -0
@@ -0,0 +1,52 @@
1
+ module Integrity
2
+ class Notifier
3
+ class Email < Notifier::Base
4
+ attr_reader :to, :from
5
+
6
+ def self.to_haml
7
+ <<-EOF
8
+ %p.normal
9
+ %label{ :for => "email_notifier_to" } Send to
10
+ %input.text#email_notifier_to{ :name => "notifiers[Email][to]", :type => "text", :value => config["to"] }
11
+
12
+ %p.normal
13
+ %label{ :for => "email_notifier_from" } Send from
14
+ %input.text#email_notifier_from{ :name => "notifiers[Email][from]", :type => "text", :value => config["from"] }
15
+
16
+ %h3 SMTP Server Configuration
17
+
18
+ %p.normal
19
+ %label{ :for => "email_notifier_host" } Host : Port
20
+ = succeed " : " do
21
+ %input.text#email_notifier_host{ :name => "notifiers[Email][host]", :value => config["host"], :style => "width: 24.5em;", :type => "text" }
22
+ %input.text#email_notifier_port{ :name => "notifiers[Email][port]", :value => config["port"], :style => "width: 3.5em;", :type => "text" }
23
+
24
+ %p.normal
25
+ %label{ :for => "email_notifier_user" } User
26
+ %input.text#email_notifier_user{ :name => "notifiers[Email][user]", :value => config["user"], :type => "text" }
27
+
28
+ %p.normal
29
+ %label{ :for => "email_notifier_pass" } Password
30
+ %input.text#email_notifier_pass{ :name => "notifiers[Email][pass]", :value => config["pass"], :type => "text" }
31
+
32
+ %p.normal
33
+ %label{ :for => "email_notifier_auth" } Auth type
34
+ %input.text#email_notifier_auth{ :name => "notifiers[Email][auth]", :value => (config["auth"] || "plain"), :type => "text" }
35
+
36
+ %p.normal
37
+ %label{ :for => "email_notifier_domain" } Domain
38
+ %input.text#email_notifier_domain{ :name => "notifiers[Email][domain]", :value => config["domain"], :type => "text" }
39
+ EOF
40
+ end
41
+
42
+ def initialize(build, config={})
43
+ @to = config.delete("to")
44
+ @from = config.delete("from")
45
+ super
46
+ end
47
+
48
+ def deliver!
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,99 @@
1
+ module GitHelper
2
+ @@_git_repositories = Hash.new {|h,k| h[k] = Repo.new(k) }
3
+
4
+ def git_repo(name)
5
+ @@_git_repositories[name]
6
+ end
7
+
8
+ def destroy_all_git_repos
9
+ @@_git_repositories.each {|n,r| r.destroy }
10
+ @@_git_repositories.clear
11
+ end
12
+
13
+ class Repo
14
+ attr_reader :path
15
+
16
+ def initialize(name)
17
+ @name = name
18
+ @path = "/tmp" / @name.to_s
19
+ create
20
+ end
21
+
22
+ def path
23
+ @path / ".git"
24
+ end
25
+
26
+ def create
27
+ destroy
28
+ FileUtils.mkdir_p @path
29
+
30
+ Dir.chdir(@path) do
31
+ system 'git init &>/dev/null'
32
+ system 'git config user.name "John Doe"'
33
+ system 'git config user.email "johndoe@example.org"'
34
+ system 'echo "just a test repo" >> README'
35
+ system 'git add README &>/dev/null'
36
+ system 'git commit -m "First commit" &>/dev/null'
37
+ end
38
+
39
+ add_successful_commit
40
+ end
41
+
42
+ def commits
43
+ Dir.chdir(@path) do
44
+ commits = `git log --pretty=oneline`.collect { |line| line.split(" ").first }
45
+ commits.inject([]) do |commits, sha1|
46
+ format = %Q(---%n:message: >-%n %s%n:timestamp: %ci%n:id: %H%n:author: %n :name: %an%n :email: %ae%n)
47
+ commits << YAML.load(`git show -s --pretty=format:"#{format}" #{sha1}`)
48
+ end
49
+ end
50
+ end
51
+
52
+ def add_commit(message, &action)
53
+ Dir.chdir(@path) do
54
+ yield action
55
+ system %Q(git commit -m "#{message}" &>/dev/null)
56
+ end
57
+ end
58
+
59
+ def add_failing_commit
60
+ add_commit "This commit will fail" do
61
+ system %Q(echo '#{build_script(false)}' > test)
62
+ system %Q(chmod +x test)
63
+ system %Q(git add test &>/dev/null)
64
+ end
65
+ end
66
+
67
+ def add_successful_commit
68
+ add_commit "This commit will work" do
69
+ system %Q(echo '#{build_script(true)}' > test)
70
+ system %Q(chmod +x test)
71
+ system %Q(git add test &>/dev/null)
72
+ end
73
+ end
74
+
75
+ def head
76
+ Dir.chdir(@path) do
77
+ `git log --pretty=format:%H | head -1`.chomp
78
+ end
79
+ end
80
+
81
+ def short_head
82
+ head[0..6]
83
+ end
84
+
85
+ def destroy
86
+ FileUtils.rm_rf @path if File.directory?(@path)
87
+ end
88
+
89
+ protected
90
+
91
+ def build_script(successful=true)
92
+ <<-script
93
+ #!/bin/sh
94
+ echo "Running tests..."
95
+ exit #{successful ? 0 : 1}
96
+ script
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,47 @@
1
+ module NotifierHelper
2
+ def fill_in_email_notifier
3
+ fill_in "notifiers[Email][to]", :with => "quentin@example.com"
4
+ fill_in "notifiers[Email][from]", :with => "ci@example.com"
5
+ fill_in "notifiers[Email][user]", :with => "inspector"
6
+ fill_in "notifiers[Email][pass]", :with => "gadget"
7
+ fill_in "notifiers[Email][auth]", :with => "simple"
8
+ fill_in "notifiers[Email][domain]", :with => "example.com"
9
+ end
10
+
11
+ def fill_in_project_info(name, repo)
12
+ fill_in "Name", :with => name
13
+ fill_in "Git repository", :with => repo
14
+ fill_in "Branch to track", :with => "master"
15
+ fill_in "Build script", :with => "rake"
16
+ check "Public project"
17
+
18
+ fill_in_email_notifier
19
+ end
20
+
21
+ def assert_have_email_notifier
22
+ assert_have_tag "input#email_notifier_to[@value='quentin@example.com']"
23
+ assert_have_tag "input#email_notifier_from[@value='ci@example.com']"
24
+ assert_have_tag "input#email_notifier_user[@value='inspector']"
25
+ assert_have_tag "input#email_notifier_pass[@value='gadget']"
26
+ assert_have_tag "input#email_notifier_auth[@value='simple']"
27
+ assert_have_tag "input#email_notifier_domain[@value='example.com']"
28
+ end
29
+
30
+ def add_project(name, repo)
31
+ visit "/new"
32
+ fill_in_project_info(name, repo)
33
+ click_button "Create Project"
34
+
35
+ assert_have_tag("h1", :content => name)
36
+ click_link 'Edit Project'
37
+ assert_have_email_notifier
38
+ end
39
+
40
+ def edit_project(name)
41
+ visit "/#{name}"
42
+ click_link "Edit Project"
43
+ assert_have_email_notifier
44
+ fill_in :branch, :with => "testing"
45
+ click_button "Update Project"
46
+ end
47
+ end
@@ -0,0 +1,26 @@
1
+ module Integrity
2
+ class Notifier
3
+ class Textfile < Notifier::Base
4
+ def self.to_haml
5
+ <<-haml
6
+ %p.normal
7
+ %label{ :for => "textfile_notifier_file" } File
8
+ %input.text#textfile_notifier_file{ :name => "notifiers[Textfile][file]", :type => "text", :value => config["file"] }
9
+ haml
10
+ end
11
+
12
+ def initialize(build, config={})
13
+ super
14
+ @file = @config["file"]
15
+ end
16
+
17
+ def deliver!
18
+ File.open(@file, "a") do |f|
19
+ f.puts "=== #{short_message} ==="
20
+ f.puts
21
+ f.puts full_message
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
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"
@@ -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