summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/dashing.rb168
-rw-r--r--lib/dashing/app.rb167
-rw-r--r--test/app_test.rb307
3 files changed, 323 insertions, 319 deletions
diff --git a/lib/dashing.rb b/lib/dashing.rb
index 54579dd..855aa36 100644
--- a/lib/dashing.rb
+++ b/lib/dashing.rb
@@ -1,170 +1,6 @@
-require 'sinatra'
-require 'sprockets'
-require 'sinatra/content_for'
-require 'rufus/scheduler'
-require 'coffee-script'
-require 'sass'
-require 'json'
-require 'yaml'
-
require 'dashing/cli'
require 'dashing/downloader'
+require 'dashing/app'
-SCHEDULER = Rufus::Scheduler.new
-
-set :root, Dir.pwd
-
-set :sprockets, Sprockets::Environment.new(settings.root)
-set :assets_prefix, '/assets'
-set :digest_assets, false
-['assets/javascripts', 'assets/stylesheets', 'assets/fonts', 'assets/images', 'widgets', File.expand_path('../../javascripts', __FILE__)]. each do |path|
- settings.sprockets.append_path path
-end
-
-set server: 'thin', connections: [], history_file: 'history.yml'
-
-# Persist history in tmp file at exit
-at_exit do
- File.open(settings.history_file, 'w') do |f|
- f.puts settings.history.to_yaml
- end
-end
-
-if File.exists?(settings.history_file)
- set history: YAML.load_file(settings.history_file)
-else
- set history: {}
-end
-
-set :public_folder, File.join(settings.root, 'public')
-set :views, File.join(settings.root, 'dashboards')
-set :default_dashboard, nil
-set :auth_token, nil
-
-helpers Sinatra::ContentFor
-helpers do
- def protected!
- # override with auth logic
- end
-end
-
-get '/events', provides: 'text/event-stream' do
- protected!
- response.headers['X-Accel-Buffering'] = 'no' # Disable buffering for nginx
- stream :keep_open do |out|
- settings.connections << out
- out << latest_events
- out.callback { settings.connections.delete(out) }
- end
-end
-
-get '/' do
- protected!
- begin
- redirect "/" + (settings.default_dashboard || first_dashboard).to_s
- rescue NoMethodError => e
- raise Exception.new("There are no dashboards in your dashboard directory.")
- end
-end
-
-get '/:dashboard' do
- protected!
- tilt_html_engines.each do |suffix, _|
- file = File.join(settings.views, "#{params[:dashboard]}.#{suffix}")
- return render(suffix.to_sym, params[:dashboard].to_sym) if File.exist? file
- end
-
- halt 404
-end
-
-get '/views/:widget?.html' do
- protected!
- tilt_html_engines.each do |suffix, engines|
- file = File.join(settings.root, "widgets", params[:widget], "#{params[:widget]}.#{suffix}")
- return engines.first.new(file).render if File.exist? file
- end
-end
-
-post '/dashboards/:id' do
- request.body.rewind
- body = JSON.parse(request.body.read)
- body['dashboard'] ||= params['id']
- auth_token = body.delete("auth_token")
- if !settings.auth_token || settings.auth_token == auth_token
- send_event(params['id'], body, 'dashboards')
- 204 # response without entity body
- else
- status 401
- "Invalid API key\n"
- end
+module Dashing
end
-
-post '/widgets/:id' do
- request.body.rewind
- body = JSON.parse(request.body.read)
- auth_token = body.delete("auth_token")
- if !settings.auth_token || settings.auth_token == auth_token
- send_event(params['id'], body)
- 204 # response without entity body
- else
- status 401
- "Invalid API key\n"
- end
-end
-
-not_found do
- send_file File.join(settings.public_folder, '404.html')
-end
-
-def development?
- ENV['RACK_ENV'] == 'development'
-end
-
-def production?
- ENV['RACK_ENV'] == 'production'
-end
-
-def send_event(id, body, target=nil)
- body[:id] = id
- body[:updatedAt] ||= Time.now.to_i
- event = format_event(body.to_json, target)
- Sinatra::Application.settings.history[id] = event unless target == 'dashboards'
- Sinatra::Application.settings.connections.each { |out| out << event }
-end
-
-def format_event(body, name=nil)
- str = ""
- str << "event: #{name}\n" if name
- str << "data: #{body}\n\n"
-end
-
-def latest_events
- settings.history.inject("") do |str, (id, body)|
- str << body
- end
-end
-
-def first_dashboard
- files = Dir[File.join(settings.views, '*')].collect { |f| File.basename(f, '.*') }
- files -= ['layout']
- files.sort.first
-end
-
-def tilt_html_engines
- Tilt.mappings.select do |_, engines|
- default_mime_type = engines.first.default_mime_type
- default_mime_type.nil? || default_mime_type == 'text/html'
- end
-end
-
-settings_file = File.join(settings.root, 'config/settings.rb')
-if (File.exists?(settings_file))
- require settings_file
-end
-
-Dir[File.join(settings.root, 'lib', '**', '*.rb')].each {|file| require file }
-{}.to_json # Forces your json codec to initialize (in the event that it is lazily loaded). Does this before job threads start.
-
-job_path = ENV["JOB_PATH"] || 'jobs'
-files = Dir[File.join(settings.root, job_path, '**', '/*.rb')]
-files.each { |job| require(job) }
diff --git a/lib/dashing/app.rb b/lib/dashing/app.rb
new file mode 100644
index 0000000..7c4f25a
--- /dev/null
+++ b/lib/dashing/app.rb
@@ -0,0 +1,167 @@
+require 'sinatra'
+require 'sprockets'
+require 'sinatra/content_for'
+require 'rufus/scheduler'
+require 'coffee-script'
+require 'sass'
+require 'json'
+require 'yaml'
+
+SCHEDULER = Rufus::Scheduler.new
+
+set :root, Dir.pwd
+
+set :sprockets, Sprockets::Environment.new(settings.root)
+set :assets_prefix, '/assets'
+set :digest_assets, false
+['assets/javascripts', 'assets/stylesheets', 'assets/fonts', 'assets/images', 'widgets', File.expand_path('../../javascripts', __FILE__)]. each do |path|
+ settings.sprockets.append_path path
+end
+
+set server: 'thin', connections: [], history_file: 'history.yml'
+
+# Persist history in tmp file at exit
+at_exit do
+ File.open(settings.history_file, 'w') do |f|
+ f.puts settings.history.to_yaml
+ end
+end
+
+if File.exists?(settings.history_file)
+ set history: YAML.load_file(settings.history_file)
+else
+ set history: {}
+end
+
+set :public_folder, File.join(settings.root, 'public')
+set :views, File.join(settings.root, 'dashboards')
+set :default_dashboard, nil
+set :auth_token, nil
+
+helpers Sinatra::ContentFor
+helpers do
+ def protected!
+ # override with auth logic
+ end
+end
+
+get '/events', provides: 'text/event-stream' do
+ protected!
+ response.headers['X-Accel-Buffering'] = 'no' # Disable buffering for nginx
+ stream :keep_open do |out|
+ settings.connections << out
+ out << latest_events
+ out.callback { settings.connections.delete(out) }
+ end
+end
+
+get '/' do
+ protected!
+ begin
+ redirect "/" + (settings.default_dashboard || first_dashboard).to_s
+ rescue NoMethodError => e
+ raise Exception.new("There are no dashboards in your dashboard directory.")
+ end
+end
+
+get '/:dashboard' do
+ protected!
+ tilt_html_engines.each do |suffix, _|
+ file = File.join(settings.views, "#{params[:dashboard]}.#{suffix}")
+ return render(suffix.to_sym, params[:dashboard].to_sym) if File.exist? file
+ end
+
+ halt 404
+end
+
+get '/views/:widget?.html' do
+ protected!
+ tilt_html_engines.each do |suffix, engines|
+ file = File.join(settings.root, "widgets", params[:widget], "#{params[:widget]}.#{suffix}")
+ return engines.first.new(file).render if File.exist? file
+ end
+end
+
+post '/dashboards/:id' do
+ request.body.rewind
+ body = JSON.parse(request.body.read)
+ body['dashboard'] ||= params['id']
+ auth_token = body.delete("auth_token")
+ if !settings.auth_token || settings.auth_token == auth_token
+ send_event(params['id'], body, 'dashboards')
+ 204 # response without entity body
+ else
+ status 401
+ "Invalid API key\n"
+ end
+end
+
+post '/widgets/:id' do
+ request.body.rewind
+ body = JSON.parse(request.body.read)
+ auth_token = body.delete("auth_token")
+ if !settings.auth_token || settings.auth_token == auth_token
+ send_event(params['id'], body)
+ 204 # response without entity body
+ else
+ status 401
+ "Invalid API key\n"
+ end
+end
+
+not_found do
+ send_file File.join(settings.public_folder, '404.html')
+end
+
+def development?
+ ENV['RACK_ENV'] == 'development'
+end
+
+def production?
+ ENV['RACK_ENV'] == 'production'
+end
+
+def send_event(id, body, target=nil)
+ body[:id] = id
+ body[:updatedAt] ||= Time.now.to_i
+ event = format_event(body.to_json, target)
+ Sinatra::Application.settings.history[id] = event unless target == 'dashboards'
+ Sinatra::Application.settings.connections.each { |out| out << event }
+end
+
+def format_event(body, name=nil)
+ str = ""
+ str << "event: #{name}\n" if name
+ str << "data: #{body}\n\n"
+end
+
+def latest_events
+ settings.history.inject("") do |str, (id, body)|
+ str << body
+ end
+end
+
+def first_dashboard
+ files = Dir[File.join(settings.views, '*')].collect { |f| File.basename(f, '.*') }
+ files -= ['layout']
+ files.sort.first
+end
+
+def tilt_html_engines
+ Tilt.mappings.select do |_, engines|
+ default_mime_type = engines.first.default_mime_type
+ default_mime_type.nil? || default_mime_type == 'text/html'
+ end
+end
+
+settings_file = File.join(settings.root, 'config/settings.rb')
+if (File.exists?(settings_file))
+ require settings_file
+end
+
+Dir[File.join(settings.root, 'lib', '**', '*.rb')].each {|file| require file }
+{}.to_json # Forces your json codec to initialize (in the event that it is lazily loaded). Does this before job threads start.
+
+job_path = ENV["JOB_PATH"] || 'jobs'
+files = Dir[File.join(settings.root, job_path, '**', '/*.rb')]
+files.each { |job| require(job) }
diff --git a/test/app_test.rb b/test/app_test.rb
index bf3bbb1..dbb7cb5 100644
--- a/test/app_test.rb
+++ b/test/app_test.rb
@@ -1,153 +1,154 @@
-# require 'test_helper'
-# require 'haml'
-
-# class AppTest < Dashing::Test
-# def setup
-# @connection = []
-# Sinatra::Application.settings.history_file = File.join(Dir.tmpdir, 'history.yml')
-# Sinatra::Application.settings.connections = [@connection]
-# Sinatra::Application.settings.auth_token = nil
-# Sinatra::Application.settings.default_dashboard = nil
-# end
-
-# def test_post_widgets_without_auth_token
-# post '/widgets/some_widget', JSON.generate({value: 6})
-# assert_equal 204, last_response.status
-
-# assert_equal 1, @connection.length
-# data = parse_data @connection[0]
-# assert_equal 6, data['value']
-# assert_equal 'some_widget', data['id']
-# assert data['updatedAt']
-# end
-
-# def test_post_widgets_with_invalid_auth_token
-# Sinatra::Application.settings.auth_token = 'sekrit'
-# post '/widgets/some_widget', JSON.generate({value: 9})
-# assert_equal 401, last_response.status
-# end
-
-# def test_post_widgets_with_valid_auth_token
-# Sinatra::Application.settings.auth_token = 'sekrit'
-# post '/widgets/some_widget', JSON.generate({value: 9, auth_token: 'sekrit'})
-# assert_equal 204, last_response.status
-# end
-
-# def test_get_events
-# post '/widgets/some_widget', JSON.generate({value: 8})
-# assert_equal 204, last_response.status
-
-# get '/events'
-# assert_equal 200, last_response.status
-# assert_equal 8, parse_data(@connection[0])['value']
-# end
-
-# def test_dashboard_events
-# post '/dashboards/my_super_sweet_dashboard', JSON.generate({event: 'reload'})
-# assert_equal 204, last_response.status
-
-# get '/events'
-# assert_equal 200, last_response.status
-# assert_equal 'dashboards', parse_event(@connection[0])
-# assert_equal 'reload', parse_data(@connection[0])['event']
-# end
-
-# def test_redirect_to_default_dashboard
-# with_generated_project do
-# Sinatra::Application.settings.default_dashboard = 'test1'
-# get '/'
-# assert_equal 302, last_response.status
-# assert_equal 'http://example.org/test1', last_response.location
-# end
-# end
-
-# def test_redirect_to_first_dashboard
-# with_generated_project do
-# get '/'
-# assert_equal 302, last_response.status
-# assert_equal 'http://example.org/sample', last_response.location
-# end
-# end
-
-# def test_redirect_to_first_dashboard_without_erb
-# with_generated_project do |dir|
-# FileUtils.touch(File.join(dir, "dashboards/htmltest.html"))
-# get '/'
-# assert_equal 302, last_response.status
-# assert_equal 'http://example.org/htmltest', last_response.location
-# end
-# end
-
-# def test_get_dashboard
-# with_generated_project do
-# get '/sampletv'
-# assert_equal 200, last_response.status
-# assert_includes last_response.body, 'class="gridster"'
-# assert_includes last_response.body, "DOCTYPE"
-# end
-# end
-
-# def test_page_title_set_correctly
-# with_generated_project do
-# get '/sampletv'
-# assert_includes last_response.body, '<title>1080p dashboard</title>'
-# end
-# end
-
-# def test_get_haml_dashboard
-# with_generated_project do |dir|
-# File.write(File.join(dir, 'dashboards/hamltest.haml'), '.gridster')
-# get '/hamltest'
-# assert_equal 200, last_response.status
-# assert_includes last_response.body, "class='gridster'"
-# end
-# end
-
-# def test_get_haml_widget
-# with_generated_project do |dir|
-# File.write(File.join(dir, 'widgets/clock/clock.haml'), '%h1 haml')
-# File.unlink(File.join(dir, 'widgets/clock/clock.html'))
-# get '/views/clock.html'
-# assert_equal 200, last_response.status
-# assert_includes last_response.body, '<h1>haml</h1>'
-# end
-# end
-
-# def test_get_nonexistent_dashboard
-# with_generated_project do
-# get '/nodashboard'
-# assert_equal 404, last_response.status
-# end
-# end
-
-# def test_get_widget
-# with_generated_project do
-# get '/views/meter.html'
-# assert_equal 200, last_response.status
-# assert_includes last_response.body, 'class="meter"'
-# end
-# end
-
-# def with_generated_project
-# temp do |dir|
-# cli = Dashing::CLI.new
-# silent { cli.new 'new_project' }
-
-# Sinatra::Application.settings.views = File.join(dir, 'new_project/dashboards')
-# Sinatra::Application.settings.root = File.join(dir, 'new_project')
-# yield Sinatra::Application.settings.root
-# end
-# end
-
-# def app
-# Sinatra::Application
-# end
-
-# def parse_data(string)
-# JSON.parse string[/data: (.+)/, 1]
-# end
-
-# def parse_event(string)
-# string[/event: (.+)/, 1]
-# end
-# end
+require 'test_helper'
+require 'haml'
+
+class AppTest < Dashing::Test
+ def setup
+ @connection = []
+ Sinatra::Application.settings.history_file = File.join(Dir.tmpdir, 'history.yml')
+ Sinatra::Application.settings.connections = [@connection]
+ Sinatra::Application.settings.auth_token = nil
+ Sinatra::Application.settings.default_dashboard = nil
+ end
+
+ def test_post_widgets_without_auth_token
+ post '/widgets/some_widget', JSON.generate({value: 6})
+ assert_equal 204, last_response.status
+
+ assert_equal 1, @connection.length
+ data = parse_data @connection[0]
+ assert_equal 6, data['value']
+ assert_equal 'some_widget', data['id']
+ assert data['updatedAt']
+ end
+
+ def test_post_widgets_with_invalid_auth_token
+ Sinatra::Application.settings.auth_token = 'sekrit'
+ post '/widgets/some_widget', JSON.generate({value: 9})
+ assert_equal 401, last_response.status
+ end
+
+ def test_post_widgets_with_valid_auth_token
+ Sinatra::Application.settings.auth_token = 'sekrit'
+ post '/widgets/some_widget', JSON.generate({value: 9, auth_token: 'sekrit'})
+ assert_equal 204, last_response.status
+ end
+
+ def test_get_events
+ post '/widgets/some_widget', JSON.generate({value: 8})
+ assert_equal 204, last_response.status
+
+ get '/events'
+ assert_equal 200, last_response.status
+ assert_equal 8, parse_data(@connection[0])['value']
+ end
+
+ def test_dashboard_events
+ post '/dashboards/my_super_sweet_dashboard', JSON.generate({event: 'reload'})
+ assert_equal 204, last_response.status
+
+ get '/events'
+ assert_equal 200, last_response.status
+ assert_equal 'dashboards', parse_event(@connection[0])
+ assert_equal 'reload', parse_data(@connection[0])['event']
+ end
+
+ def test_redirect_to_default_dashboard
+ with_generated_project do
+ Sinatra::Application.settings.default_dashboard = 'test1'
+ get '/'
+ assert_equal 302, last_response.status
+ assert_equal 'http://example.org/test1', last_response.location
+ end
+ end
+
+ def test_redirect_to_first_dashboard
+ with_generated_project do
+ get '/'
+ assert_equal 302, last_response.status
+ assert_equal 'http://example.org/sample', last_response.location
+ end
+ end
+
+ def test_redirect_to_first_dashboard_without_erb
+ with_generated_project do |dir|
+ FileUtils.touch(File.join(dir, "dashboards/htmltest.html"))
+ get '/'
+ assert_equal 302, last_response.status
+ assert_equal 'http://example.org/htmltest', last_response.location
+ end
+ end
+
+ def test_get_dashboard
+ with_generated_project do
+ get '/sampletv'
+ assert_equal 200, last_response.status
+ assert_includes last_response.body, 'class="gridster"'
+ assert_includes last_response.body, "DOCTYPE"
+ end
+ end
+
+ def test_page_title_set_correctly
+ with_generated_project do
+ get '/sampletv'
+ assert_includes last_response.body, '<title>1080p dashboard</title>'
+ end
+ end
+
+ def test_get_haml_dashboard
+ with_generated_project do |dir|
+ File.write(File.join(dir, 'dashboards/hamltest.haml'), '.gridster')
+ get '/hamltest'
+ assert_equal 200, last_response.status
+ assert_includes last_response.body, "class='gridster'"
+ end
+ end
+
+ def test_get_haml_widget
+ with_generated_project do |dir|
+ File.write(File.join(dir, 'widgets/clock/clock.haml'), '%h1 haml')
+ File.unlink(File.join(dir, 'widgets/clock/clock.html'))
+ get '/views/clock.html'
+ assert_equal 200, last_response.status
+ assert_includes last_response.body, '<h1>haml</h1>'
+ end
+ end
+
+ def test_get_nonexistent_dashboard
+ with_generated_project do
+ get '/nodashboard'
+ assert_equal 404, last_response.status
+ end
+ end
+
+ def test_get_widget
+ with_generated_project do
+ get '/views/meter.html'
+ assert_equal 200, last_response.status
+ assert_includes last_response.body, 'class="meter"'
+ end
+ end
+
+ def with_generated_project
+ temp do |dir|
+ cli = Dashing::CLI.new
+ cli.stubs(:source_paths).returns([File.expand_path('../../templates', __FILE__)])
+ silent { cli.new 'new_project' }
+
+ Sinatra::Application.settings.views = File.join(dir, 'new_project/dashboards')
+ Sinatra::Application.settings.root = File.join(dir, 'new_project')
+ yield Sinatra::Application.settings.root
+ end
+ end
+
+ def app
+ Sinatra::Application
+ end
+
+ def parse_data(string)
+ JSON.parse string[/data: (.+)/, 1]
+ end
+
+ def parse_event(string)
+ string[/event: (.+)/, 1]
+ end
+end