fir 0.0.9 → 0.0.10
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.
- data/README.markdown +33 -8
- data/bin/fir +7 -12
- data/example/Rakefile +4 -1
- data/example/deploy.yml +3 -0
- data/example/public/cache/404.html +46 -0
- data/example/public/cache/contact-us.html +48 -0
- data/example/public/cache/index.html +52 -0
- data/example/public/cache/products/dynamite-plus.html +52 -0
- data/example/public/cache/products/dynamite.html +52 -0
- data/example/public/cache/products/index.html +58 -0
- data/example/public/cache/products/mouse-trap.html +52 -0
- data/example/users.yml +0 -1
- data/lib/fir/admin.rb +9 -6
- data/lib/fir/generator.rb +33 -0
- data/lib/fir/tasks.rb +58 -7
- data/skeleton/public/dispatch.cgi +34 -0
- data/skeleton/public/htaccess +3 -0
- data/spec/admin_spec.rb +172 -0
- data/spec/fir_spec.rb +75 -48
- data/spec/generator_spec.rb +132 -0
- data/spec/rack_integration_spec.rb +44 -0
- data/spec/spec_helper.rb +16 -2
- data/spec/support/cache_testing.rb +20 -0
- data/spec/support/file_matchers.rb +22 -0
- data/spec/support/server_matchers.rb +39 -0
- data/spec/support/server_testing.rb +35 -0
- data/spec/support/test_app_setup.rb +11 -0
- data/spec/tasks_spec.rb +132 -0
- metadata +85 -9
@@ -0,0 +1,132 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'Fir.generate!' do
|
4
|
+
def fir_root
|
5
|
+
@fir_root ||= File.expand_path(File.join(File.dirname(__FILE__), '..', 'gen_test_example'))
|
6
|
+
end
|
7
|
+
|
8
|
+
# Args should be a string, e.g. '--with-dispatch-cgi --with-htaccess'
|
9
|
+
def generate(args = '')
|
10
|
+
begin
|
11
|
+
original_dir = Dir.getwd
|
12
|
+
bin = File.join(File.dirname(__FILE__), '..', 'bin', 'fir')
|
13
|
+
`export TESTING_FIR_BIN=1;#{bin} #{fir_root} #{args}`
|
14
|
+
Dir.chdir fir_root
|
15
|
+
yield
|
16
|
+
ensure
|
17
|
+
Dir.chdir original_dir
|
18
|
+
FileUtils::rm_rf fir_root
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def assert_generator_creates(should_create, path_components)
|
23
|
+
path_components.unshift(fir_root) unless path_components.first == fir_root
|
24
|
+
generate do
|
25
|
+
if should_create
|
26
|
+
File.join(path_components).should exist_on_disk
|
27
|
+
else
|
28
|
+
File.join(path_components).should_not exist_on_disk
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def generator_should_create(*path_components)
|
34
|
+
assert_generator_creates(true, path_components)
|
35
|
+
end
|
36
|
+
|
37
|
+
def generator_should_not_create(*path_components)
|
38
|
+
assert_generator_creates(false, path_components)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'creates a Fir site that can be booted with Rackup' do
|
42
|
+
generate do
|
43
|
+
[fir_root, 'rackup -p 3001'].should spawn_working_server
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'creates the root directory' do
|
48
|
+
generator_should_create fir_root
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'creates the pages directory' do
|
52
|
+
generator_should_create 'pages'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'creates the layouts directory' do
|
56
|
+
generator_should_create 'layouts'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'creates the public directory' do
|
60
|
+
generator_should_create 'public'
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'creates the tmp directory' do
|
64
|
+
generator_should_create 'tmp'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'creates config.rb' do
|
68
|
+
generator_should_create 'config.rb'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'does not create .htaccess by default' do
|
72
|
+
generator_should_not_create 'public', '.htaccess'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'creates .htaccess if --with-htaccess is given' do
|
76
|
+
generate('--with-htaccess') do
|
77
|
+
File.join(fir_root, 'public', '.htaccess').should exist_on_disk
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'does not create dispatch.cgi by default' do
|
82
|
+
generator_should_not_create 'public', 'dispatch.cgi'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'creates dispatch.cgi if --with-dispatch-cgi is given' do
|
86
|
+
generate('--with-dispatch-cgi') do
|
87
|
+
File.join(fir_root, 'public', 'dispatch.cgi').should exist_on_disk
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'config.rb' do
|
92
|
+
it 'calls Fir.config' do
|
93
|
+
generate do
|
94
|
+
Fir.should_receive(:config)
|
95
|
+
load File.join(fir_root, 'config.rb')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'sets the default site name' do
|
100
|
+
generate do
|
101
|
+
Fir.config.should_receive(:site_name=)
|
102
|
+
load File.join(fir_root, 'config.rb')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'creates menus.yml' do
|
108
|
+
generator_should_create 'menus.yml'
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'creates pages.yml' do
|
112
|
+
generator_should_create 'pages.yml'
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'creates Rakefile' do
|
116
|
+
generator_should_create 'Rakefile'
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'Rakefile' do
|
120
|
+
it 'has a task called users:add' do
|
121
|
+
generate do
|
122
|
+
`rake -D`.should include('users:add')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'has a task called export' do
|
127
|
+
generate do
|
128
|
+
`rake -D`.should include('export')
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
# This is where we test with real, honest-to-goodness server processes.
|
4
|
+
# The point is to ensure that Fir can integrate with Rack-compliant servers.
|
5
|
+
|
6
|
+
describe 'Rack integration' do
|
7
|
+
def fir_root
|
8
|
+
@fir_root ||= File.expand_path(File.join(File.dirname(__FILE__), '..', 'example'))
|
9
|
+
end
|
10
|
+
|
11
|
+
def home_should_be_accessible(options = {})
|
12
|
+
options = {:host => 'localhost', :port => 3001}.merge(options)
|
13
|
+
retry_request do
|
14
|
+
Net::HTTP.get(URI.parse("http://#{options[:host]}:#{options[:port]}")).should contain('Welcome to Acme Company!')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with rackup' do
|
19
|
+
it 'allows access to the home page' do
|
20
|
+
with_spawned_server(fir_root, 'rackup -p 3001') do
|
21
|
+
home_should_be_accessible
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with CGI' do
|
27
|
+
# This is a simple way to test CGI support. We can't
|
28
|
+
# test against Apache, because that requires installing and configuring
|
29
|
+
# it, which we obviously can't do in this test suite. Sadly, this means we
|
30
|
+
# can't test .htaccess. That's a shame, because there is a very real
|
31
|
+
# possibility of errors creeping into .htaccess.
|
32
|
+
#
|
33
|
+
# Instead, we set up a mock CGI environment by setting environment variables.
|
34
|
+
#
|
35
|
+
# It would be even better if we could test this against a light web server running
|
36
|
+
# in a forked process, but there doesn't seem to be an easy way to do that.
|
37
|
+
it 'allows access to the home page' do
|
38
|
+
dispatch = File.join(fir_root, 'public', 'dispatch.cgi')
|
39
|
+
response = `export PATH_INFO=/; ruby #{dispatch}`
|
40
|
+
response.should include('Status: 200')
|
41
|
+
response.should include('Welcome to Acme Company!')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,23 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
3
|
require 'fir'
|
4
|
+
require 'fir/generator'
|
4
5
|
require 'spec'
|
5
6
|
require 'spec/autorun'
|
7
|
+
require 'rack/test'
|
8
|
+
require 'webrat'
|
9
|
+
require 'rake'
|
10
|
+
|
11
|
+
Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
|
12
|
+
|
13
|
+
FIR_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', 'example'))
|
6
14
|
|
7
15
|
Spec::Runner.configure do |config|
|
8
|
-
|
9
|
-
|
16
|
+
config.include Rack::Test::Methods
|
17
|
+
config.include Webrat::Matchers
|
18
|
+
config.include Fir::TestAppSetup
|
19
|
+
config.include Fir::CacheTesting
|
20
|
+
config.include Fir::ServerTesting
|
21
|
+
config.include Fir::FileMatchers
|
22
|
+
config.include Fir::ServerMatchers
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Fir
|
2
|
+
module CacheTesting
|
3
|
+
# Path should be like this:
|
4
|
+
# directory/page
|
5
|
+
# Not this:
|
6
|
+
# directory/page.html
|
7
|
+
def with_cache(path, contents)
|
8
|
+
filename = File.join(FIR_ROOT, 'public', 'cache', path + '.html')
|
9
|
+
dirname = File.dirname(filename)
|
10
|
+
unless File.directory?(dirname)
|
11
|
+
FileUtils.mkdir_p(dirname)
|
12
|
+
end
|
13
|
+
File.open(filename, 'w') do |file|
|
14
|
+
file.write(contents)
|
15
|
+
end
|
16
|
+
yield
|
17
|
+
File.delete(filename)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Fir
|
2
|
+
module FileMatchers
|
3
|
+
class ExistOnDisk
|
4
|
+
def matches?(path)
|
5
|
+
@path = path
|
6
|
+
File.exists?(path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def failure_message
|
10
|
+
"Expected #{@path} to exist"
|
11
|
+
end
|
12
|
+
|
13
|
+
def negative_failure_message
|
14
|
+
"Expected #{@path} not to exist"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def exist_on_disk
|
19
|
+
ExistOnDisk.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'server_testing.rb'))
|
2
|
+
|
3
|
+
module Fir
|
4
|
+
module ServerMatchers
|
5
|
+
class SpawnWorkingServer
|
6
|
+
include Fir::ServerTesting
|
7
|
+
|
8
|
+
def matches?(command_arr)
|
9
|
+
@dir = command_arr[0]
|
10
|
+
@command = command_arr[1]
|
11
|
+
@host_and_port = command_arr[2] || 'localhost:3001'
|
12
|
+
@response = nil
|
13
|
+
with_spawned_server(@dir, @command) do
|
14
|
+
retry_request do
|
15
|
+
@response = Net::HTTP.get(URI.parse("http://#{@host_and_port}"))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
@response.is_a?(String) and @response.include?('Home')
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message
|
22
|
+
"Expected that running #{@command} in #{@dir} would spawn a working server at #{@host_and_port}. Response: #{@response.inspect}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def negative_failure_message
|
26
|
+
"Expected that running #{@command} in #{@dir} would not spawn a working server at #{@host_and_port}. Response: #{@response.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Usage:
|
31
|
+
# [dir, command, host_and_port].should spawn_working_server
|
32
|
+
# This will cd to dir, try to spawn a server with command,
|
33
|
+
# and try to GET http://host_and_port. host_and_port is optional.
|
34
|
+
# It defaults to localhost:3001.
|
35
|
+
def spawn_working_server
|
36
|
+
SpawnWorkingServer.new
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Fir
|
2
|
+
module ServerTesting
|
3
|
+
def with_spawned_server(dir, command)
|
4
|
+
original_dir = Dir.getwd
|
5
|
+
Dir.chdir(dir)
|
6
|
+
begin
|
7
|
+
server_pid = fork do
|
8
|
+
puts 'About to spawn server.'
|
9
|
+
exec command
|
10
|
+
end
|
11
|
+
response = ''
|
12
|
+
yield
|
13
|
+
ensure
|
14
|
+
puts "About to kill server. The interrupt message is normal. Don't worry about it."
|
15
|
+
Process.kill('INT', server_pid)
|
16
|
+
Dir.chdir(original_dir)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def retry_request
|
21
|
+
failures = 0
|
22
|
+
begin
|
23
|
+
yield
|
24
|
+
rescue Errno::ECONNREFUSED => exc
|
25
|
+
failures += 1
|
26
|
+
if failures == 3
|
27
|
+
raise exc
|
28
|
+
else
|
29
|
+
sleep((2 ** failures) * 0.3)
|
30
|
+
retry
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/spec/tasks_spec.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'Fir Rake tasks' do
|
4
|
+
Fir::Tasks.define # Some tasks need to be executed within this Ruby instance so that we can use stubs, method expectations, etc.
|
5
|
+
|
6
|
+
def fir_root
|
7
|
+
@fir_root ||= File.expand_path(File.join(File.dirname(__FILE__), '..', 'example'))
|
8
|
+
end
|
9
|
+
|
10
|
+
def rake(args)
|
11
|
+
original_wd = Dir.getwd
|
12
|
+
output = nil
|
13
|
+
begin
|
14
|
+
Dir.chdir(fir_root)
|
15
|
+
output = `export TESTING_FIR_TASKS=1;rake #{args}`
|
16
|
+
ensure
|
17
|
+
Dir.chdir(original_wd)
|
18
|
+
end
|
19
|
+
output
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'users:add' do
|
23
|
+
it 'adds a new user with hashed and salted password' do
|
24
|
+
yaml_path = File.join(fir_root, 'users.yml')
|
25
|
+
original_yaml = YAML::load(File.read(yaml_path))
|
26
|
+
begin
|
27
|
+
rake('users:add user=someone pass=password')
|
28
|
+
new_yaml = YAML::load(File.read(yaml_path))
|
29
|
+
new_yaml.should have_key('someone')
|
30
|
+
salt = new_yaml['someone']['salt']
|
31
|
+
new_yaml['someone']['crypted_password'].should == Fir.encrypt_password('password', salt)
|
32
|
+
ensure
|
33
|
+
File.open(yaml_path, 'w') do |file|
|
34
|
+
file.write(YAML::dump(original_yaml))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'export' do
|
41
|
+
def export(extra_args = nil)
|
42
|
+
output = nil
|
43
|
+
begin
|
44
|
+
output = rake("export dir=\"../exported_example\" #{extra_args}")
|
45
|
+
yield if block_given?
|
46
|
+
ensure
|
47
|
+
FileUtils.rm_rf export_root
|
48
|
+
end
|
49
|
+
output
|
50
|
+
end
|
51
|
+
|
52
|
+
def export_root
|
53
|
+
File.expand_path File.join(fir_root, '..', 'exported_example')
|
54
|
+
end
|
55
|
+
|
56
|
+
def should_export(*path_components)
|
57
|
+
path_components.unshift(export_root) unless path_components.first == export_root
|
58
|
+
export do
|
59
|
+
File.join(path_components).should exist_on_disk
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def with_existing_files
|
64
|
+
begin
|
65
|
+
Dir.mkdir(export_root)
|
66
|
+
old_file_path = File.join(export_root, 'old.txt')
|
67
|
+
File.open(old_file_path, 'w') { |file| file.write 'Old' }
|
68
|
+
yield
|
69
|
+
ensure
|
70
|
+
FileUtils.rm_rf export_root
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'creates the root directory' do
|
75
|
+
should_export export_root
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'fails if the root directory is not empty and the force option was not given' do
|
79
|
+
with_existing_files do
|
80
|
+
export.should include('Directory is not empty')
|
81
|
+
File.join(export_root, 'index.html').should_not exist_on_disk
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'overwrites everything if the root directory exists and the force option was given' do
|
86
|
+
with_existing_files do
|
87
|
+
export('force=1') do
|
88
|
+
File.join(export_root, 'old.txt').should_not exist_on_disk
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'export_to_server' do
|
95
|
+
def run_export_to_server
|
96
|
+
ENV['dest'] = 'username@host.com:/home/username/public_html'
|
97
|
+
Rake::Task['export_to_server'].execute
|
98
|
+
end
|
99
|
+
|
100
|
+
before :each do
|
101
|
+
@rsyncer = ::Fir::Tasks::Rsyncer.new
|
102
|
+
::Fir::Tasks::Rsyncer.stub(:new).and_return(@rsyncer)
|
103
|
+
@rsyncer.stub(:run_command)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'exports the site first' do
|
107
|
+
begin
|
108
|
+
export_root = File.expand_path(File.join(File.dirname(__FILE__), 'testable_export_tmp'))
|
109
|
+
@rsyncer.stub(:run_command).and_return do
|
110
|
+
FileUtils.cp_r('.server_export_tmp', export_root)
|
111
|
+
end
|
112
|
+
run_export_to_server
|
113
|
+
export_root.should exist_on_disk
|
114
|
+
File.join(export_root, 'index.html').should exist_on_disk
|
115
|
+
File.join(export_root, 'products', 'index.html').should exist_on_disk
|
116
|
+
ensure
|
117
|
+
FileUtils.rm_rf export_root
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'rsyncs the exported site to the server' do
|
122
|
+
@rsyncer.should_receive(:run_command).with('rsync -ave ssh .server_export_tmp/* username@host.com:/home/username/public_html')
|
123
|
+
run_export_to_server
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'uses deploy.yml if it exists' do
|
127
|
+
ENV['dest'] = nil
|
128
|
+
@rsyncer.should_receive(:run_command).with('rsync -ave ssh .server_export_tmp/* me@example.com:/www-root')
|
129
|
+
Rake::Task['export_to_server'].execute
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|