gusto 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/Spec.coffee ADDED
@@ -0,0 +1,62 @@
1
+ #= require Spec/Util
2
+ #= require Spec/Test
3
+ #= require Spec/Suite
4
+ #= require Spec/Report
5
+ #= require Spec/ObjectDSL
6
+ #= require Spec/DSL
7
+ #= require Spec/Matchers
8
+ #= require Spec/MethodStub
9
+ #= require Spec/MethodStub/PossibleCall
10
+ #= require Spec/DelayedExpectation
11
+ #= require Spec/MockObject
12
+
13
+ # Seaweed Coffeescript spec framework
14
+
15
+ window.Spec ||= {}
16
+
17
+ class window.Spec.ExpectationError extends Error
18
+ constructor: (@message) ->
19
+
20
+ class window.Spec.PendingError extends Error
21
+ constructor: (@message) ->
22
+ @status = Spec.Report.Pending
23
+
24
+ Spec.Util.extend window.Spec,
25
+ environmentExtended: false
26
+ suites: []
27
+ root: window
28
+
29
+ # Executes a test case
30
+ describe: (title, definition) ->
31
+ @extendEnvironment() unless @environmentExtended
32
+ suite = new Spec.Suite(title, definition)
33
+ suite.load window
34
+ @suites.push suite
35
+
36
+ # Extends a class or instance with object DSL
37
+ extend: (objects...) ->
38
+ for object in objects
39
+ Spec.Util.extend object, Spec.ObjectDSL
40
+ Spec.Util.extend object.prototype, Spec.ObjectDSL if object.prototype
41
+
42
+ # Extends the environment with test methods
43
+ extendEnvironment: ->
44
+ @environmentExtended = true
45
+
46
+ Spec.Util.extend(@root,
47
+ Spec.DSL,
48
+ Spec.Matchers
49
+ )
50
+
51
+ @extend(
52
+ Array,
53
+ Boolean,
54
+ Date,
55
+ Function,
56
+ Number,
57
+ RegExp,
58
+ String,
59
+ Element,
60
+ jQuery,
61
+ Spec.MockObject
62
+ )
@@ -0,0 +1,40 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ module Gusto
5
+ class Runner
6
+ def load_gusto
7
+ require File.join(File.dirname(__FILE__), '..', 'gusto')
8
+ Gusto.load_configuration
9
+ Gusto.port = @port
10
+ end
11
+
12
+ def load_gusto_version
13
+ require File.join(File.dirname(__FILE__), '..', 'gusto', 'version')
14
+ end
15
+
16
+ def initialize mode, options={}, parser=nil
17
+ @port = options[:port] || 4567
18
+
19
+ if options[:version]
20
+ load_gusto_version
21
+ puts "Gusto Version #{Gusto::VERSION}"
22
+ else
23
+ case mode
24
+ when 's', 'server'
25
+ puts "Starting gusto server at http://127.0.0.1:#{@port}/"
26
+ load_gusto
27
+ Gusto.server
28
+ when 'c', 'cli'
29
+ load_gusto
30
+ Gusto.cli
31
+ when 'a', 'auto'
32
+ load_gusto
33
+ Gusto.autotest
34
+ else
35
+ puts parser || "Unknown mode “#{mode}”"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'sinatra'
4
+ require 'sass'
5
+ require 'slim'
6
+ require 'coffee-script'
7
+ require File.expand_path(File.dirname(__FILE__) + '/../gusto')
8
+
9
+ module Gusto
10
+ class Server < Sinatra::Application
11
+ # Configure paths
12
+ set :public_folder, ROOT + '/public'
13
+ set :views, ROOT + '/views'
14
+
15
+ # Configure slim for prettier code formatting
16
+ Slim::Engine.set_default_options :pretty => true
17
+
18
+ # Hide redundant log messages
19
+ disable :logging
20
+
21
+ # Processes request for page index
22
+ get "/" do
23
+ # Fetch list of all specification files in specs path
24
+ @scripts = []
25
+ Gusto.specs.each do |path|
26
+ Dir["#{Gusto::PROJECT_ROOT}/#{path}/**/*spec.coffee"].each do |file|
27
+ @scripts << $1 if file.match Regexp.new("^#{Regexp.escape Gusto::PROJECT_ROOT}\\/#{Regexp.escape path}\\/(.*).coffee$")
28
+ end
29
+ end
30
+
31
+ render :slim, :index
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Gusto
2
+ VERSION = "1.0.0.beta2"
3
+ end
data/lib/gusto.rb ADDED
@@ -0,0 +1,162 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'rubygems'
4
+ require 'sprockets'
5
+ require 'net/http'
6
+ require 'rack'
7
+ require 'json'
8
+ require File.join(File.dirname(__FILE__), 'gusto', 'version')
9
+
10
+ module Gusto
11
+ ROOT = File.expand_path File.join(File.dirname(__FILE__), '..')
12
+ PROJECT_ROOT = File.expand_path "."
13
+
14
+ CONFIG_PATHS = [
15
+ File.join(PROJECT_ROOT, 'gusto.json'),
16
+ File.join(PROJECT_ROOT, 'config', 'gusto.json')
17
+ ]
18
+
19
+ @configuration = {}
20
+
21
+ class << self
22
+
23
+ def load_configuration
24
+ # Set configuration defaults
25
+ @configuration['port'] = 4567
26
+ @configuration['lib_paths'] = %w(lib)
27
+ @configuration['spec_paths'] = %w(spec)
28
+
29
+ # Load custom configuration file
30
+ CONFIG_PATHS.each do |path|
31
+ if File.exists? path
32
+ @configuration.merge! JSON.parse(File.read(path))
33
+ puts "Loaded configuration from “#{path}”"
34
+ end
35
+ end
36
+ end
37
+
38
+ def port
39
+ @configuration['port']
40
+ end
41
+
42
+ def port= value
43
+ @configuration['port'] = value
44
+ end
45
+
46
+ def root_url
47
+ "http://localhost:#{port}/"
48
+ end
49
+
50
+ def libs
51
+ @configuration['lib_paths']
52
+ end
53
+
54
+ def specs
55
+ @configuration['spec_paths']
56
+ end
57
+
58
+ def all_paths
59
+ libs + specs
60
+ end
61
+
62
+ def server
63
+ trap_sigint
64
+ spawn_server
65
+ Process.waitall
66
+ end
67
+
68
+ def cli
69
+ trap_sigint
70
+ spawn_server
71
+ result = run_suite
72
+ shut_down(result ? 0 : 1)
73
+ end
74
+
75
+ def autotest
76
+ trap_sigint
77
+ spawn_server
78
+ run_suite
79
+ watch_for_changes
80
+ Process.waitall
81
+ end
82
+
83
+ # Prepares a Sprockets::Environment object to serve coffeescript assets
84
+ def sprockets_environment
85
+ @environment ||= Sprockets::Environment.new.tap do |environment|
86
+ environment.append_path File.join(ROOT, 'lib')
87
+ environment.append_path File.join(ROOT, 'assets')
88
+ all_paths.each do |path|
89
+ environment.append_path path
90
+ end
91
+ end
92
+ end
93
+
94
+ def start_server
95
+ app = Rack::Builder.app do
96
+ map '/assets' do
97
+ run Gusto::sprockets_environment
98
+ end
99
+
100
+ map '/' do
101
+ run Gusto::Server
102
+ end
103
+ end
104
+ Rack::Handler.default.run app, :Port => port
105
+ end
106
+
107
+ def spawn_server
108
+ @server = Process.fork{ $0 = 'gusto server'; start_server }
109
+ wait_for_server_at(root_url)
110
+ end
111
+
112
+ def run_suite
113
+ if @browser
114
+ @browser.navigate.refresh
115
+ else
116
+ require 'selenium/webdriver'
117
+ @browser = Selenium::WebDriver.for :firefox, profile: Selenium::WebDriver::Firefox::Profile.new
118
+ @browser.get "#{root_url}#terminal"
119
+ end
120
+ result = @browser[css: '.results'].text
121
+ puts result
122
+ !!result.match('passed, 0 failed')
123
+ end
124
+
125
+ def watch_for_changes
126
+ require 'listen'
127
+
128
+ @listener = Listen.to(PROJECT_ROOT)
129
+
130
+ # Match .coffee files in any project paths
131
+ @listener.filter Regexp.new('^(' + all_paths.map{ |s| Regexp.escape s}.join('|') + ')\/.*\.coffee$')
132
+
133
+ @listener.change { run_suite }
134
+ @listener.start false
135
+ end
136
+
137
+ def shut_down(status=0)
138
+ @listener.stop if @listener
139
+ @browser.close if @browser
140
+ Process.kill 'TERM', @server if @server
141
+ exit status
142
+ end
143
+
144
+ def trap_sigint
145
+ trap('SIGINT') do
146
+ puts "Shutting down..."
147
+ shut_down
148
+ end
149
+ end
150
+
151
+ private
152
+
153
+ def wait_for_server_at(url)
154
+ page = Net::HTTP.get URI.parse(url)
155
+ rescue Errno::ECONNREFUSED
156
+ sleep 1
157
+ retry
158
+ end
159
+ end
160
+ end
161
+
162
+ require File.expand_path(File.dirname(__FILE__) + '/gusto/server')
data/public/ie.js ADDED
@@ -0,0 +1,5 @@
1
+ if(typeof String.prototype.trim !== 'function') {
2
+ String.prototype.trim = function() {
3
+ return this.replace(/^\s+|\s+$/g, '');
4
+ }
5
+ }