integrity 0.1.9.0 → 0.1.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ mailfactory --version '>= 1.4.0'
2
+ tlsmail
3
+ foca-sinatra-ditties --version 0.0.3 --source http://gems.github.com
4
+ integrity --version 0.1.9.0
@@ -0,0 +1,6 @@
1
+ desc "Create the Integrity database"
2
+ task "db:migrate" do
3
+ require File.dirname(__FILE__) + "/integrity-config"
4
+
5
+ DataMapper.auto_migrate!
6
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + "/integrity-config"
3
+
4
+ Integrity::App.set(:environment, ENV["RACK_ENV"] || :production)
5
+ Integrity::App.disable(:run, :reload)
6
+ run Integrity::App
7
+
@@ -0,0 +1,11 @@
1
+ require "rubygems"
2
+ gem "integrity"
3
+ require "integrity"
4
+
5
+ Integrity.config = {
6
+ :database_uri => ENV["DATABASE_URL"],
7
+ :export_directory => File.dirname(__FILE__) + "/tmp",
8
+ :log => File.dirname(__FILE__) + "/log/integrity.log"
9
+ }
10
+
11
+ Integrity.new
data/integrity.gemspec ADDED
@@ -0,0 +1,123 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "integrity"
3
+ s.version = "0.1.9.1"
4
+ s.date = "2009-03-16"
5
+
6
+ s.description = "Your Friendly Continuous Integration server. Easy, fun and painless!"
7
+ s.summary = "The easy and fun Continuous Integration server"
8
+ s.homepage = "http://integrityapp.com"
9
+
10
+ s.authors = ["Nicolás Sanguinetti", "Simon Rozet"]
11
+ s.email = "info@integrityapp.com"
12
+
13
+ s.require_paths = ["lib"]
14
+ s.executables = ["integrity"]
15
+
16
+ s.post_install_message = "Run `integrity help` for information on how to setup Integrity."
17
+ s.rubyforge_project = "integrity"
18
+ s.has_rdoc = false
19
+ s.rubygems_version = "1.3.1"
20
+
21
+ s.add_dependency "sinatra", [">= 0.9.1.1"]
22
+ s.add_dependency "haml", [">= 2.0.0"]
23
+ s.add_dependency "data_mapper", [">= 0.9.10"]
24
+ s.add_dependency "uuidtools" # required by dm-types
25
+ s.add_dependency "bcrypt-ruby" # required by dm-types
26
+ s.add_dependency "json"
27
+ s.add_dependency "thor"
28
+
29
+ s.files = %w[
30
+ README.markdown
31
+ Rakefile
32
+ bin/integrity
33
+ config/config.sample.ru
34
+ config/config.sample.yml
35
+ config/heroku/.gems
36
+ config/heroku/Rakefile
37
+ config/heroku/config.ru
38
+ config/heroku/integrity-config.rb
39
+ config/thin.sample.yml
40
+ integrity.gemspec
41
+ lib/integrity.rb
42
+ lib/integrity/app.rb
43
+ lib/integrity/author.rb
44
+ lib/integrity/build.rb
45
+ lib/integrity/commit.rb
46
+ lib/integrity/core_ext/object.rb
47
+ lib/integrity/helpers.rb
48
+ lib/integrity/helpers/authorization.rb
49
+ lib/integrity/helpers/breadcrumbs.rb
50
+ lib/integrity/helpers/forms.rb
51
+ lib/integrity/helpers/pretty_output.rb
52
+ lib/integrity/helpers/rendering.rb
53
+ lib/integrity/helpers/resources.rb
54
+ lib/integrity/helpers/urls.rb
55
+ lib/integrity/installer.rb
56
+ lib/integrity/migrations.rb
57
+ lib/integrity/notifier.rb
58
+ lib/integrity/notifier/base.rb
59
+ lib/integrity/notifier/test.rb
60
+ lib/integrity/notifier/test/fixtures.rb
61
+ lib/integrity/notifier/test/hpricot_matcher.rb
62
+ lib/integrity/project.rb
63
+ lib/integrity/project_builder.rb
64
+ lib/integrity/scm.rb
65
+ lib/integrity/scm/git.rb
66
+ lib/integrity/scm/git/uri.rb
67
+ public/buttons.css
68
+ public/reset.css
69
+ public/spinner.gif
70
+ test/acceptance/api_test.rb
71
+ test/acceptance/browse_project_builds_test.rb
72
+ test/acceptance/browse_project_test.rb
73
+ test/acceptance/build_notifications_test.rb
74
+ test/acceptance/create_project_test.rb
75
+ test/acceptance/delete_project_test.rb
76
+ test/acceptance/edit_project_test.rb
77
+ test/acceptance/error_page_test.rb
78
+ test/acceptance/helpers.rb
79
+ test/acceptance/installer_test.rb
80
+ test/acceptance/manual_build_project_test.rb
81
+ test/acceptance/notifier_test.rb
82
+ test/acceptance/project_syndication_test.rb
83
+ test/acceptance/stylesheet_test.rb
84
+ test/helpers.rb
85
+ test/helpers/acceptance.rb
86
+ test/helpers/acceptance/email_notifier.rb
87
+ test/helpers/acceptance/git_helper.rb
88
+ test/helpers/acceptance/textfile_notifier.rb
89
+ test/helpers/expectations.rb
90
+ test/helpers/expectations/be_a.rb
91
+ test/helpers/expectations/change.rb
92
+ test/helpers/expectations/have.rb
93
+ test/helpers/expectations/predicates.rb
94
+ test/helpers/fixtures.rb
95
+ test/helpers/initial_migration_fixture.sql
96
+ test/unit/build_test.rb
97
+ test/unit/commit_test.rb
98
+ test/unit/helpers_test.rb
99
+ test/unit/integrity_test.rb
100
+ test/unit/migrations_test.rb
101
+ test/unit/notifier/test_test.rb
102
+ test/unit/notifier_test.rb
103
+ test/unit/project_builder_test.rb
104
+ test/unit/project_test.rb
105
+ test/unit/scm_test.rb
106
+ vendor/sinatra-ditties/README.rdoc
107
+ vendor/sinatra-ditties/lib/sinatra/ditties.rb
108
+ vendor/sinatra-ditties/lib/sinatra/ditties/authorization.rb
109
+ vendor/sinatra-ditties/lib/sinatra/ditties/mailer.rb
110
+ views/_commit_info.haml
111
+ views/build.haml
112
+ views/error.haml
113
+ views/home.haml
114
+ views/integrity.sass
115
+ views/layout.haml
116
+ views/new.haml
117
+ views/not_found.haml
118
+ views/notifier.haml
119
+ views/project.builder
120
+ views/project.haml
121
+ views/unauthorized.haml
122
+ ]
123
+ end
data/lib/integrity.rb CHANGED
@@ -1,6 +1,8 @@
1
- $:.unshift File.expand_path(File.dirname(__FILE__))
1
+ $:.unshift File.expand_path(File.dirname(__FILE__)),
2
+ File.expand_path(File.dirname(__FILE__) + "/../vendor/sinatra-ditties/lib")
2
3
 
3
4
  require "json"
5
+ require "haml"
4
6
  require "dm-core"
5
7
  require "dm-validations"
6
8
  require "dm-types"
@@ -34,22 +36,18 @@ module Integrity
34
36
  DataMapper.setup(:default, config[:database_uri])
35
37
  end
36
38
 
37
- def self.root
38
- Pathname.new(File.dirname(__FILE__)).join("..").expand_path
39
- end
40
-
41
39
  def self.default_configuration
42
40
  @defaults ||= { :database_uri => "sqlite3::memory:",
43
- :export_directory => root / "exports",
41
+ :export_directory => "/tmp/exports",
44
42
  :log => STDOUT,
45
43
  :base_uri => "http://localhost:8910",
46
44
  :use_basic_auth => false,
47
45
  :build_all_commits => true,
48
- :log_debug_info => false }.dup
46
+ :log_debug_info => false }
49
47
  end
50
48
 
51
49
  def self.config
52
- @config ||= default_configuration
50
+ @config ||= default_configuration.dup
53
51
  end
54
52
 
55
53
  def self.config=(options)
@@ -65,13 +63,8 @@ module Integrity
65
63
  logger.formatter = LogFormatter.new
66
64
  end
67
65
  end
66
+ private_class_method :logger
68
67
 
69
- def self.version
70
- YAML.load_file(File.dirname(__FILE__) + "/../VERSION.yml").
71
- values.join(".")
72
- end
73
-
74
- private
75
68
  class LogFormatter < Logger::Formatter
76
69
  def call(severity, time, progname, msg)
77
70
  time.strftime("[%H:%M:%S] ") + msg2str(msg) + "\n"
@@ -1,5 +1,5 @@
1
- require File.dirname(__FILE__) + "/../integrity"
2
1
  require "thor"
2
+ require File.dirname(__FILE__) + "/../integrity"
3
3
 
4
4
  module Integrity
5
5
  class Installer < Thor
@@ -7,16 +7,30 @@ module Integrity
7
7
 
8
8
  desc "install [PATH]",
9
9
  "Copy template files to PATH for desired deployement strategy
10
- (either Thin or Passenger). Next, go there and edit them."
11
- method_options :passenger => false, :thin => false
10
+ (either Thin, Passenger or Heroku). Next, go there and edit them."
11
+ method_options :passenger => :boolean,
12
+ :thin => :boolean,
13
+ :heroku => :boolean
12
14
  def install(path)
13
15
  @root = Pathname(path).expand_path
14
16
 
15
- create_dir_structure
16
- copy_template_files
17
- edit_template_files
18
- migrate_db(root.join("config.yml"))
19
- after_setup_message
17
+ if options[:heroku]
18
+ cp_r Pathname(__FILE__).join("../../../config/heroku"), root
19
+ puts <<EOF
20
+ Your Integrity install is ready to be deployed onto Heroku. Next steps:
21
+
22
+ 1. git init && git add . && git commit -am "Initial import"
23
+ 2. heroku create
24
+ 3. git push heroku master
25
+ 4. heroku rake db:migrate
26
+ EOF
27
+ else
28
+ create_dir_structure
29
+ copy_template_files
30
+ edit_template_files
31
+ migrate_db(root.join("config.yml"))
32
+ after_setup_message
33
+ end
20
34
  end
21
35
 
22
36
  desc "migrate_db [CONFIG]",
@@ -55,6 +69,7 @@ module Integrity
55
69
 
56
70
  def create_dir_structure
57
71
  mkdir_p root
72
+
58
73
  mkdir_p root / "builds"
59
74
  mkdir_p root / "log"
60
75
 
@@ -65,9 +80,9 @@ module Integrity
65
80
  end
66
81
 
67
82
  def copy_template_files
68
- copy "config/config.sample.ru"
69
- copy "config/config.sample.yml"
70
- copy "config/thin.sample.yml" if options[:thin]
83
+ copy "config.sample.ru"
84
+ copy "config.sample.yml"
85
+ copy "thin.sample.yml" if options[:thin]
71
86
  end
72
87
 
73
88
  def edit_template_files
@@ -90,26 +105,27 @@ module Integrity
90
105
  end
91
106
 
92
107
  def after_setup_message
93
- puts
94
- puts %Q(Awesome! Integrity was installed successfully!)
95
- puts
96
- puts %Q(If you want to enable notifiers, install the gems and then require them)
97
- puts %Q(in #{root}/config.ru)
98
- puts
99
- puts %Q(For example:)
100
- puts
101
- puts %Q( sudo gem install -s http://gems.github.com foca-integrity-email)
102
- puts
103
- puts %Q(And then in #{root}/config.ru add:)
104
- puts
105
- puts %Q( require "notifier/email")
106
- puts
107
- puts %Q(Don't forget to tweak #{root / "config.yml"} to your needs.)
108
+ puts <<EOF
109
+ Awesome! Integrity was installed successfully!
110
+
111
+ If you want to enable notifiers, install the gems and then require them
112
+ in #{root}/config.ru
113
+
114
+ For example:
115
+
116
+ sudo gem install -s http://gems.github.com foca-integrity-email)
117
+
118
+ And then in #{root}/config.ru add:
119
+
120
+ require "notifier/email"
121
+
122
+ Don't forget to tweak #{root / "config.yml"} to your needs.
123
+ EOF
108
124
  end
109
125
 
110
- def copy(path)
111
- cp(File.dirname(__FILE__) + "/../../#{path}",
112
- root.join(File.basename(path).gsub(/\.sample/, "")))
126
+ def copy(source)
127
+ cp(Pathname(__FILE__).dirname.join("../../config", source),
128
+ root.join(File.basename(source).gsub(/\.sample/, "")))
113
129
  end
114
130
  end
115
131
  end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + "/../../integrity"
2
+
3
+ require "integrity/notifier/test/hpricot_matcher"
4
+ require "integrity/notifier/test/fixtures"
5
+
6
+ module Integrity
7
+ class Notifier
8
+ module Test
9
+ def setup_database
10
+ DataMapper.setup(:default, "sqlite3::memory:")
11
+ DataMapper.auto_migrate!
12
+ end
13
+
14
+ def notifier_class
15
+ Integrity::Notifier.const_get(notifier)
16
+ end
17
+
18
+ def notification(commit)
19
+ notifier_class.new(commit).full_message
20
+ end
21
+
22
+ def notification_successful
23
+ notification(Integrity::Commit.gen(:successful))
24
+ end
25
+
26
+ def notification_failed
27
+ notification(Integrity::Commit.gen(:failed))
28
+ end
29
+
30
+ def assert_form_have_option(option, value=nil)
31
+ selector = "input##{notifier.downcase}_notifier_#{option}"
32
+ selector << "[@name='notifiers[#{notifier}][#{option}]']"
33
+ selector << "[@value='#{value}']" if value
34
+
35
+ assert_form_have_tag(selector, option => value)
36
+ end
37
+
38
+ def assert_form_have_options(*options)
39
+ options.each { |option| assert_form_have_option(option) }
40
+ end
41
+
42
+ def assert_form_have_tag(selector, options={})
43
+ content = options.delete(:content)
44
+ assert_have_tag(form(options), selector, content)
45
+ end
46
+
47
+ def assert_have_tag(html, selector, content=nil)
48
+ matcher = HpricotMatcher.new(html)
49
+ assert_equal content, matcher.tag(selector) if content
50
+ assert matcher.tag(selector)
51
+ end
52
+
53
+ def form(config={})
54
+ Haml::Engine.new(notifier_class.to_haml).
55
+ render(OpenStruct.new(:config => config))
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,108 @@
1
+ require "dm-sweatshop"
2
+
3
+ include DataMapper::Sweatshop::Unique
4
+
5
+ class Array
6
+ def pick
7
+ self[rand(self.length)]
8
+ end
9
+ end
10
+
11
+ def create_notifier!(name)
12
+ klass = Class.new(Integrity::Notifier::Base) do
13
+ def self.to_haml; ""; end
14
+ def deliver!; nil; end
15
+ end
16
+
17
+ unless Integrity::Notifier.const_defined?(name)
18
+ Integrity::Notifier.const_set(name, klass)
19
+ end
20
+ end
21
+
22
+ Integrity::Project.fixture do
23
+ { :name => (name = unique { /\w+/.gen }),
24
+ :uri => "git://github.com/#{/\w+/.gen}/#{name}.git",
25
+ :branch => ["master", "test-refactoring", "lh-34"].pick,
26
+ :command => ["rake", "make", "ant -buildfile test.xml"].pick,
27
+ :public => [true, false].pick,
28
+ :building => [true, false].pick }
29
+ end
30
+
31
+ Integrity::Project.fixture(:integrity) do
32
+ { :name => "Integrity",
33
+ :uri => "git://github.com/foca/integrity.git",
34
+ :branch => "master",
35
+ :command => "rake",
36
+ :public => true,
37
+ :building => false }
38
+ end
39
+
40
+ Integrity::Project.fixture(:my_test_project) do
41
+ { :name => "My Test Project",
42
+ :uri => File.dirname(__FILE__) + "/../../",
43
+ :branch => "master",
44
+ :command => "./test",
45
+ :public => true,
46
+ :building => false }
47
+ end
48
+
49
+ Integrity::Commit.fixture do
50
+ project = Integrity::Project.first || Integrity::Project.gen
51
+
52
+ { :identifier => Digest::SHA1.hexdigest(/[:paragraph:]/.gen),
53
+ :message => /[:sentence:]/.gen,
54
+ :author => /\w+ \w+ <\w+@example.org>/.gen,
55
+ :committed_at => unique {|i| Time.mktime(2008, 12, 15, 18, (59 - i) % 60) },
56
+ :project_id => project.id }
57
+ end
58
+
59
+ Integrity::Commit.fixture(:successful) do
60
+ Integrity::Commit.generate_attributes.update(:build => Integrity::Build.gen(:successful))
61
+ end
62
+
63
+ Integrity::Commit.fixture(:failed) do
64
+ Integrity::Commit.generate_attributes.update(:build => Integrity::Build.gen(:failed))
65
+ end
66
+
67
+ Integrity::Commit.fixture(:pending) do
68
+ Integrity::Commit.generate_attributes.update(:build => Integrity::Build.gen(:pending))
69
+ end
70
+
71
+ Integrity::Build.fixture do
72
+ commit = Integrity::Commit.first || Integrity::Commit.gen
73
+
74
+ { :output => /[:paragraph:]/.gen,
75
+ :successful => true,
76
+ :started_at => unique {|i| Time.mktime(2008, 12, 15, 18, i % 60) },
77
+ :created_at => unique {|i| Time.mktime(2008, 12, 15, 18, i % 60) },
78
+ :completed_at => unique {|i| Time.mktime(2008, 12, 15, 18, i % 60) },
79
+ :commit_id => commit.id }
80
+ end
81
+
82
+ Integrity::Build.fixture(:successful) do
83
+ Integrity::Build.generate_attributes.update(:successful => true)
84
+ end
85
+
86
+ Integrity::Build.fixture(:failed) do
87
+ Integrity::Build.generate_attributes.update(:successful => false)
88
+ end
89
+
90
+ Integrity::Build.fixture(:pending) do
91
+ Integrity::Build.generate_attributes.update(:successful => nil, :started_at => nil, :completed_at => nil)
92
+ end
93
+
94
+ Integrity::Notifier.fixture(:irc) do
95
+ create_notifier! "IRC"
96
+
97
+ { :project => Integrity::Project.generate,
98
+ :name => "IRC",
99
+ :config => { :uri => "irc://irc.freenode.net/integrity" }}
100
+ end
101
+
102
+ Integrity::Notifier.fixture(:twitter) do
103
+ create_notifier! "Twitter"
104
+
105
+ { :project => Integrity::Project.generate,
106
+ :name => "Twitter",
107
+ :config => { :email => "foo@example.org", :pass => "secret" }}
108
+ end
@@ -0,0 +1,38 @@
1
+ require "hpricot"
2
+
3
+ module Integrity
4
+ class Notifier
5
+ module Test
6
+ # Thanks Harry! http://gist.github.com/39960
7
+ class HpricotMatcher
8
+ def initialize(html)
9
+ @doc = Hpricot(html)
10
+ end
11
+
12
+ # elements('h1') returns a Hpricot::Elements object with all h1-tags.
13
+ def elements(selector)
14
+ @doc.search(selector)
15
+ end
16
+
17
+ # element('h1') returns Hpricot::Elem with first h1-tag, or nil if
18
+ # none exist.
19
+ def element(selector)
20
+ @doc.at(selector)
21
+ end
22
+
23
+ # tags('h1') returns the inner HTML of all matched elements mathed.
24
+ def tags(selector)
25
+ e = elements(selector)
26
+ e.map {|x| x.inner_html}
27
+ end
28
+
29
+ # tag('h1') returns the inner HTML of the first mached element, or
30
+ # nil if none matched.
31
+ def tag(selector)
32
+ e = element(selector)
33
+ e && e.inner_html
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + "/helpers"
2
- require File.dirname(__FILE__) + "/../helpers/acceptance/textfile_notifier"
2
+ require "helpers/acceptance/textfile_notifier"
3
3
 
4
4
  class BuildNotificationsTest < Test::Unit::AcceptanceTestCase
5
5
  story <<-EOS
@@ -11,7 +11,7 @@ class BuildNotificationsTest < Test::Unit::AcceptanceTestCase
11
11
  before(:each) do
12
12
  # This is needed before any available notifier is unset
13
13
  # in the global #before
14
- load File.dirname(__FILE__) + "/../helpers/acceptance/textfile_notifier.rb"
14
+ load "helpers/acceptance/textfile_notifier.rb"
15
15
  end
16
16
 
17
17
  scenario "an admin sets up a notifier for a project that didn't have any" do
@@ -18,11 +18,9 @@ class InstallerTest < Test::Unit::AcceptanceTestCase
18
18
  Pathname("/tmp/i-haz-integrity")
19
19
  end
20
20
 
21
- def install(options={})
22
- installer = Installer.new
23
- installer.options = { :passenger => false, :thin => false }.merge!(options)
24
- stdout, _ = util_capture { installer.install(root.to_s) }
25
- stdout
21
+ def install(option="")
22
+ installer = File.dirname(__FILE__) + "/../../bin/integrity"
23
+ IO.popen("#{installer} install #{root} #{option}".strip).read
26
24
  end
27
25
 
28
26
  scenario "Installing integrity into a given directory" do
@@ -33,6 +31,10 @@ class InstallerTest < Test::Unit::AcceptanceTestCase
33
31
  assert ! root.join("public").directory?
34
32
  assert ! root.join("tmp").directory?
35
33
 
34
+ assert ! root.join("Rakefile").file?
35
+ assert ! root.join("integrity.rb").file?
36
+ assert ! root.join(".gems").file?
37
+
36
38
  assert ! root.join("thin.yml").file?
37
39
  assert root.join("config.ru").file?
38
40
 
@@ -44,14 +46,14 @@ class InstallerTest < Test::Unit::AcceptanceTestCase
44
46
  end
45
47
 
46
48
  scenario "Installing integrity for Passenger" do
47
- install(:passenger => true)
49
+ install("--passenger")
48
50
 
49
51
  assert root.join("public").directory?
50
52
  assert root.join("tmp").directory?
51
53
  end
52
54
 
53
55
  scenario "Installing Integrity for Thin" do
54
- install(:thin => true)
56
+ install("--thin")
55
57
 
56
58
  config = YAML.load_file(root.join("thin.yml"))
57
59
  config["chdir"].should == root.to_s
@@ -59,4 +61,20 @@ class InstallerTest < Test::Unit::AcceptanceTestCase
59
61
  config["rackup"].should == root.join("config.ru").to_s
60
62
  config["log"].should == root.join("log/thin.log").to_s
61
63
  end
64
+
65
+ scenario "Installing Integrity for Heroku" do
66
+ message = install("--heroku")
67
+
68
+ gemifest = root.join(".gems").read
69
+ assert gemifest.include?("mailfactory")
70
+ assert gemifest.include?("tlsmail")
71
+ assert gemifest.include?("foca-sinatra-ditties")
72
+ assert gemifest.include?("integrity")
73
+
74
+ assert root.join("Rakefile").file?
75
+ assert root.join("integrity-config.rb").file?
76
+ assert root.join("config.ru").file?
77
+
78
+ assert message.include?("ready to be deployed onto Heroku")
79
+ end
62
80
  end
data/test/helpers.rb CHANGED
@@ -33,7 +33,7 @@ end
33
33
 
34
34
  require "integrity"
35
35
  require "helpers/expectations"
36
- require "helpers/fixtures"
36
+ require "integrity/notifier/test/fixtures"
37
37
 
38
38
  module TestHelper
39
39
  def ignore_logs!
@@ -61,12 +61,9 @@ class Test::Unit::AcceptanceTestCase < Test::Unit::TestCase
61
61
  }
62
62
  end
63
63
 
64
- before(:all) do
65
- Integrity.config[:base_uri] = "http://www.example.com"
66
- end
67
-
68
64
  before(:each) do
69
65
  # ensure each scenario is run in a clean sandbox
66
+ Integrity.config[:base_uri] = "http://www.example.com"
70
67
  enable_auth!
71
68
  setup_log!
72
69
  set_and_create_export_directory!
@@ -1,25 +1,3 @@
1
- require "dm-sweatshop"
2
-
3
- include DataMapper::Sweatshop::Unique
4
-
5
- class Array
6
- def pick
7
- self[rand(self.length)]
8
- end
9
- end
10
-
11
- def create_notifier!(name)
12
- klass = Class.new(Integrity::Notifier::Base) do
13
- def self.to_haml; ""; end
14
- def deliver!; nil; end
15
- end
16
-
17
- unless Integrity::Notifier.const_defined?(name)
18
- Integrity::Notifier.const_set(name, klass)
19
- end
20
- end
21
-
22
-
23
1
  Integrity::Project.fixture do
24
2
  { :name => (name = unique { /\w+/.gen }),
25
3
  :uri => "git://github.com/#{/\w+/.gen}/#{name}.git",
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + "/../../helpers"
2
+ require "helpers/acceptance/textfile_notifier"
3
+
4
+ require "integrity/notifier/test"
5
+
6
+ class NotifierTestTest < Test::Unit::TestCase
7
+ include Integrity::Notifier::Test
8
+
9
+ before(:each) do
10
+ # Because we unset every notifier in global setup
11
+ load "helpers/acceptance/textfile_notifier.rb"
12
+ end
13
+
14
+ def notifier
15
+ "Textfile"
16
+ end
17
+
18
+ test "it provides a formulary to configure options" do
19
+ assert_form_have_option("file")
20
+ end
21
+
22
+ test "it sends notification" do
23
+ commit = Integrity::Commit.gen(:build => Build.gen(:successful))
24
+
25
+ assert notification(commit).include?(commit.identifier)
26
+ assert notification_failed.include?("failed")
27
+ assert notification_successful.include?("was successful")
28
+ end
29
+ end
@@ -2,7 +2,10 @@ require File.dirname(__FILE__) + "/../helpers"
2
2
 
3
3
  class ProjectBuilderTest < Test::Unit::TestCase
4
4
  before(:all) do
5
- Integrity.config[:export_directory] = File.dirname(__FILE__)
5
+ unless File.directory?(Integrity.config[:export_directory])
6
+ FileUtils.mkdir(Integrity.config[:export_directory])
7
+ end
8
+
6
9
  @directory = Integrity.config[:export_directory] + "/foca-integrity-master"
7
10
  FileUtils.mkdir(@directory)
8
11
  end
@@ -0,0 +1,3 @@
1
+ = Sinatra Ditties
2
+
3
+ All those handy tunes in one elegant package.
@@ -0,0 +1,12 @@
1
+ require "sinatra/base"
2
+
3
+ module Sinatra
4
+ module Ditties
5
+ def self.version
6
+ "0.0.2".freeze
7
+ end
8
+ end
9
+
10
+ autoload :Authorization, File.dirname(__FILE__) + "/ditties/authorization"
11
+ autoload :Mailer, File.dirname(__FILE__) + "/ditties/mailer"
12
+ end
@@ -0,0 +1,61 @@
1
+ module Sinatra
2
+ # HTTP Authorization helpers for Sinatra.
3
+ #
4
+ # In your helpers module, include Sinatra::Authorization and then define
5
+ # a +authorize(user, password)+ method to handle user provided
6
+ # credentials.
7
+ #
8
+ # Inside your events, call +login_required+ to trigger the HTTP
9
+ # Authorization window to pop up in the browser.
10
+ #
11
+ # Code adapted from Ryan Tomayko <http://tomayko.com> and Christopher
12
+ # Schneid <http://gittr.com>, shared under an MIT License
13
+ module Authorization
14
+ # Redefine this method on your helpers block to actually contain
15
+ # your authorization logic.
16
+ def authorize(username, password)
17
+ false
18
+ end
19
+
20
+ # From you app, call set :authorization_realm, "my app" to set this
21
+ # or define a `authorization_realm` method in your helpers block.
22
+ def authorization_realm
23
+ Sinatra::Default.authorization_realm
24
+ end
25
+
26
+ # Call in any event that requires authentication
27
+ def login_required
28
+ return if authorized?
29
+ unauthorized! unless auth.provided?
30
+ bad_request! unless auth.basic?
31
+ unauthorized! unless authorize(*auth.credentials)
32
+ request.env['REMOTE_USER'] = auth.username
33
+ end
34
+
35
+ # Convenience method to determine if a user is logged in
36
+ def authorized?
37
+ !!request.env['REMOTE_USER']
38
+ end
39
+ alias :logged_in? :authorized?
40
+
41
+ # Name provided by the current user to log in
42
+ def current_user
43
+ request.env['REMOTE_USER']
44
+ end
45
+
46
+ private
47
+
48
+ def auth
49
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
50
+ end
51
+
52
+ def unauthorized!(realm=authorization_realm)
53
+ response["WWW-Authenticate"] = %(Basic realm="#{realm}")
54
+ throw :halt, [ 401, 'Authorization Required' ]
55
+ end
56
+
57
+ def bad_request!
58
+ throw :halt, [ 400, 'Bad Request' ]
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,146 @@
1
+ # Shamelssly stolen from Merb::Mailer
2
+ # http://merbivore.com
3
+
4
+ require 'net/smtp'
5
+ require 'rubygems'
6
+ require 'mailfactory'
7
+ require 'tlsmail'
8
+
9
+ Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
10
+
11
+ class MailFactory
12
+ attr_reader :html, :text
13
+ end
14
+
15
+ module Sinatra
16
+ # = Sinatra::Mailer
17
+ #
18
+ # Adds an #email method to your email handlers, that receives a hash of
19
+ # values to create your email.
20
+ #
21
+ # For example:
22
+ #
23
+ # post "/signup" do
24
+ # # sign up the user, and then:
25
+ # email :to => @user.email,
26
+ # :from => "awesomeness@example.com",
27
+ # :subject => "Welcome to Awesomeness!",
28
+ # :body => haml(:some_template)
29
+ # end
30
+ #
31
+ # == Configuration
32
+ #
33
+ # This plugin is very dirty yet :) Since it's just a port to Sinatra of
34
+ # Merb::Mailer[merbivore.com/documentation/1.0/doc/rdoc/merb-mailer-1.0].
35
+ # So the configuration is not Sinatra-y, yet. But we'll get to that.
36
+ #
37
+ # == Using SMTP
38
+ #
39
+ # Sinatra::Mailer.config = {
40
+ # :host => 'smtp.yourserver.com',
41
+ # :port => '25',
42
+ # :user => 'user',
43
+ # :pass => 'pass',
44
+ # :auth => :plain # :plain, :login, :cram_md5, the default is no auth
45
+ # :domain => "localhost.localdomain" # HELO domain provided by the client
46
+ # }
47
+ #
48
+ # == Using Gmail SMTP
49
+ #
50
+ # You need smtp-tls[http://github.com/ambethia/smtp-tls], a gem that improves
51
+ # Net::HTTP to add support for secure servers such as Gmail.
52
+ #
53
+ # require "smtp-tls"
54
+ #
55
+ # Sinatra::Mailer.config = {
56
+ # :host => 'smtp.gmail.com',
57
+ # :port => '587',
58
+ # :user => 'user@gmail.com',
59
+ # :pass => 'pass',
60
+ # :auth => :plain
61
+ # }
62
+ #
63
+ # Make sure that when you call your #email method you pass the
64
+ # +:text+ option and not +:body+.
65
+ #
66
+ # == Using sendmail
67
+ #
68
+ # Sinatra::Mailer.config = {:sendmail_path => '/somewhere/odd'}
69
+ # Sinatra::Mailer.delivery_method = :sendmail
70
+ #
71
+ # == Credits
72
+ #
73
+ # This has been blatantly adapted from
74
+ # Merb::Mailer[merbivore.com/documentation/1.0/doc/rdoc/merb-mailer-1.0]
75
+ # so all credit is theirs, I just ported it to Sinatra.
76
+ module Mailer
77
+ class << self
78
+ attr_accessor :config, :delivery_method
79
+ end
80
+
81
+ def email(mail_options={})
82
+ Email.new(mail_options).deliver!
83
+ end
84
+
85
+ class Email
86
+ attr_accessor :mail, :config
87
+
88
+ # Sends the mail using sendmail.
89
+ def sendmail
90
+ sendmail = IO.popen("#{config[:sendmail_path]} #{@mail.to}", 'w+')
91
+ sendmail.puts @mail.to_s
92
+ sendmail.close
93
+ end
94
+
95
+ # Sends the mail using SMTP.
96
+ def net_smtp
97
+ Net::SMTP.start(config[:host], config[:port].to_i, config[:domain],
98
+ config[:user], config[:pass], config[:auth]) { |smtp|
99
+ smtp.send_message(@mail.to_s, @mail.from.first, @mail.to.to_s.split(/[,;]/))
100
+ }
101
+ end
102
+
103
+ # Delivers the mail with the specified delivery method, defaulting to
104
+ # net_smtp.
105
+ def deliver!
106
+ send(Mailer.delivery_method || :net_smtp)
107
+ end
108
+
109
+ # ==== Parameters
110
+ # file_or_files<File, Array[File]>:: File(s) to attach.
111
+ # filename<String>::
112
+ # type<~to_s>::
113
+ # The attachment MIME type. If left out, it will be determined from
114
+ # file_or_files.
115
+ # headers<String, Array>:: Additional attachment headers.
116
+ #
117
+ # ==== Raises
118
+ # ArgumentError::
119
+ # file_or_files was not a File or an Array of File instances.
120
+ def attach(file_or_files, filename = file_or_files.is_a?(File) ? File.basename(file_or_files.path) : nil,
121
+ type = nil, headers = nil)
122
+ if file_or_files.is_a?(Array)
123
+ file_or_files.each {|k,v| @mail.add_attachment_as k, *v}
124
+ else
125
+ raise ArgumentError, "You did not pass in a file. Instead, you sent a #{file_or_files.class}" if !file_or_files.is_a?(File)
126
+ @mail.add_attachment_as(file_or_files, filename, type, headers)
127
+ end
128
+ end
129
+
130
+ # ==== Parameters
131
+ # o<Hash{~to_s => Object}>:: Configuration commands to send to MailFactory.
132
+ def initialize(o={})
133
+ self.config = Mailer.config || {:sendmail_path => '/usr/sbin/sendmail'}
134
+ o[:rawhtml] = o.delete(:html)
135
+ m = MailFactory.new()
136
+ o.each { |k,v| m.send "#{k}=", v }
137
+ @mail = m
138
+ end
139
+
140
+ end
141
+ end
142
+
143
+ class EventContext
144
+ include Mailer
145
+ end
146
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: integrity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9.0
4
+ version: 0.1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Nicol\xC3\xA1s Sanguinetti"
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-03-13 00:00:00 +01:00
13
+ date: 2009-03-16 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -73,16 +73,6 @@ dependencies:
73
73
  - !ruby/object:Gem::Version
74
74
  version: "0"
75
75
  version:
76
- - !ruby/object:Gem::Dependency
77
- name: foca-sinatra-ditties
78
- type: :runtime
79
- version_requirement:
80
- version_requirements: !ruby/object:Gem::Requirement
81
- requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- version: 0.0.3
85
- version:
86
76
  - !ruby/object:Gem::Dependency
87
77
  name: thor
88
78
  type: :runtime
@@ -102,99 +92,98 @@ extensions: []
102
92
  extra_rdoc_files: []
103
93
 
104
94
  files:
105
- - Rakefile
106
95
  - README.markdown
96
+ - Rakefile
107
97
  - bin/integrity
108
- - lib/integrity
109
- - lib/integrity/project_builder.rb
110
- - lib/integrity/core_ext
111
- - lib/integrity/core_ext/object.rb
112
- - lib/integrity/notifier.rb
113
- - lib/integrity/helpers.rb
114
- - lib/integrity/installer.rb
98
+ - config/config.sample.ru
99
+ - config/config.sample.yml
100
+ - config/heroku/.gems
101
+ - config/heroku/Rakefile
102
+ - config/heroku/config.ru
103
+ - config/heroku/integrity-config.rb
104
+ - config/thin.sample.yml
105
+ - integrity.gemspec
106
+ - lib/integrity.rb
115
107
  - lib/integrity/app.rb
116
- - lib/integrity/build.rb
117
- - lib/integrity/scm
118
- - lib/integrity/scm/git.rb
119
- - lib/integrity/scm/git
120
- - lib/integrity/scm/git/uri.rb
121
108
  - lib/integrity/author.rb
122
- - lib/integrity/project.rb
123
- - lib/integrity/migrations.rb
124
- - lib/integrity/scm.rb
125
- - lib/integrity/helpers
126
- - lib/integrity/helpers/rendering.rb
109
+ - lib/integrity/build.rb
110
+ - lib/integrity/commit.rb
111
+ - lib/integrity/core_ext/object.rb
112
+ - lib/integrity/helpers.rb
127
113
  - lib/integrity/helpers/authorization.rb
128
- - lib/integrity/helpers/forms.rb
129
- - lib/integrity/helpers/resources.rb
130
114
  - lib/integrity/helpers/breadcrumbs.rb
115
+ - lib/integrity/helpers/forms.rb
131
116
  - lib/integrity/helpers/pretty_output.rb
117
+ - lib/integrity/helpers/rendering.rb
118
+ - lib/integrity/helpers/resources.rb
132
119
  - lib/integrity/helpers/urls.rb
133
- - lib/integrity/notifier
120
+ - lib/integrity/installer.rb
121
+ - lib/integrity/migrations.rb
122
+ - lib/integrity/notifier.rb
134
123
  - lib/integrity/notifier/base.rb
135
- - lib/integrity/notifier/test_helpers.rb
136
- - lib/integrity/commit.rb
137
- - lib/integrity.rb
138
- - views/not_found.haml
139
- - views/notifier.haml
140
- - views/new.haml
141
- - views/error.haml
142
- - views/unauthorized.haml
143
- - views/layout.haml
144
- - views/project.builder
145
- - views/_commit_info.haml
146
- - views/project.haml
147
- - views/build.haml
148
- - views/home.haml
149
- - views/integrity.sass
124
+ - lib/integrity/notifier/test.rb
125
+ - lib/integrity/notifier/test/fixtures.rb
126
+ - lib/integrity/notifier/test/hpricot_matcher.rb
127
+ - lib/integrity/project.rb
128
+ - lib/integrity/project_builder.rb
129
+ - lib/integrity/scm.rb
130
+ - lib/integrity/scm/git.rb
131
+ - lib/integrity/scm/git/uri.rb
150
132
  - public/buttons.css
151
- - public/spinner.gif
152
133
  - public/reset.css
153
- - config/config.ru
154
- - config/thin.sample.yml
155
- - config/config.sample.ru
156
- - config/config.yml
157
- - config/config.sample.yml
158
- - test/helpers.rb
159
- - test/acceptance
160
- - test/acceptance/build_notifications_test.rb
161
- - test/acceptance/notifier_test.rb
162
- - test/acceptance/manual_build_project_test.rb
163
- - test/acceptance/helpers.rb
164
- - test/acceptance/stylesheet_test.rb
134
+ - public/spinner.gif
165
135
  - test/acceptance/api_test.rb
166
- - test/acceptance/project_syndication_test.rb
167
- - test/acceptance/error_page_test.rb
136
+ - test/acceptance/browse_project_builds_test.rb
168
137
  - test/acceptance/browse_project_test.rb
169
- - test/acceptance/edit_project_test.rb
170
- - test/acceptance/delete_project_test.rb
138
+ - test/acceptance/build_notifications_test.rb
171
139
  - test/acceptance/create_project_test.rb
140
+ - test/acceptance/delete_project_test.rb
141
+ - test/acceptance/edit_project_test.rb
142
+ - test/acceptance/error_page_test.rb
143
+ - test/acceptance/helpers.rb
172
144
  - test/acceptance/installer_test.rb
173
- - test/acceptance/browse_project_builds_test.rb
174
- - test/unit
175
- - test/unit/helpers_test.rb
176
- - test/unit/migrations_test.rb
177
- - test/unit/notifier_test.rb
178
- - test/unit/project_builder_test.rb
179
- - test/unit/build_test.rb
180
- - test/unit/project_test.rb
181
- - test/unit/commit_test.rb
182
- - test/unit/scm_test.rb
183
- - test/unit/integrity_test.rb
184
- - test/helpers
185
- - test/helpers/expectations.rb
145
+ - test/acceptance/manual_build_project_test.rb
146
+ - test/acceptance/notifier_test.rb
147
+ - test/acceptance/project_syndication_test.rb
148
+ - test/acceptance/stylesheet_test.rb
149
+ - test/helpers.rb
186
150
  - test/helpers/acceptance.rb
187
- - test/helpers/acceptance
188
151
  - test/helpers/acceptance/email_notifier.rb
189
- - test/helpers/acceptance/textfile_notifier.rb
190
152
  - test/helpers/acceptance/git_helper.rb
191
- - test/helpers/expectations
192
- - test/helpers/expectations/have.rb
153
+ - test/helpers/acceptance/textfile_notifier.rb
154
+ - test/helpers/expectations.rb
193
155
  - test/helpers/expectations/be_a.rb
194
- - test/helpers/expectations/predicates.rb
195
156
  - test/helpers/expectations/change.rb
157
+ - test/helpers/expectations/have.rb
158
+ - test/helpers/expectations/predicates.rb
196
159
  - test/helpers/fixtures.rb
197
160
  - test/helpers/initial_migration_fixture.sql
161
+ - test/unit/build_test.rb
162
+ - test/unit/commit_test.rb
163
+ - test/unit/helpers_test.rb
164
+ - test/unit/integrity_test.rb
165
+ - test/unit/migrations_test.rb
166
+ - test/unit/notifier/test_test.rb
167
+ - test/unit/notifier_test.rb
168
+ - test/unit/project_builder_test.rb
169
+ - test/unit/project_test.rb
170
+ - test/unit/scm_test.rb
171
+ - vendor/sinatra-ditties/README.rdoc
172
+ - vendor/sinatra-ditties/lib/sinatra/ditties.rb
173
+ - vendor/sinatra-ditties/lib/sinatra/ditties/authorization.rb
174
+ - vendor/sinatra-ditties/lib/sinatra/ditties/mailer.rb
175
+ - views/_commit_info.haml
176
+ - views/build.haml
177
+ - views/error.haml
178
+ - views/home.haml
179
+ - views/integrity.sass
180
+ - views/layout.haml
181
+ - views/new.haml
182
+ - views/not_found.haml
183
+ - views/notifier.haml
184
+ - views/project.builder
185
+ - views/project.haml
186
+ - views/unauthorized.haml
198
187
  has_rdoc: false
199
188
  homepage: http://integrityapp.com
200
189
  post_install_message: Run `integrity help` for information on how to setup Integrity.
data/config/config.ru DELETED
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.dirname(__FILE__) + "/../lib/integrity"
3
- require "rack/lobster"
4
- # If you want to add any notifiers, install the gems and then require them here
5
- # For example, to enable the Email notifier: install the gem (from github:
6
- #
7
- # sudo gem install -s http://gems.github.com foca-integrity-email
8
- #
9
- # And then uncomment the following line:
10
- #
11
- # require "notifier/email"
12
-
13
- # Load configuration and initialize Integrity
14
- Integrity.new#(File.dirname(__FILE__) + "/config.yml")
15
- DataMapper.auto_migrate!
16
-
17
- # You probably don't want to edit anything below
18
- Integrity::App.set :environment, ENV["RACK_ENV"] || :production
19
- Integrity::App.set :port, 8910
20
- rack = proc do |env|
21
- [200, { 'Content-Type' => 'text/html' }, "#{env['rack.session'].inspect}"]
22
- end
23
-
24
- map "/foo" do
25
- run Integrity::App
26
- end
27
- map "/" do
28
- run rack
29
- end
data/config/config.yml DELETED
@@ -1,34 +0,0 @@
1
- # Domain where integrity will be running from. This is used to have
2
- # nice URLs in your notifications.
3
- # For example:
4
- # http://builder.integrityapp.com
5
- :base_uri: http://0.0.0.0:1234
6
-
7
- # This should be a complete connection string to your database. For example
8
- # `mysql://user@localhost/integrity` (you need an `integrity` db created in
9
- # localhost, of course).
10
- :database_uri: sqlite3:///home/simon/tmp/integrity.db
11
-
12
- # This is where your project's code will be checked out to. Make sure it's
13
- # writable by the user that runs Integrity.
14
- :export_directory: /home/simon/tmp/integrity_exports
15
-
16
- # Path to the integrity log file
17
- :log: /tmp/integrity.log
18
-
19
- # Enable or disable HTTP authentication for the app. BE AWARE that if you
20
- # disable this anyone can delete and alter projects, so do it only if your
21
- # app is running in a controlled environment (ie, behind your company's
22
- # firewall.)
23
- :use_basic_auth: false
24
-
25
- # When `use_basic_auth` is true, the admin's username for HTTP authentication.
26
- :admin_username: username
27
-
28
- # When `use_basic_auth` is true, the admin's password. Usually saved as a
29
- # SHA1 hash. See the next option.
30
- :admin_password: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
31
-
32
- # If this is true, then whenever we authenticate the admin user, will hash
33
- # it using SHA1. If not, we'll assume the provided password is in plain text.
34
- :hash_admin_password: true
@@ -1,100 +0,0 @@
1
- require "hpricot"
2
- require "haml"
3
- require File.dirname(__FILE__) + "/../../integrity"
4
-
5
- module Integrity
6
- class Notifier
7
- module TestHelpers
8
- module HpricotAssertions
9
- # Thanks Harry! http://gist.github.com/39960
10
-
11
- class HpricotMatcher
12
- def initialize(html)
13
- @doc = Hpricot(html)
14
- end
15
-
16
- # elements('h1') returns a Hpricot::Elements object with all h1-tags.
17
- def elements(selector)
18
- @doc.search(selector)
19
- end
20
-
21
- # element('h1') returns Hpricot::Elem with first h1-tag, or nil if
22
- # none exist.
23
- def element(selector)
24
- @doc.at(selector)
25
- end
26
-
27
- # tags('h1') returns the inner HTML of all matched elements mathed.
28
- def tags(selector)
29
- e = elements(selector)
30
- e.map {|x| x.inner_html}
31
- end
32
-
33
- # tag('h1') returns the inner HTML of the first mached element, or
34
- # nil if none matched.
35
- def tag(selector)
36
- e = element(selector)
37
- e && e.inner_html
38
- end
39
- end
40
-
41
- def assert_have_tag(html, selector, content=nil)
42
- matcher = HpricotMatcher.new(html)
43
- assert_equal content, matcher.tag(selector) if content
44
- assert matcher.tag(selector)
45
- end
46
- end
47
-
48
- module NotifierFormHelpers
49
- include HpricotAssertions
50
-
51
- def form(config={})
52
- Haml::Engine.new(notifier_class.to_haml).
53
- render(OpenStruct.new(:config => config))
54
- end
55
-
56
- def assert_form_have_tag(selector, options={})
57
- content = options.delete(:content)
58
- assert_have_tag(form(options), selector, content)
59
- end
60
-
61
- def assert_form_have_option(option, value=nil)
62
- selector = "input##{notifier.downcase}_notifier_#{option}"
63
- selector << "[@name='notifiers[#{notifier}][#{option}]']"
64
- selector << "[@value='#{value}']" if value
65
-
66
- assert_form_have_tag(selector, option => value)
67
- end
68
-
69
- def assert_form_have_options(*options)
70
- options.each { |option| assert_form_have_option(option) }
71
- end
72
- end
73
-
74
- include NotifierFormHelpers
75
-
76
- def build
77
- @build ||= Integrity::Build.gen(:successful)
78
- end
79
-
80
- def commit
81
- @commit ||= build.commit
82
- end
83
-
84
- def notifier_class
85
- Integrity::Notifier.const_get(notifier)
86
- end
87
-
88
- def notification
89
- notifier_class.new(commit).body
90
- end
91
-
92
- def setup_database
93
- DataMapper.setup(:default, "sqlite3::memory:")
94
- DataMapper.auto_migrate!
95
-
96
- require File.dirname(__FILE__) + "/../../../test/helpers/fixtures"
97
- end
98
- end
99
- end
100
- end