gforces-integrity 0.1.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/.gitignore +12 -0
  2. data/CHANGES +42 -0
  3. data/README.md +82 -0
  4. data/Rakefile +57 -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 +138 -0
  14. data/lib/integrity.rb +78 -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 +60 -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/forms.rb +29 -0
  24. data/lib/integrity/helpers/pretty_output.rb +45 -0
  25. data/lib/integrity/helpers/rendering.rb +25 -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 +151 -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 +59 -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 +100 -0
  36. data/lib/integrity/project/notifiers.rb +33 -0
  37. data/lib/integrity/project/push.rb +44 -0
  38. data/lib/integrity/project_builder.rb +56 -0
  39. data/lib/integrity/scm.rb +21 -0
  40. data/lib/integrity/scm/git.rb +89 -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 +95 -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 +18 -0
  53. data/test/acceptance/installer_test.rb +79 -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 +82 -0
  60. data/test/helpers/acceptance.rb +83 -0
  61. data/test/helpers/acceptance/email_notifier.rb +55 -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_test.rb +29 -0
  78. data/test/unit/notifier_test.rb +97 -0
  79. data/test/unit/project_builder_test.rb +118 -0
  80. data/test/unit/project_test.rb +363 -0
  81. data/test/unit/scm_test.rb +54 -0
  82. data/views/_commit_info.haml +24 -0
  83. data/views/build.haml +2 -0
  84. data/views/error.haml +37 -0
  85. data/views/home.haml +21 -0
  86. data/views/integrity.sass +400 -0
  87. data/views/layout.haml +29 -0
  88. data/views/new.haml +50 -0
  89. data/views/not_found.haml +31 -0
  90. data/views/notifier.haml +7 -0
  91. data/views/project.builder +21 -0
  92. data/views/project.haml +30 -0
  93. data/views/unauthorized.haml +38 -0
  94. metadata +325 -0
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
+
3
+ class ErrorPageTest < Test::Unit::AcceptanceTestCase
4
+ story <<-EOS
5
+ As an user,
6
+ I want to be shown a friendly page when something go terribly wrong
7
+ So that I can understand what's going on
8
+ EOS
9
+
10
+ scenario "an error happen while I am browsing my Integrity install" do
11
+ stub(Project).only_public_unless(false) { raise ArgumentError }
12
+ lambda { visit "/" }.should raise_error(Webrat::PageLoadError)
13
+
14
+ response_code.should == 500
15
+ assert_have_tag("h1", :content => "Whatever you do")
16
+ assert_have_tag("strong", :content => "ArgumentError")
17
+ end
18
+ end
@@ -0,0 +1,79 @@
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
+ require "integrity/installer"
3
+
4
+ class InstallerTest < Test::Unit::AcceptanceTestCase
5
+ include FileUtils
6
+
7
+ story <<-EOS
8
+ As an user,
9
+ I want to easily install Integrity
10
+ So that I can spend time actually writing code
11
+ EOS
12
+
13
+ before(:each) do
14
+ rm_rf root if File.directory?(root)
15
+ end
16
+
17
+ def root
18
+ Pathname("/tmp/i-haz-integrity")
19
+ end
20
+
21
+ def install(option="")
22
+ installer = File.dirname(__FILE__) + "/../../bin/integrity"
23
+ IO.popen("#{installer} install #{root} #{option}".strip).read
24
+ end
25
+
26
+ scenario "Installing integrity into a given directory" do
27
+ post_install_message = install
28
+
29
+ assert post_install_message.include?("Awesome")
30
+ assert post_install_message.include?("integrity migrate_db #{root.join("config.yml")}")
31
+
32
+ assert root.join("builds").directory?
33
+ assert root.join("log").directory?
34
+ assert ! root.join("public").directory?
35
+ assert ! root.join("tmp").directory?
36
+
37
+ assert ! root.join("Rakefile").file?
38
+ assert ! root.join("integrity.rb").file?
39
+ assert ! root.join(".gems").file?
40
+
41
+ assert ! root.join("thin.yml").file?
42
+ assert root.join("config.ru").file?
43
+
44
+ config = YAML.load_file(root.join("config.yml"))
45
+
46
+ config[:export_directory].should == root.join("builds").to_s
47
+ config[:database_uri].should == "sqlite3://#{root}/integrity.db"
48
+ config[:log].should == root.join("log/integrity.log").to_s
49
+ end
50
+
51
+ scenario "Installing integrity for Passenger" do
52
+ install("--passenger")
53
+
54
+ assert root.join("public").directory?
55
+ assert root.join("tmp").directory?
56
+ end
57
+
58
+ scenario "Installing Integrity for Thin" do
59
+ install("--thin")
60
+
61
+ config = YAML.load_file(root.join("thin.yml"))
62
+ config["chdir"].should == root.to_s
63
+ config["pid"].should == root.join("thin.pid").to_s
64
+ config["rackup"].should == root.join("config.ru").to_s
65
+ config["log"].should == root.join("log/thin.log").to_s
66
+ end
67
+
68
+ scenario "Installing Integrity for Heroku" do
69
+ message = install("--heroku")
70
+
71
+ assert_equal "integrity --version 0.1.9.0", root.join(".gems").read.chomp
72
+
73
+ assert root.join("Rakefile").file?
74
+ assert root.join("integrity-config.rb").file?
75
+ assert root.join("config.ru").file?
76
+
77
+ assert message.include?("ready to be deployed onto Heroku")
78
+ end
79
+ end
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
+
3
+ class ManualBuildProjectTest < Test::Unit::AcceptanceTestCase
4
+ story <<-EOS
5
+ As an administrator,
6
+ I want to manually build my project
7
+ So that I know if it builds properly
8
+ EOS
9
+
10
+ scenario "clicking on 'Manual Build' triggers a successful build" do
11
+ git_repo(:my_test_project).add_successful_commit
12
+ Project.gen(:my_test_project, :uri => git_repo(:my_test_project).path)
13
+ login_as "admin", "test"
14
+
15
+ visit "/my-test-project"
16
+ click_button "manual build"
17
+
18
+ assert_have_tag("h1", :content =>
19
+ "Built #{git_repo(:my_test_project).short_head} successfully")
20
+ assert_have_tag("blockquote p", :content => "This commit will work")
21
+ assert_have_tag("span.who", :content => "by: John Doe")
22
+ assert_have_tag("span.when", :content => "today")
23
+ assert_have_tag("pre.output", :content => "Running tests...")
24
+ end
25
+
26
+ scenario "clicking on 'Manual Build' triggers a failed build" do
27
+ git_repo(:my_test_project).add_failing_commit
28
+ Project.gen(:my_test_project, :uri => git_repo(:my_test_project).path)
29
+ login_as "admin", "test"
30
+
31
+ visit "/my-test-project"
32
+ click_button "manual build"
33
+
34
+ assert_have_tag("h1",
35
+ :content => "Built #{git_repo(:my_test_project).short_head} and failed")
36
+ assert_have_tag("blockquote p", :content => "This commit will fail")
37
+ end
38
+
39
+ scenario "fixing the build command and then rebuilding result in a successful build" do
40
+ git_repo(:my_test_project).add_successful_commit
41
+ Project.gen(:my_test_project,
42
+ :uri => git_repo(:my_test_project).path,
43
+ :command => "ruby not-found.rb")
44
+
45
+ login_as "admin", "test"
46
+
47
+ visit "/my-test-project"
48
+ click_button "manual build"
49
+ assert_have_tag("h1", :content => "failed")
50
+
51
+ visit "/my-test-project/edit"
52
+ fill_in "Build script", :with => "./test"
53
+ click_button "Update Project"
54
+
55
+ visit "/my-test-project"
56
+ click_button "Build the last commit"
57
+
58
+ assert_have_tag("h1", :content => "success")
59
+ end
60
+
61
+ scenario "Successful builds should not display the 'Rebuild' button" do
62
+ git_repo(:my_test_project).add_successful_commit
63
+ Project.gen(:my_test_project, :uri => git_repo(:my_test_project).path)
64
+ login_as "admin", "test"
65
+
66
+ visit "/my-test-project"
67
+ click_button "manual build"
68
+
69
+ assert_have_no_tag("button", :content => "Rebuild")
70
+ end
71
+
72
+ scenario "Failed builds should display the 'Rebuild' button" do
73
+ git_repo(:my_test_project).add_failing_commit
74
+ Project.gen(:my_test_project, :uri => git_repo(:my_test_project).path)
75
+ login_as "admin", "test"
76
+
77
+ visit "/my-test-project"
78
+ click_button "manual build"
79
+
80
+ assert_have_tag("button", :content => "Rebuild")
81
+ end
82
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
+
3
+ class NotFoundPageTest < Test::Unit::AcceptanceTestCase
4
+ story <<-EOS
5
+ As an visitor,
6
+ I want to be shown a friendly four oh four
7
+ So that I DON'T HAVE TO THINK.
8
+ EOS
9
+
10
+ scenario "chilling on some Integrity instance found via The Holy Hub" do
11
+ project = Project.gen
12
+
13
+ visit "/42"
14
+ assert_equal 404, response_code
15
+
16
+ click_link "list of projects"
17
+ assert_contain(project.name)
18
+
19
+ visit "/42"
20
+
21
+ click_link "the projects list"
22
+ assert_contain(project.name)
23
+
24
+ visit "/42"
25
+
26
+ click_link "back from whence you came"
27
+ assert_contain("Add a new project")
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
+
3
+ class ProjectSyndicationTest < Test::Unit::AcceptanceTestCase
4
+ story <<-EOS
5
+ As a user,
6
+ I want to subscribe to a public project's Atom feed
7
+ So I can know the status of my favorite projects while having my morning coffee
8
+ EOS
9
+
10
+ scenario "a public project's page includes an autodiscovery link tag for the feed" do
11
+ Project.gen(:integrity, :public => true)
12
+ visit "/integrity"
13
+
14
+ assert_have_tag("link[@href='/integrity.atom']")
15
+ end
16
+
17
+ scenario "a public project's feed should include the latest builds" do
18
+ commits = 10.of { Commit.gen(:successful) } + 1.of { Commit.gen(:failed) }
19
+ Project.gen(:integrity, :public => true, :commits => commits)
20
+
21
+ visit "/integrity.atom"
22
+
23
+ # TODO: check for content-type
24
+
25
+ assert_have_tag("feed title", :content => "Build history for Integrity")
26
+ assert_have_tag("feed entry", :count => 11)
27
+ assert_have_tag("feed entry:first title", :content => "success")
28
+ assert_have_tag("feed entry:last title", :content => "failed")
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
+
3
+ class IntegrityStylesheetTest < Test::Unit::AcceptanceTestCase
4
+ story <<-EOS
5
+ As a user,
6
+ I want the stylesheet to work (even with Sinatra 0.9.1)
7
+ So that Integrity isn't a PITA to use
8
+ EOS
9
+
10
+ scenario "browsing on some Integrity install" do
11
+ visit "/"
12
+ assert_have_tag("link[@href='/integrity.css']")
13
+ visit "/integrity.css"
14
+
15
+ assert_contain("body {")
16
+ # TODO: Check that it actually returns a 302
17
+ assert_equal %Q{"2465c472aacf302259dde5146a841e45"},
18
+ webrat_session.send(:response).headers["ETag"]
19
+
20
+ visit "/reset.css"
21
+ assert_contain("Yahoo!")
22
+
23
+ visit "/buttons.css"
24
+ assert_contain("button {")
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + "/../helpers/acceptance"
2
+
3
+ class UnauthorizedPageTest < Test::Unit::AcceptanceTestCase
4
+ story <<-EOS
5
+ As an administrator,
6
+ I want to be shown a friendly login error page
7
+ So that I don't feel guilty of loosing my password
8
+ EOS
9
+
10
+ scenario "an administrator (who's amnesiac) tries to login" do
11
+ project = Project.gen(:public => false)
12
+
13
+ visit "/#{project.name}/edit"
14
+ assert_equal 401, response_code
15
+
16
+ # TODO click_link "try again"
17
+ assert_have_tag("a[@href='/login']", :content => "try again")
18
+ assert_have_tag("a[@href='/']", :content => "go back")
19
+ end
20
+ end
data/test/helpers.rb ADDED
@@ -0,0 +1,82 @@
1
+ $:.unshift File.dirname(__FILE__) + "/../lib", File.dirname(__FILE__)
2
+
3
+ require "rubygems"
4
+
5
+ require "test/unit"
6
+ require "rr"
7
+ require "mocha"
8
+ require "dm-sweatshop"
9
+ require "webrat/sinatra"
10
+
11
+ gem "jeremymcanally-context"
12
+ gem "jeremymcanally-matchy"
13
+ gem "jeremymcanally-pending"
14
+ require "context"
15
+ require "matchy"
16
+ require "pending"
17
+
18
+ require "integrity"
19
+ require "integrity/notifier/test/fixtures"
20
+
21
+ require "helpers/expectations"
22
+
23
+ begin
24
+ require "ruby-debug"
25
+ require "redgreen"
26
+ rescue LoadError
27
+ end
28
+
29
+ module TestHelper
30
+ def ignore_logs!
31
+ Integrity.config[:log] = "/tmp/integrity.test.log"
32
+ end
33
+
34
+ def capture_stdout
35
+ output = StringIO.new
36
+ $stdout = output
37
+ yield
38
+ $stdout = STDOUT
39
+ output
40
+ end
41
+
42
+ def silence_warnings
43
+ $VERBOSE, v = nil, $VERBOSE
44
+ yield
45
+ ensure
46
+ $VERBOSE = v
47
+ end
48
+ end
49
+
50
+ class Test::Unit::TestCase
51
+ class << self
52
+ alias_method :specify, :test
53
+ end
54
+
55
+ include RR::Adapters::TestUnit
56
+ include Integrity
57
+ include TestHelper
58
+
59
+ before(:all) do
60
+ DataMapper.setup(:default, "sqlite3::memory:")
61
+
62
+ require "integrity/migrations"
63
+ end
64
+
65
+ before(:each) do
66
+ [Project, Build, Commit, Notifier].each(&:auto_migrate_down!)
67
+ capture_stdout { Integrity.migrate_db }
68
+
69
+ RR.reset
70
+
71
+ Notifier.available.each { |n|
72
+ Notifier.send(:remove_const, n.to_s.split(":").last.to_sym)
73
+ }
74
+
75
+ Notifier.available.clear
76
+ Integrity.instance_variable_set(:@config, nil)
77
+ end
78
+
79
+ after(:each) do
80
+ capture_stdout { Integrity::Migrations.migrate_down! }
81
+ end
82
+ end
@@ -0,0 +1,83 @@
1
+ require File.dirname(__FILE__) + "/../helpers"
2
+
3
+ gem "foca-storyteller"
4
+ require "storyteller"
5
+
6
+ require "helpers/acceptance/git_helper"
7
+
8
+ module AcceptanceHelper
9
+ include FileUtils
10
+
11
+ def export_directory
12
+ File.dirname(__FILE__) + "/../../exports"
13
+ end
14
+
15
+ def enable_auth!
16
+ Integrity.config[:use_basic_auth] = true
17
+ Integrity.config[:admin_username] = "admin"
18
+ Integrity.config[:admin_password] = "test"
19
+ Integrity.config[:hash_admin_password] = false
20
+ end
21
+
22
+ def login_as(user, password)
23
+ def AcceptanceHelper.logged_in; true; end
24
+ basic_auth user, password
25
+ visit "/login"
26
+ Integrity::App.before { login_required if AcceptanceHelper.logged_in }
27
+ end
28
+
29
+ def log_out
30
+ def AcceptanceHelper.logged_in; false; end
31
+ @_webrat_session = Webrat::SinatraSession.new(self)
32
+ end
33
+
34
+ def disable_auth!
35
+ Integrity.config[:use_basic_auth] = false
36
+ end
37
+
38
+ def set_and_create_export_directory!
39
+ FileUtils.rm_r(export_directory) if File.directory?(export_directory)
40
+ FileUtils.mkdir(export_directory)
41
+ Integrity.config[:export_directory] = export_directory
42
+ end
43
+
44
+ def setup_log!
45
+ log_file = Pathname(File.dirname(__FILE__) + "/../../integrity.log")
46
+ log_file.delete if log_file.exist?
47
+ Integrity.config[:log] = log_file
48
+ end
49
+ end
50
+
51
+ class Test::Unit::AcceptanceTestCase < Test::Unit::TestCase
52
+ include AcceptanceHelper
53
+ include Test::Storyteller
54
+ include GitHelper
55
+ include Webrat::Methods
56
+ include Webrat::Matchers
57
+ include Webrat::HaveTagMatcher
58
+
59
+ # TODO: does this belongs in Webrat::SinatraSession?
60
+ Webrat::Methods.delegate_to_session :response_code
61
+
62
+ def app
63
+ Integrity::App.tap { |app|
64
+ app.set :environment, :test
65
+ app.disable :raise_errors, :run, :reload
66
+ }
67
+ end
68
+
69
+ before(:each) do
70
+ # ensure each scenario is run in a clean sandbox
71
+ Integrity.config[:base_uri] = "http://www.example.com"
72
+ enable_auth!
73
+ setup_log!
74
+ set_and_create_export_directory!
75
+ log_out
76
+ end
77
+
78
+ after(:each) do
79
+ destroy_all_git_repos
80
+ rm_r export_directory if File.directory?(export_directory)
81
+ end
82
+
83
+ end