jobim 0.5.0 → 0.6.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fac1f285dd7910f146c63dcad408ce2351dbe456
4
- data.tar.gz: 32036107d6d25b517648aa1f2a07b539f1e77b45
3
+ metadata.gz: bfa8178336f50e709e059a336e5c6591369dec55
4
+ data.tar.gz: 3b493302ce532f7253b9cb479928c55acf171675
5
5
  SHA512:
6
- metadata.gz: 8356e9b1d0ae90852a69e1cd3debc4178d63da25acbecf828845fe1d0be7989fcad06ecdd85979752af833b843f42c4a9af644ba7bd7c622eca72810441eb68b
7
- data.tar.gz: 8cc2ddb3c4dd8cb1f2228918360cfb5e29967d1812b2fd64f83fdda977961edb5d974ce7a2ef328a049ce892ccdbf4f9bbc043ea3ac62612c5a49175f44bb1b0
6
+ metadata.gz: b7088b4464eb2a73c88a1d36273426b00bacdedc2e62d41861e67cff013dbe7fe6834cfd9e6fe82561097d3a5c4e9ec387db003f0133f0bf9c83aaf4f4f626b4
7
+ data.tar.gz: 19e8af1b48aa7ef99ffbeb9eae774a31e772a8d471628c102eb9cf18f9c7ac8533492e84a400886393384b0436bb8c0f7f80817c9f5109684925ca5807c89173
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,2 @@
1
+ MethodLength:
2
+ Enabled: false
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.0.0
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Jobim
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/jobim.png)](http://badge.fury.io/rb/jobim)
4
+ [![Build Status](https://secure.travis-ci.org/zellio/jobim.png?branch=master)](http://travis-ci.org/zellio/jobim)
4
5
  [![Dependency Status](https://gemnasium.com/zellio/jobim.png)](https://gemnasium.com/zellio/jobim)
5
6
  [![Code Climate](https://codeclimate.com/github/zellio/jobim.png)](https://codeclimate.com/github/zellio/jobim)
6
7
 
@@ -8,7 +9,8 @@
8
9
  for rapid website design and development without the hassle and security risk
9
10
  of a full web-server installation. `jobim` leverages
10
11
  [Thin](//github.com/macournoyer/thin/) and exposes a limited subset of the
11
- `thin` executable command flags for your convenience.
12
+ `thin` executable command flags for your convenience in addition to a set of
13
+ flags for its own configuration.
12
14
 
13
15
  ## Installation
14
16
 
@@ -26,8 +28,9 @@ Usage: jobim [OPTION]... [DIRECTORY]
26
28
 
27
29
  Specific options:
28
30
  -a, --address HOST bind to HOST address (default: 0.0.0.0)
31
+ -c, --[no-]config [PATH] Disable config loading or specify path to load from
29
32
  -d, --daemonize Run as a daemon process
30
- -p, --port PORT use PORT (default: 5634)
33
+ -p, --port PORT use PORT (default: 3000)
31
34
  -P, --prefix PATH Mount the app under PATH
32
35
  -q, --quiet Silence all logging
33
36
 
@@ -40,14 +43,36 @@ Report bugs to: <https://github.com/zellio/jobim/issues>
40
43
  ```
41
44
 
42
45
  `jobim` is run like `thin` but does not require a configuration script. By
43
- default `jobim` will bind to `0.0.0.0:5634` and serve the current working
46
+ default `jobim` will bind to `0.0.0.0:3000` and serve the current working
44
47
  directory.
45
48
 
46
49
  ``` shell
47
50
  jobim path/to/webroot
48
51
  ```
49
52
 
50
- The site can be viewed at `http://localhost:5634` via a normal web browser.
53
+ The site can be viewed at `http://localhost:3000` via a normal web browser.
54
+
55
+ ### Configuration Files
56
+
57
+ `jobim` also allows for the use of a configuration file `.jobim.yml`. This can
58
+ be used to set sane defaults for the `jobim` program to use in every
59
+ execution. `jobim` will search up from the current working directory until it
60
+ reaches `/` in the pursuit of configuration files, with the configuration
61
+ options cascading from root to the current working directory. Options passed
62
+ as command flags to `jobim` always win.
63
+
64
+ ```
65
+ # Example config file
66
+ ---
67
+ :dir: /web_root
68
+ :prefix: /foo
69
+ :port: 300
70
+ ```
71
+
72
+ All options must be specified as key value pairs in a depth one hash. The keys
73
+ must be ruby symbols (For historical reasons capitalization of these keys is
74
+ irrelevant but they should be all downcase). The valid options are
75
+ `:daemonize`, `:dir`, `:host`, `:port`, `:prefix`, `:quiet`, and `:conf_dir`.
51
76
 
52
77
  ## Contributing
53
78
 
@@ -59,4 +84,5 @@ The site can be viewed at `http://localhost:5634` via a normal web browser.
59
84
 
60
85
  ## Copyright
61
86
 
62
- Copyright (c) 2013 Zachary Elliott. See [LICENSE](/LICENSE) for further details.
87
+ Copyright (c) 2013-2014 Zachary Elliott. See [LICENSE](/LICENSE) for further
88
+ details.
data/Rakefile CHANGED
@@ -1 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/jobim CHANGED
@@ -3,8 +3,8 @@
3
3
  require 'pathname'
4
4
  file = Pathname.new(__FILE__).realpath
5
5
 
6
- $:.unshift File.expand_path("../../lib", file)
6
+ $LOAD_PATH.unshift File.expand_path('../../lib', file)
7
7
 
8
8
  require 'jobim'
9
9
 
10
- Jobim::CLI.run!(*ARGV)
10
+ Jobim::Application.run(*ARGV)
@@ -25,9 +25,13 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.add_development_dependency "bundler", "~> 1.3"
27
27
  spec.add_development_dependency "rake", "~> 10.1"
28
+ spec.add_development_dependency "rspec"
29
+ spec.add_development_dependency "simplecov"
28
30
  spec.add_development_dependency 'yard', "~> 0.8"
29
31
  spec.add_development_dependency 'redcarpet', "~> 3.0"
30
32
  spec.add_development_dependency 'github-markup', "~> 0.7"
33
+ spec.add_development_dependency 'fakefs', '~> 0.5'
34
+ spec.add_development_dependency 'rack-test'
31
35
 
32
36
  spec.add_runtime_dependency "thin", "~> 1.5"
33
37
  spec.add_runtime_dependency "rack-rewrite", "~> 1.2"
@@ -1,9 +1,8 @@
1
-
1
+ # Jobim application container
2
2
  module Jobim
3
-
4
- require "jobim/version"
5
- require "jobim/settings"
6
- require "jobim/server"
7
- require "jobim/cli"
8
-
3
+ require 'jobim/version'
4
+ require 'jobim/settings'
5
+ require 'jobim/server'
6
+ require 'jobim/cli'
7
+ require 'jobim/application'
9
8
  end
@@ -0,0 +1,26 @@
1
+ # Application container for initialization and execution of Jobim's
2
+ # resources. Generates a new `Jobim::CLI` instance, and then passes it off to
3
+ # a `Jobim::Server`. Good chance this will change in the future.
4
+ module Jobim::Application
5
+ # Initializes and runs the CLI and Server
6
+ #
7
+ # @param args [Array<String>] list of args passed to the application
8
+ # @param block [Block] dummy block object (Not used)
9
+ def self.run(*args, &block)
10
+ cli = Jobim::CLI.new
11
+ begin
12
+ cli.parse(args)
13
+
14
+ exit if cli.exit
15
+
16
+ Jobim::Server.start!(cli.settings)
17
+ rescue OptionParser::InvalidOption => invalid_option
18
+ $stderr.puts ">>> Error: #{invalid_option}"
19
+ $stderr.puts cli.help
20
+
21
+ rescue RuntimeError => runtime_error
22
+ $stderr.puts '>>> Failed to start server'
23
+ $stderr.puts ">> #{runtime_error}"
24
+ end
25
+ end
26
+ end
@@ -1,91 +1,108 @@
1
1
  require 'optparse'
2
2
 
3
+ # Command line interface for the Jobim application. Utilizes optparse to
4
+ # manage user arguments and populates a `Jobim::Settings` object.
3
5
  class Jobim::CLI
6
+ attr_reader :parser, :settings, :exit, :options
4
7
 
5
- attr_reader :parser, :settings
6
-
7
- def self.run!(*args, &opts)
8
- cli = Jobim::CLI.new
9
- begin
10
- cli.parse(args)
11
-
12
- exit if cli.options.nil?
13
-
14
- Jobim::Server.start cli.options
15
-
16
- rescue OptionParser::InvalidOption => invalid_option
17
- puts ">>> Error: #{invalid_option}"
18
- puts cli.help
19
-
20
- rescue RuntimeError => runtime_error
21
- puts ">>> Failed to start server"
22
- puts ">> #{runtime_error}"
23
- end
24
- end
25
-
8
+ # Memoized, lazy accessor for the settings object.
9
+ #
10
+ # @return [Jobim::Settings]
26
11
  def settings
27
- @settings ||= Jobim::Settings.new
12
+ @settings ||= Jobim::Settings.new(options)
28
13
  end
29
14
 
15
+ # Memoized, lazy accessor for the options hash.
16
+ #
17
+ # @return [Hash] options generated from #parse
30
18
  def options
31
- settings.options
19
+ @options ||= {
20
+ daemonize: false,
21
+ dir: Dir.pwd,
22
+ host: '0.0.0.0',
23
+ port: 3000,
24
+ prefix: '/',
25
+ quiet: false,
26
+ conf_dir: Dir.pwd
27
+ }
32
28
  end
33
29
 
30
+ # Memoized accessor for the `OptionParser` object. It is generated only when
31
+ # called upon. See the readme for information about the command flags.
32
+ #
33
+ # @return [OptionParser]
34
34
  def parser
35
35
  @parser ||= OptionParser.new do |o|
36
- o.banner = "Usage: jobim [OPTION]... [DIRECTORY]"
36
+ o.banner = 'Usage: jobim [OPTION]... [DIRECTORY]'
37
+
38
+ o.separator ''
39
+ o.separator 'Specific options:'
37
40
 
38
- o.separator ""
39
- o.separator "Specific options:"
41
+ o.on('-a', '--address HOST',
42
+ 'bind to HOST address (default: 0.0.0.0)') do |host|
43
+ options[:host] = host
44
+ end
40
45
 
41
- o.on("-a", "--address HOST",
42
- "bind to HOST address (default: 0.0.0.0)") do |host|
43
- options[:Host] = host
46
+ o.on('-c', '--[no-]config [PATH]',
47
+ 'Disable config loading or specify path to load from') do |v|
48
+ options[:conf_dir] = v.nil? ? Dir.pwd : v
44
49
  end
45
50
 
46
- o.on "-d", "--daemonize", "Run as a daemon process" do
47
- options[:Daemonize] = true
51
+ o.on '-d', '--daemonize', 'Run as a daemon process' do
52
+ options[:daemonize] = true
48
53
  end
49
54
 
50
- o.on "-p", "--port PORT", "use PORT (default: 5634)" do |port|
51
- options[:Port] = port
55
+ o.on('-p', '--port PORT', OptionParser::DecimalInteger,
56
+ 'use PORT (default: 3000)') do |port|
57
+ fail OptionParser::InvalidArgument if port == 0
58
+ options[:port] = port
52
59
  end
53
60
 
54
- o.on "-P", "--prefix PATH", "Mount the app under PATH" do |path|
55
- options[:Prefix] = path
61
+ o.on '-P', '--prefix PATH', 'Mount the app under PATH' do |path|
62
+ options[:prefix] = path
56
63
  end
57
64
 
58
- o.on "-q", "--quiet", "Silence all logging" do
59
- options[:Quiet] = true
65
+ o.on '-q', '--quiet', 'Silence all logging' do
66
+ options[:quiet] = true
60
67
  end
61
68
 
62
- o.separator ""
63
- o.separator "General options:"
69
+ o.separator ''
70
+ o.separator 'General options:'
64
71
 
65
- o.on "-h", "--help", "Display this help message." do
72
+ o.on '-h', '--help', 'Display this help message.' do
73
+ @exit = true
66
74
  puts help
67
- exit
68
75
  end
69
- o.on "--version", "Display the version number" do
70
- options[:version] = Jobim::VERSION
71
- puts options[:version]
72
- exit
76
+ o.on '--version', 'Display the version number' do
77
+ @exit = true
78
+ puts "#{Jobim::VERSION}\n"
73
79
  end
74
80
 
75
- o.separator ""
76
- o.separator "Jobim home page: <https://github.com/zellio/jobim/>"
77
- o.separator "Report bugs to: <https://github.com/zellio/jobim/issues>"
78
- o.separator ""
81
+ o.separator ''
82
+ o.separator 'Jobim home page: <https://github.com/zellio/jobim/>'
83
+ o.separator 'Report bugs to: <https://github.com/zellio/jobim/issues>'
84
+ o.separator ''
79
85
  end
80
86
  end
81
87
 
88
+ # Runs the parse method of the value returned by the `#parser` method. This
89
+ # is done in a manner destructive to the passed args `Array`. If there is a
90
+ # trailing value after parsing is completed it is treated as the `:dir`
91
+ # option.
92
+ #
93
+ # @param [Array<String>] args to be paresed
94
+ # @return [NilClass] sentitinal nil value
82
95
  def parse(args)
83
96
  parser.parse!(args)
84
- options[:Dir] = File.expand_path(args[0]) if args.length == 1
97
+ options[:dir] = File.expand_path(args[0]) if args.length == 1
98
+
99
+ nil
85
100
  end
86
101
 
102
+ # Help documentation of the program.
103
+ #
104
+ # @return [String]
87
105
  def help
88
106
  parser.to_s
89
107
  end
90
-
91
108
  end
@@ -1,21 +1,94 @@
1
+ require 'thin'
1
2
  require 'rack'
2
3
  require 'rack/rewrite'
3
4
 
4
- module Jobim::Server
5
+ # HTTP Server container. Contains the Rack application definition and routing
6
+ # tables. Class explicitly leverages `::Thin::Server` to create the HTTP
7
+ # server, this should possibly be changed.
8
+ class Jobim::Server
9
+ # Utitly wrapper to create and start a new `Jobim::Server` instnace.
10
+ #
11
+ # @param opts [Hash] option hash for server configuration
12
+ # @return [Jobim::Server] new running server instance
13
+ def self.start!(opts)
14
+ Jobim::Server.new(opts).start
15
+ end
16
+
17
+ attr_accessor :app, :settings, :server
18
+
19
+ def initialize(settings, &block)
20
+ @settings = settings
21
+
22
+ yield self if block_given?
23
+ end
24
+
25
+ # Memoized accessor for the server Rack application.
26
+ #
27
+ # NB. This has been split into a memoized called to `#build_app` becuase of
28
+ # the way the `Rack::Builder` class handles scope in the context of
29
+ # `instance_eval` instead of `yield`.
30
+ #
31
+ # @return [Rack::Builder]
32
+ def app
33
+ @app ||= build_app(settings)
34
+ end
35
+
36
+ # Memoized accessor for the internal server instance.
37
+ #
38
+ # This is currently explicitly a `::Thin::Server`, possibly should change
39
+ # into a more generic form.
40
+ #
41
+ # @return [Thin::Server]
42
+ def server
43
+ if @server.nil?
44
+ thin_app = Rack::Chunked.new(Rack::ContentLength.new(app))
45
+ server = ::Thin::Server.new(settings.host, settings.port, thin_app)
5
46
 
6
- def self.start(opts)
7
- app = Rack::Builder.new do
47
+ if settings.daemonize
48
+ server.pid_file = 'jobim.pid'
49
+ server.log_file = 'jobim.log'
50
+ end
51
+
52
+ @server = server
53
+ end
54
+
55
+ @server
56
+ end
57
+
58
+ # Pass through delegation to the internal server object's start method.
59
+ # Handles daemonizing the server before starting it if nessesary.
60
+ def start
61
+ Thin::Logging.silent = settings.quiet
62
+
63
+ puts ">>> Serving #{settings.dir}"
64
+
65
+ server.daemonize if settings.daemonize
66
+ server.start
67
+ end
68
+
69
+ private
70
+
71
+ # Method to create a new instance of the Rack application. The creation
72
+ # functionality has been broken out into its own method for scope
73
+ # reason. `Rack::Builder` uses instance_eval which makes generating
74
+ # applicaitons a pain.
75
+ #
76
+ # @param opts [Hash] option hash for server configuration
77
+ # @return [Rack::Builder] Rack::Builder instance for application routing
78
+ def build_app(opts)
79
+ Rack::Builder.new do
8
80
  use Rack::Rewrite do
9
- rewrite(%r{(.*)}, lambda do |match, env|
10
- request_path = env["REQUEST_PATH"]
81
+ rewrite(/(.*)/, lambda do |match, env|
82
+ request_path = env['PATH_INFO']
11
83
 
12
- return match[1] if opts[:Prefix].length > request_path.length
84
+ return match[1] if opts.prefix.length > request_path.length
13
85
 
14
- local_path = File.join(opts[:Dir], request_path[opts[:Prefix].length..-1])
86
+ local_path = File.join(opts.dir,
87
+ request_path[opts.prefix.length..-1])
15
88
 
16
- if File.directory?(local_path) and
17
- File.exists?(File.join(local_path, "index.html"))
18
- File.join(request_path, "index.html")
89
+ if File.directory?(local_path) &&
90
+ File.exists?(File.join(local_path, 'index.html'))
91
+ File.join(request_path, 'index.html')
19
92
  else
20
93
  match[1]
21
94
  end
@@ -24,22 +97,9 @@ module Jobim::Server
24
97
 
25
98
  use Rack::CommonLogger, STDOUT
26
99
 
27
- map opts[:Prefix] do
28
- run Rack::Directory.new(opts[:Dir])
29
- end
30
- end
31
-
32
- puts ">>> Serving #{opts[:Dir]}"
33
-
34
- Rack::Handler::Thin.run(app, opts) do |server|
35
- if opts[:Daemonize]
36
- server.pid_file = 'jobim.pid'
37
- server.log_file = 'jobim.log'
38
- server.daemonize
100
+ map opts.prefix do
101
+ run Rack::Directory.new(opts.dir)
39
102
  end
40
-
41
- Thin::Logging.silent = opts[:Quiet]
42
103
  end
43
104
  end
44
-
45
105
  end
@@ -1,56 +1,70 @@
1
1
  require 'yaml'
2
2
 
3
+ # Manages applications settings and configuration. Handles sane defaults and
4
+ # the loading / merging of configuration from files.
3
5
  class Jobim::Settings
6
+ VALID_KEYS = [:daemonize, :dir, :host, :port, :prefix, :quiet, :conf_dir]
4
7
 
5
- attr_reader :options
8
+ attr_accessor *VALID_KEYS
6
9
 
7
- def initialize
8
- load
10
+ def initialize(defaults = {})
11
+ update(defaults)
12
+ load if conf_dir
9
13
  end
10
14
 
11
- def options
12
- @options ||= {
13
- :Daemonize => false,
14
- :Dir => Dir.pwd,
15
- :Host => '0.0.0.0',
16
- :Port => 5634,
17
- :Prefix => '/',
18
- :Quiet => false
19
- }
15
+ def update(opts)
16
+ VALID_KEYS.each { |key| send("#{key}=", opts[key]) unless opts[key].nil? }
17
+ self
20
18
  end
21
19
 
20
+ # Loads a configuration file in the yaml format into the settings object.
21
+ #
22
+ # @param [String] file path to the configuration file
23
+ # @return [Jobim::Settings] self
22
24
  def load_file(file)
23
- opts = YAML.load_file(file)
25
+ opts = YAML.load_file(file) || {}
24
26
  opts.keys.each do |key|
25
- opts[(key.to_s.capitalize.to_sym rescue key) || key] = opts.delete(key)
27
+ begin
28
+ opts[key.to_s.downcase.to_sym || key] = opts.delete(key)
29
+ rescue
30
+ opts[key] = opts.delete(key)
31
+ end
26
32
  end
27
33
 
28
- if opts[:Dir]
29
- unless Pathname.new(opts[:Dir]).absolute?
30
- opts[:Dir] = File.expand_path("../#{opts[:Dir]}", file)
34
+ if opts[:dir]
35
+ unless Pathname.new(opts[:dir]).absolute?
36
+ opts[:dir] = File.expand_path("../#{opts[:dir]}", file)
31
37
  end
32
38
  end
33
39
 
34
- options.merge!(opts)
40
+ update(opts)
35
41
  end
36
42
 
37
- def load
38
- dir = Pathname('.').realpath
43
+ # Loads all configuration files from provided directory up. Defaults to the
44
+ # current working directory of the program.
45
+ #
46
+ # @param [String] directory to load files from (defaults to Dir.pwd)
47
+ # @return [Jobim::Settings] self
48
+ def load(dir = conf_dir)
49
+ dir = Pathname(File.expand_path(dir))
39
50
  files = []
40
51
 
41
52
  loop do
42
- file = File.expand_path('.jobim.yaml', dir)
43
-
44
- files.unshift(file) if File.exists? file
53
+ file = File.expand_path('.jobim.yml', dir)
54
+ if File.exists? file
55
+ files.unshift(file)
56
+ else
57
+ file = File.expand_path('.jobim.yaml', dir)
58
+ files.unshift(file) if File.exists? file
59
+ end
45
60
 
46
61
  break if dir.root?
47
62
 
48
63
  dir = dir.parent
49
64
  end
50
65
 
51
- files.each {|file| self.load_file(file)}
66
+ files.each { |file| load_file(file) }
52
67
 
53
- options
68
+ self
54
69
  end
55
-
56
70
  end
@@ -1,3 +1,4 @@
1
1
  module Jobim
2
- VERSION = "0.5.0"
2
+ # Applcation version number
3
+ VERSION = '0.6.0'
3
4
  end
@@ -0,0 +1 @@
1
+ ---
@@ -0,0 +1,2 @@
1
+ ---
2
+ :prefix: '/jobim'
@@ -0,0 +1,3 @@
1
+ ---
2
+ :daemonize: true
3
+ :dir: '/pub'
@@ -0,0 +1,4 @@
1
+ ---
2
+ :port: 1234
3
+ :dir: 'public_html'
4
+ :prefix: '/web_root'
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jobim::Application, fakefs: true do
4
+
5
+ describe '::run' do
6
+ before(:each) do
7
+ Jobim::Server.stub(:start!)
8
+ $stdout.stub(:write)
9
+ $stderr.stub(:write)
10
+ end
11
+
12
+ it 'exits on --help command flag' do
13
+ expect { Jobim::Application.run('--help') }.to raise_error SystemExit
14
+ end
15
+
16
+ it 'exits on --version command flags' do
17
+ expect { Jobim::Application.run('--version') }.to raise_error SystemExit
18
+ end
19
+
20
+ it 'starts the server' do
21
+ expect(Jobim::Server).to receive(:start!)
22
+ Jobim::Application.run
23
+ end
24
+
25
+ it 'catches InvalidOption and reports to stderr' do
26
+ expect($stderr).to receive(:write)
27
+ Jobim::Application.run('--foo')
28
+ end
29
+
30
+ it 'catches RuntimeError and reports to stderr' do
31
+ expect($stderr).to receive(:write)
32
+ Jobim::Server.unstub(:start!)
33
+ Jobim::Application.run('--port', '1')
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jobim::CLI, fakefs: true do
4
+
5
+ let(:cli) { Jobim::CLI.new }
6
+
7
+ describe 'options' do
8
+ it 'defaults conf_dir to Dir.pwd' do
9
+ expect(cli.options[:conf_dir]).to eql Dir.pwd
10
+ end
11
+
12
+ it 'defaults daemonize to false' do
13
+ expect(cli.options[:daemonize]).to be_false
14
+ end
15
+
16
+ it 'defaults dir to current working directory' do
17
+ expect(cli.options[:dir]).to eql Dir.pwd
18
+ end
19
+
20
+ it 'defaults host to 0.0.0.0' do
21
+ expect(cli.options[:host]).to eql '0.0.0.0'
22
+ end
23
+
24
+ it 'defaults port to 3000' do
25
+ expect(cli.options[:port]).to eql 3000
26
+ end
27
+
28
+ it 'defaults prefix to /' do
29
+ expect(cli.options[:prefix]).to eql '/'
30
+ end
31
+
32
+ it 'defaults quiet to false' do
33
+ expect(cli.options[:quiet]).to be_false
34
+ end
35
+ end
36
+
37
+ describe '#parser' do
38
+ describe '-a, --address' do
39
+ it 'sets the host address' do
40
+ cli.parse(%w[--address foo])
41
+ expect(cli.options[:host]).to eql 'foo'
42
+ end
43
+ end
44
+
45
+ describe '-c, --[no-]config' do
46
+ it 'sets the conf_dir value' do
47
+ cli.parse(%w[--no-config])
48
+ expect(cli.options[:conf_dir]).to be_false
49
+
50
+ cli.parse(%w[--config foo/bar])
51
+ expect(cli.options[:conf_dir]).to eql 'foo/bar'
52
+ end
53
+ end
54
+
55
+ describe '-d, --daemonize' do
56
+ it 'sets the daemonize flag' do
57
+ cli.parse(%w[--daemonize])
58
+ expect(cli.options[:host]).to be_true
59
+ end
60
+ end
61
+
62
+ describe '-p, --port' do
63
+ it 'takes an Integer' do
64
+ expect do
65
+ cli.parse(%w[--port foo])
66
+ end.to raise_error OptionParser::InvalidArgument
67
+ end
68
+
69
+ it 'considers 0 to be an invalid argument' do
70
+ expect do
71
+ cli.parse(%w[--port 0])
72
+ end.to raise_error OptionParser::InvalidArgument
73
+ end
74
+
75
+ it 'sets the binding port' do
76
+ cli.parse(%w[--port 3333])
77
+ expect(cli.options[:port]).to eql 3333
78
+ end
79
+ end
80
+
81
+ describe '-P, --prefix' do
82
+ it 'sets the path to mount the app under' do
83
+ cli.parse(%w[--prefix /foo])
84
+ expect(cli.options[:prefix]).to eql '/foo'
85
+ end
86
+ end
87
+
88
+ describe '-q, --quiet' do
89
+ it 'sets the quiet flag' do
90
+ cli.parse(%w[--quiet])
91
+ expect(cli.options[:quiet]).to be_true
92
+ end
93
+ end
94
+
95
+ describe '-h, --help' do
96
+ it 'displays the help message' do
97
+ expect($stdout).to receive(:write).with(cli.help)
98
+ cli.parse(%w[--help])
99
+ end
100
+ end
101
+
102
+ describe '--version' do
103
+ it 'displays the version number' do
104
+ expect($stdout).to receive(:write).with("#{Jobim::VERSION}\n")
105
+ cli.parse(%w[--version])
106
+ end
107
+ end
108
+ end
109
+
110
+ describe '#parse', fakefs: true do
111
+ it 'parses the cli option array' do
112
+ args = %w[--port 3333 --prefix /foo]
113
+ cli.parse(args)
114
+ expect(args).to eql []
115
+ end
116
+
117
+ it 'sets the Directory option to its trailing argument' do
118
+ args = %w[dir]
119
+ cli.parse(args)
120
+ expect(cli.options[:dir]).to eql '/dir'
121
+ end
122
+ end
123
+
124
+ describe '#help' do
125
+ it 'returns the help message' do
126
+ expect(cli.help).to include('Usage: jobim [OPTION]... [DIRECTORY]')
127
+ end
128
+ end
129
+
130
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jobim::Server, fakefs: true do
4
+
5
+ before(:each) do
6
+ Dir.mkdir('/web_app')
7
+ Dir.mkdir('/web_app/trail_test')
8
+ Dir.mkdir('/web_app/index_test')
9
+
10
+ File.open('/web_app/index_test/index.html', 'w') { |f| f.write(index) }
11
+ File.open('/web_app/trail_test/foo.html', 'w') { |f| f.write(index) }
12
+ File.open('/web_app/trail_test/foo', 'w') { |f| f.write(index) }
13
+ end
14
+
15
+ let(:index) { "<!DOCTYPE html>\n<html />\n" }
16
+ let(:settings) { Jobim::CLI.new.settings }
17
+
18
+ describe 'app', rack_test: true do
19
+ before(:each) { $stdout.stub(:write) }
20
+
21
+ let(:server) do
22
+ settings.dir = '/web_app'
23
+ Jobim::Server.new(settings)
24
+ end
25
+
26
+ let(:app) { server.app }
27
+
28
+ it 'returns index.html from dirs when it exists' do
29
+ get '/index_test/'
30
+ expect(last_response).to be_ok
31
+ expect(last_response.body).to eql index
32
+ end
33
+
34
+ it 'treats bare urls as directories when they are' do
35
+ get '/trail_test'
36
+ expect(last_response).to be_ok
37
+ expect(last_response.body).to include '/trail_test/foo.html'
38
+ end
39
+
40
+ it 'treats bare urls as files when they are' do
41
+ get '/trail_test/foo'
42
+ expect(last_response).to be_ok
43
+ expect(last_response.body).to eql index
44
+ end
45
+ end
46
+
47
+ describe 'server' do
48
+ let(:server) do
49
+ settings.daemonize = true
50
+ Jobim::Server.new(settings)
51
+ end
52
+
53
+ it 'sets server.pid_file if :daemonize is true' do
54
+ expect(server.server.pid_file).to eql('jobim.pid')
55
+ end
56
+
57
+ it 'sets server.log_file if :daemonize is true' do
58
+ expect(server.server.log_file).to eql('jobim.log')
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jobim::Settings, fakefs: true do
4
+
5
+ before(:each) do
6
+ unless example.metadata[:no_conf]
7
+ Dir.mkdir('/home')
8
+ Dir.mkdir('/home/jobim')
9
+ Dir.mkdir('/home/jobim/public_html')
10
+ Dir.mkdir('/home/jobim/projects')
11
+
12
+ Dir.chdir('/home/jobim/projects')
13
+
14
+ file = RealFile.expand_path(__FILE__)
15
+ config_dir = RealFile.expand_path('../configs', file)
16
+
17
+ r_cfg = RealFile.read(RealFile.expand_path('root_conf.yml', config_dir))
18
+ u_cfg = RealFile.read(RealFile.expand_path('user_conf.yml', config_dir))
19
+ l_cfg = RealFile.read(RealFile.expand_path('local_conf.yml', config_dir))
20
+ e_cfg = RealFile.read(RealFile.expand_path('empty_conf.yml', config_dir))
21
+
22
+ File.open('/.jobim.yml', 'w') { |f| f.write r_cfg }
23
+ File.open('/home/.jobim.yml', 'w') { |f| f.write e_cfg }
24
+ File.open('/home/jobim/.jobim.yaml', 'w') { |f| f.write u_cfg }
25
+ File.open('/home/jobim/projects/.jobim.yaml', 'w') do |f|
26
+ f.write l_cfg
27
+ end
28
+ end
29
+ end
30
+
31
+ let(:settings) do
32
+ cli = Jobim::CLI.new
33
+ cli.parse(%w[--no-config])
34
+
35
+ settings = cli.settings
36
+ settings.conf_dir = Dir.pwd
37
+ settings
38
+ end
39
+
40
+ describe '#initialize' do
41
+
42
+ end
43
+
44
+ describe '#load_file' do
45
+ it 'loads config data into settings' do
46
+ settings.load_file('/.jobim.yml')
47
+ expect(settings.daemonize).to be_true
48
+ end
49
+
50
+ it 'only changes configured options' do
51
+ settings.load_file('/.jobim.yml')
52
+ expect(settings.port).to eql 3000
53
+ end
54
+
55
+ it 'expands directories relative to the config file location' do
56
+ settings.load_file('/home/jobim/.jobim.yaml')
57
+ expect(settings.dir).to eql '/home/jobim/public_html'
58
+ end
59
+
60
+ it 'overrides only specified options' do
61
+ settings.load_file('/home/jobim/.jobim.yaml')
62
+ expect(settings.quiet).to be_false
63
+ end
64
+
65
+ it 'handles empty configuration files' do
66
+ expect { settings.load_file('/home/.jobim.yml') }.to_not raise_error
67
+ end
68
+ end
69
+
70
+ describe '#load' do
71
+ before(:each) { settings.load }
72
+
73
+ it 'loads all config files from CWD to root by default' do
74
+ expect(settings.daemonize).to be_true
75
+ expect(settings.port).to eql 1234
76
+ expect(settings.dir).to eql '/home/jobim/public_html'
77
+ end
78
+
79
+ it 'overrides previous directory options with current ones' do
80
+ expect(settings.dir).to eql '/home/jobim/public_html'
81
+ end
82
+
83
+ it 'will check for yaml files only if there is no yml file' do
84
+ expect(settings.prefix).to eql '/jobim'
85
+ end
86
+
87
+ it 'can handle absolute directories' do
88
+ expect(settings.daemonize).to be_true
89
+ expect(settings.port).to eql 1234
90
+ expect(settings.dir).to eql '/home/jobim/public_html'
91
+ end
92
+
93
+ it 'can handle relative directories' do
94
+ settings.load('../')
95
+ expect(settings.prefix).to eql '/web_root'
96
+ expect(settings.port).to eql 1234
97
+ end
98
+ end
99
+
100
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jobim do
4
+
5
+ it 'has a version number' do
6
+ expect(Jobim::VERSION).to_not be_nil
7
+ end
8
+
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
4
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
5
+ require 'jobim'
6
+
7
+ require 'fakefs/spec_helpers'
8
+ require 'rack/test'
9
+
10
+ RSpec.configure do |config|
11
+ config.include FakeFS::SpecHelpers, fakefs: true
12
+ config.include Rack::Test::Methods, rack_test: true
13
+ end
metadata CHANGED
@@ -1,111 +1,167 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jobim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zachary Elliott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-19 00:00:00.000000000 Z
11
+ date: 2014-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.1'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: yard
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
- - - ~>
73
+ - - "~>"
46
74
  - !ruby/object:Gem::Version
47
75
  version: '0.8'
48
76
  type: :development
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
- - - ~>
80
+ - - "~>"
53
81
  - !ruby/object:Gem::Version
54
82
  version: '0.8'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: redcarpet
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
- - - ~>
87
+ - - "~>"
60
88
  - !ruby/object:Gem::Version
61
89
  version: '3.0'
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
- - - ~>
94
+ - - "~>"
67
95
  - !ruby/object:Gem::Version
68
96
  version: '3.0'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: github-markup
71
99
  requirement: !ruby/object:Gem::Requirement
72
100
  requirements:
73
- - - ~>
101
+ - - "~>"
74
102
  - !ruby/object:Gem::Version
75
103
  version: '0.7'
76
104
  type: :development
77
105
  prerelease: false
78
106
  version_requirements: !ruby/object:Gem::Requirement
79
107
  requirements:
80
- - - ~>
108
+ - - "~>"
81
109
  - !ruby/object:Gem::Version
82
110
  version: '0.7'
111
+ - !ruby/object:Gem::Dependency
112
+ name: fakefs
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.5'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rack-test
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
83
139
  - !ruby/object:Gem::Dependency
84
140
  name: thin
85
141
  requirement: !ruby/object:Gem::Requirement
86
142
  requirements:
87
- - - ~>
143
+ - - "~>"
88
144
  - !ruby/object:Gem::Version
89
145
  version: '1.5'
90
146
  type: :runtime
91
147
  prerelease: false
92
148
  version_requirements: !ruby/object:Gem::Requirement
93
149
  requirements:
94
- - - ~>
150
+ - - "~>"
95
151
  - !ruby/object:Gem::Version
96
152
  version: '1.5'
97
153
  - !ruby/object:Gem::Dependency
98
154
  name: rack-rewrite
99
155
  requirement: !ruby/object:Gem::Requirement
100
156
  requirements:
101
- - - ~>
157
+ - - "~>"
102
158
  - !ruby/object:Gem::Version
103
159
  version: '1.2'
104
160
  type: :runtime
105
161
  prerelease: false
106
162
  version_requirements: !ruby/object:Gem::Requirement
107
163
  requirements:
108
- - - ~>
164
+ - - "~>"
109
165
  - !ruby/object:Gem::Version
110
166
  version: '1.2'
111
167
  description: Popup HTTP Server for serving static content.
@@ -116,7 +172,10 @@ executables:
116
172
  extensions: []
117
173
  extra_rdoc_files: []
118
174
  files:
119
- - .gitignore
175
+ - ".gitignore"
176
+ - ".rspec"
177
+ - ".rubocop.yml"
178
+ - ".travis.yml"
120
179
  - Gemfile
121
180
  - LICENSE
122
181
  - README.md
@@ -124,10 +183,21 @@ files:
124
183
  - bin/jobim
125
184
  - jobim.gemspec
126
185
  - lib/jobim.rb
186
+ - lib/jobim/application.rb
127
187
  - lib/jobim/cli.rb
128
188
  - lib/jobim/server.rb
129
189
  - lib/jobim/settings.rb
130
190
  - lib/jobim/version.rb
191
+ - spec/configs/empty_conf.yml
192
+ - spec/configs/local_conf.yml
193
+ - spec/configs/root_conf.yml
194
+ - spec/configs/user_conf.yml
195
+ - spec/jobim_application_spec.rb
196
+ - spec/jobim_cli_spec.rb
197
+ - spec/jobim_server_spec.rb
198
+ - spec/jobim_settings_spec.rb
199
+ - spec/jobim_spec.rb
200
+ - spec/spec_helper.rb
131
201
  homepage: https://github.com/zellio/jobim
132
202
  licenses:
133
203
  - MIT
@@ -138,19 +208,29 @@ require_paths:
138
208
  - lib
139
209
  required_ruby_version: !ruby/object:Gem::Requirement
140
210
  requirements:
141
- - - '>='
211
+ - - ">="
142
212
  - !ruby/object:Gem::Version
143
213
  version: '0'
144
214
  required_rubygems_version: !ruby/object:Gem::Requirement
145
215
  requirements:
146
- - - '>='
216
+ - - ">="
147
217
  - !ruby/object:Gem::Version
148
218
  version: '0'
149
219
  requirements: []
150
220
  rubyforge_project:
151
- rubygems_version: 2.1.5
221
+ rubygems_version: 2.2.2
152
222
  signing_key:
153
223
  specification_version: 4
154
224
  summary: Popup HTTP Server
155
- test_files: []
225
+ test_files:
226
+ - spec/configs/empty_conf.yml
227
+ - spec/configs/local_conf.yml
228
+ - spec/configs/root_conf.yml
229
+ - spec/configs/user_conf.yml
230
+ - spec/jobim_application_spec.rb
231
+ - spec/jobim_cli_spec.rb
232
+ - spec/jobim_server_spec.rb
233
+ - spec/jobim_settings_spec.rb
234
+ - spec/jobim_spec.rb
235
+ - spec/spec_helper.rb
156
236
  has_rdoc: