leonidas 0.0.1

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.
Files changed (65) hide show
  1. data/CHANGELOG +1 -0
  2. data/Gemfile +15 -0
  3. data/Gemfile.lock +105 -0
  4. data/LICENSE +21 -0
  5. data/Manifest +63 -0
  6. data/README.md +213 -0
  7. data/Rakefile +42 -0
  8. data/assets/scripts/coffee/leonidas/client.coffee +15 -0
  9. data/assets/scripts/coffee/leonidas/commander.coffee +34 -0
  10. data/assets/scripts/coffee/leonidas/commands/command.coffee +9 -0
  11. data/assets/scripts/coffee/leonidas/commands/organizer.coffee +24 -0
  12. data/assets/scripts/coffee/leonidas/commands/processor.coffee +13 -0
  13. data/assets/scripts/coffee/leonidas/commands/stabilizer.coffee +13 -0
  14. data/assets/scripts/coffee/leonidas/commands/synchronizer.coffee +38 -0
  15. data/assets/scripts/js/lib/jquery.js +6 -0
  16. data/bin/leonidas.js +178 -0
  17. data/config/assets.rb +7 -0
  18. data/leonidas.gemspec +36 -0
  19. data/lib/leonidas.rb +14 -0
  20. data/lib/leonidas/app/app.rb +80 -0
  21. data/lib/leonidas/app/connection.rb +20 -0
  22. data/lib/leonidas/app/repository.rb +41 -0
  23. data/lib/leonidas/commands/aggregator.rb +31 -0
  24. data/lib/leonidas/commands/command.rb +24 -0
  25. data/lib/leonidas/commands/handler.rb +21 -0
  26. data/lib/leonidas/commands/processor.rb +30 -0
  27. data/lib/leonidas/dsl/configuration_expression.rb +17 -0
  28. data/lib/leonidas/memory_layer/memory_registry.rb +33 -0
  29. data/lib/leonidas/persistence_layer/persister.rb +54 -0
  30. data/lib/leonidas/persistence_layer/state_builder.rb +17 -0
  31. data/lib/leonidas/persistence_layer/state_loader.rb +22 -0
  32. data/lib/leonidas/routes/sync.rb +45 -0
  33. data/lib/leonidas/symbols.rb +17 -0
  34. data/spec/jasmine/jasmine.yml +44 -0
  35. data/spec/jasmine/runner.html +77 -0
  36. data/spec/jasmine/support/classes.coffee +16 -0
  37. data/spec/jasmine/support/helpers.coffee +22 -0
  38. data/spec/jasmine/support/mocks.coffee +19 -0
  39. data/spec/jasmine/support/objects.coffee +11 -0
  40. data/spec/jasmine/support/requirements.coffee +1 -0
  41. data/spec/jasmine/tests/client_spec.coffee +20 -0
  42. data/spec/jasmine/tests/commander_spec.coffee +69 -0
  43. data/spec/jasmine/tests/commands/command_spec.coffee +12 -0
  44. data/spec/jasmine/tests/commands/organizer_spec.coffee +70 -0
  45. data/spec/jasmine/tests/commands/processor_spec.coffee +22 -0
  46. data/spec/jasmine/tests/commands/stabilizer_spec.coffee +30 -0
  47. data/spec/jasmine/tests/commands/synchronizer_spec.coffee +72 -0
  48. data/spec/rspec/spec_helper.rb +4 -0
  49. data/spec/rspec/support/classes/app.rb +26 -0
  50. data/spec/rspec/support/classes/commands.rb +52 -0
  51. data/spec/rspec/support/classes/persistence.rb +56 -0
  52. data/spec/rspec/support/config.rb +3 -0
  53. data/spec/rspec/support/mocks.rb +15 -0
  54. data/spec/rspec/support/objects.rb +11 -0
  55. data/spec/rspec/unit/app/app_spec.rb +185 -0
  56. data/spec/rspec/unit/app/repository_spec.rb +114 -0
  57. data/spec/rspec/unit/commands/aggregator_spec.rb +103 -0
  58. data/spec/rspec/unit/commands/command.rb +17 -0
  59. data/spec/rspec/unit/commands/processor_spec.rb +30 -0
  60. data/spec/rspec/unit/dsl/configuration_expression_spec.rb +32 -0
  61. data/spec/rspec/unit/leonidas_spec.rb +26 -0
  62. data/spec/rspec/unit/memory_layer/memory_registry_spec.rb +85 -0
  63. data/spec/rspec/unit/persistence_layer/persister_spec.rb +84 -0
  64. data/spec/rspec/unit/persistence_layer/state_loader_spec.rb +29 -0
  65. metadata +166 -0
@@ -0,0 +1,20 @@
1
+ module Leonidas
2
+ module App
3
+
4
+ class Connection
5
+ include ::Leonidas::Commands::Aggregator
6
+
7
+ attr_reader :id, :active_commands
8
+ attr_accessor :last_update
9
+
10
+ def initialize
11
+ @id = SecureRandom.uuid
12
+ @last_update = Time.now.to_i
13
+ @active_commands = [ ]
14
+ @inactive_commands = [ ]
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ module Leonidas
2
+ module App
3
+ module AppRepository
4
+ def app_repository
5
+ @repository ||= Repository.new
6
+ end
7
+ end
8
+
9
+ class Repository
10
+
11
+ def find(app_name)
12
+ app = ::Leonidas::MemoryLayer::MemoryRegistry.retrieve_app app_name
13
+ if app.nil?
14
+ app = ::Leonidas::PersistenceLayer::Persister.load app_name
15
+ watch app unless app.nil?
16
+ end
17
+ app
18
+ end
19
+
20
+ def watch(app)
21
+ ::Leonidas::MemoryLayer::MemoryRegistry.register_app! app
22
+ end
23
+
24
+ def save(app)
25
+ ::Leonidas::PersistenceLayer::Persister.persist app
26
+ end
27
+
28
+ def archive(app)
29
+ ::Leonidas::MemoryLayer::MemoryRegistry.close_app! app.name
30
+ ::Leonidas::PersistenceLayer::Persister.persist app
31
+ end
32
+
33
+ def delete(app)
34
+ ::Leonidas::MemoryLayer::MemoryRegistry.close_app! app.name
35
+ ::Leonidas::PersistenceLayer::Persister.delete app
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ module Leonidas
2
+ module Commands
3
+
4
+ module Aggregator
5
+
6
+ def add_command!(command)
7
+ raise TypeError, "Argument must be a Leonidas::Commands::Command" unless command.is_a? ::Leonidas::Commands::Command
8
+ @active_commands << command
9
+ end
10
+
11
+ def add_commands!(commands)
12
+ commands.each {|command| add_command!(command)}
13
+ end
14
+
15
+ def commands_through(timestamp)
16
+ @active_commands.select {|command| command.timestamp <= timestamp}
17
+ end
18
+
19
+ def commands_since(timestamp)
20
+ @active_commands.select {|command| command.timestamp > timestamp}
21
+ end
22
+
23
+ def deactivate_commands!(commands)
24
+ commands.each {|command| @inactive_commands << command if @active_commands.include? command}
25
+ @active_commands.select! {|command| not commands.include? command}
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ module Leonidas
2
+ module Commands
3
+
4
+ class Command
5
+
6
+ attr_reader :name, :data, :timestamp, :connection
7
+
8
+ def initialize(name, data, timestamp, connection)
9
+ @name = name
10
+ @data = data
11
+ @timestamp = timestamp
12
+
13
+ raise TypeError, "Argument must be a Leonidas::App::Connection" unless connection.is_a? ::Leonidas::App::Connection
14
+ @connection = connection
15
+ end
16
+
17
+ def to_hash
18
+ { name: @name, data: @data, timestamp: @timestamp, connection: @connection.id }
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ module Leonidas
2
+ module Commands
3
+
4
+ module Handler
5
+
6
+ def handles?(command)
7
+ false
8
+ end
9
+
10
+ def run(command)
11
+ # perform the command
12
+ end
13
+
14
+ def persist(command)
15
+ # perform the command
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ module Leonidas
2
+ module Commands
3
+
4
+ class Processor
5
+
6
+ def initialize(handlers)
7
+ @handlers = [ ]
8
+ handlers.each do |handler|
9
+ raise TypeError, "Argument must include Leonidas::Commands::Handler" unless handler.class < ::Leonidas::Commands::Handler
10
+ @handlers << handler
11
+ end
12
+ end
13
+
14
+ def process(commands, persist=false)
15
+ commands.sort! {|command1, command2| command1.timestamp <=> command2.timestamp}
16
+ commands.each do |command|
17
+ raise TypeError, "Argument must be a Leonidas::Commands::Command" unless command.is_a? ::Leonidas::Commands::Command
18
+ @handlers.each do |command_handler|
19
+ if command_handler.handles? command
20
+ command_handler.run(command)
21
+ command_handler.persist(command) if persist
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ module Leonidas
2
+ module Dsl
3
+
4
+ class ConfigurationExpression
5
+
6
+ def persister_class_is(persister_class)
7
+ ::Leonidas::PersistenceLayer::Persister.set_app_persister! persister_class.new
8
+ end
9
+
10
+ def add_app_state_builder(builder_class)
11
+ ::Leonidas::PersistenceLayer::Persister.add_state_builder! builder_class.new
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ module Leonidas
2
+ module MemoryLayer
3
+
4
+ class MemoryRegistry
5
+
6
+ @@apps = { }
7
+
8
+ def self.register_app!(app)
9
+ raise TypeError, "Argument must include Leonidas::App::App" unless app.class < ::Leonidas::App::App
10
+ raise StandardError, "An app with the name '#{app.name}' is already registered" if ::Leonidas::MemoryLayer::MemoryRegistry.has_app? app.name
11
+ @@apps[app.name] = app
12
+ end
13
+
14
+ def self.retrieve_app(name)
15
+ @@apps[name]
16
+ end
17
+
18
+ def self.has_app?(name)
19
+ not MemoryRegistry.retrieve_app(name).nil?
20
+ end
21
+
22
+ def self.close_app!(name)
23
+ @@apps.delete name
24
+ end
25
+
26
+ def self.clear_registry!
27
+ @@apps = { }
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ module Leonidas
2
+ module PersistenceLayer
3
+ module AppPersister
4
+
5
+ def load(app_name)
6
+ # load your app
7
+ end
8
+
9
+ def persist(app)
10
+ # save your app (this excludes state saving, that happens in the command handlers)
11
+ end
12
+
13
+ def delete(app)
14
+ # delete your app
15
+ end
16
+
17
+ end
18
+
19
+ class Persister
20
+
21
+ @@persister = nil
22
+
23
+ def self.set_app_persister!(persister)
24
+ raise TypeError, "Argument must include Leonidas::PersistenceLayer::AppPersister" unless persister.class < ::Leonidas::PersistenceLayer::AppPersister
25
+ @@persister = persister
26
+ end
27
+
28
+ @@state_loader = ::Leonidas::PersistenceLayer::StateLoader.new
29
+
30
+ def self.add_state_builder!(builder)
31
+ @@state_loader.add_builder! builder
32
+ end
33
+
34
+ def self.load(app_name)
35
+ app = @@persister.load app_name unless @@persister.nil?
36
+ unless app.nil?
37
+ @@state_loader.load_state app
38
+ app.process_commands!
39
+ end
40
+ app
41
+ end
42
+
43
+ def self.persist(app)
44
+ @@persister.persist app unless @@persister.nil?
45
+ end
46
+
47
+ def self.delete(app)
48
+ @@persister.delete app unless @@persister.nil?
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,17 @@
1
+ module Leonidas
2
+ module PersistenceLayer
3
+
4
+ module StateBuilder
5
+
6
+ def handles?(app)
7
+ false
8
+ end
9
+
10
+ def build_stable_state(app)
11
+ # build the stable state
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module Leonidas
2
+ module PersistenceLayer
3
+
4
+ class StateLoader
5
+
6
+ def initialize
7
+ @builders = [ ]
8
+ end
9
+
10
+ def add_builder!(builder)
11
+ raise TypeError, "Argument must include Leonidas::PersistenceLayer::StateBuilder" unless builder.class < ::Leonidas::PersistenceLayer::StateBuilder
12
+ @builders << builder
13
+ end
14
+
15
+ def load_state(app)
16
+ @builders.each {|builder| return builder.build_stable_state app if builder.handles? app}
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,45 @@
1
+ module Leonidas
2
+ module Routes
3
+
4
+ class SyncApp < Sinatra::Base
5
+ include ::Leonidas::App::AppRepository
6
+
7
+ get '/:app_name' do
8
+ content_type "application/json"
9
+
10
+ app = app_repository.find params[:app_name]
11
+
12
+ new_commands = params[:clients].reduce([ ]) {|commands, client| commands.concat app.connection(client[:id]).commands_since(client[:lastUpdate])}
13
+ additional_clients = app.connections.select {|connection| connection.id != params[:clientId]}
14
+
15
+ {
16
+ success: true,
17
+ message: 'commands retrieved',
18
+ data: {
19
+ commands: new_commands.map {|command| command.to_hash},
20
+ currentClients: additional_clients.map {|connection| { id: connection.id, lastUpdate: connection.last_update }},
21
+ stableTimestamp: app.stable_timestamp
22
+ }
23
+ }.to_json
24
+ end
25
+
26
+ post '/:app_name' do
27
+ content_type "application/json"
28
+
29
+ app = app_repository.find params[:app_name]
30
+ connection = app.connection params[:clientId]
31
+
32
+ commands = params[:commands].map {|command| ::Leonidas::Commands::Command.new(command.name, command.data, command.timestamp, connection)}
33
+ connection.add_commands! commands
34
+
35
+ {
36
+ success: true,
37
+ message: 'commands received',
38
+ data: { }
39
+ }.to_json
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ require "keystone"
2
+
3
+ module Leonidas
4
+
5
+ def self.pipeline
6
+ @@pipeline ||= ::Keystone.bootstrap("#{root_path}/config/assets.rb")
7
+ end
8
+
9
+ def self.keystone_compiler
10
+ @@keystone_compiler ||= pipeline.compiler("leonidas.js")
11
+ end
12
+
13
+ def self.root_path
14
+ File.expand_path("#{File.dirname(__FILE__)}/../../")
15
+ end
16
+
17
+ end
@@ -0,0 +1,44 @@
1
+ runner_output: "spec/jasmine/runner.html"
2
+
3
+ # src_files
4
+ #
5
+ # Return an array of filepaths relative to src_dir to include before jasmine specs.
6
+ # Default: []
7
+ src_files:
8
+ - bin/leonidas.js
9
+
10
+ # stylesheets
11
+ #
12
+ # Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
13
+ # Default: []
14
+ stylesheets:
15
+
16
+ # helpers
17
+ #
18
+ # Return an array of filepaths relative to spec_dir to include before jasmine specs.
19
+ # Default: ["helpers/**/*.js"]
20
+ helpers:
21
+ - support/requirements.coffee
22
+ - support/helpers.coffee
23
+ - support/objects.coffee
24
+ - support/classes.coffee
25
+ - support/mocks.coffee
26
+
27
+ # spec_files
28
+ #
29
+ # Return an array of filepaths relative to spec_dir to include.
30
+ # Default: ["**/*[sS]pec.js"]
31
+ spec_files:
32
+ - ./**/*_spec.coffee
33
+
34
+ # src_dir
35
+ #
36
+ # Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
37
+ # Default: project root
38
+ src_dir:
39
+
40
+ # spec_dir
41
+ #
42
+ # Spec directory path. Your spec_files must be returned relative to this path.
43
+ # Default: spec/javascripts
44
+ spec_dir: spec/jasmine
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2
+ <html>
3
+ <head>
4
+ <meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
5
+ <title>Jasmine Test Runner - Generated by jasmine-headless-webkit</title>
6
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-headless-webkit-0.8.4/vendor/assets/javascripts/prolog.js"></script>
7
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-core-1.3.1/lib/jasmine-core/jasmine.js"></script>
8
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-core-1.3.1/lib/jasmine-core/jasmine-html.js"></script>
9
+ <link rel="stylesheet" href="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-core-1.3.1/lib/jasmine-core/jasmine.css" type="text/css" />
10
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-headless-webkit-0.8.4/vendor/assets/javascripts/jasmine-extensions.js"></script>
11
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-headless-webkit-0.8.4/vendor/assets/javascripts/intense.js"></script>
12
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-headless-webkit-0.8.4/vendor/assets/javascripts/headless_reporter_result.js"></script>
13
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-headless-webkit-0.8.4/vendor/assets/javascripts/jasmine.HeadlessConsoleReporter.js"></script>
14
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-headless-webkit-0.8.4/vendor/assets/javascripts/jsDump.js"></script>
15
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/vendor/ruby/1.9.1/gems/jasmine-headless-webkit-0.8.4/vendor/assets/javascripts/beautify-html.js"></script>
16
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/bin/leonidas.js"></script>
17
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/requirements.coffee.js"></script>
18
+ <script type="text/javascript">window.CSTF['requirements.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/requirements.coffee';</script>
19
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/helpers.coffee.js"></script>
20
+ <script type="text/javascript">window.CSTF['helpers.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/helpers.coffee';</script>
21
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/objects.coffee.js"></script>
22
+ <script type="text/javascript">window.CSTF['objects.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/objects.coffee';</script>
23
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/classes.coffee.js"></script>
24
+ <script type="text/javascript">window.CSTF['classes.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/classes.coffee';</script>
25
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/mocks.coffee.js"></script>
26
+ <script type="text/javascript">window.CSTF['mocks.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/support/mocks.coffee';</script>
27
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/synchronizer_spec.coffee.js"></script>
28
+ <script type="text/javascript">window.CSTF['synchronizer_spec.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/synchronizer_spec.coffee';</script>
29
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commander_spec.coffee.js"></script>
30
+ <script type="text/javascript">window.CSTF['commander_spec.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commander_spec.coffee';</script>
31
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/stabilizer_spec.coffee.js"></script>
32
+ <script type="text/javascript">window.CSTF['stabilizer_spec.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/stabilizer_spec.coffee';</script>
33
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/organizer_spec.coffee.js"></script>
34
+ <script type="text/javascript">window.CSTF['organizer_spec.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/organizer_spec.coffee';</script>
35
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/command_spec.coffee.js"></script>
36
+ <script type="text/javascript">window.CSTF['command_spec.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/command_spec.coffee';</script>
37
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/client_spec.coffee.js"></script>
38
+ <script type="text/javascript">window.CSTF['client_spec.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/client_spec.coffee';</script>
39
+ <script type="text/javascript" src="/Users/tshelburne/Sites/musicone/leonidas/.jhw-cache/coffee_script/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/processor_spec.coffee.js"></script>
40
+ <script type="text/javascript">window.CSTF['processor_spec.coffee.js'] = '/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/processor_spec.coffee';</script>
41
+ <script type="text/javascript">
42
+ if (window.JHW) { HeadlessReporterResult.specLineNumbers = {"/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/synchronizer_spec.coffee":{"Synchronizer":[6],"#push":[23],"when successful":[28,47],"will mark the commands pushed as synced":[30],"will not mark unsynced commands added since push was called as synced":[36],"#pull":[45],"will update the list of external clients and their latest timestamps":[53],"will add the list of received commands as synced commands":[57],"will lock to a new stable state":[64],"will deactivate stable commands":[68]},"/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commander_spec.coffee":{"Commander":[7],"::default":[23],"will return a default commander using the built in classes":[25],"#startSync":[29],"will set the synchronizer to begin pushing updates":[34],"will set the synchronizer to begin pulling updates":[39],"#stopSync":[44],"will stop the synchronizer from pushing updates":[49],"will stop the synchronizer from pulling updates":[55],"#issueCommand":[61],"will generate an unsynchronized command":[63],"will run the command to update the local client state":[67]},"/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/stabilizer_spec.coffee":{"Stabilizer":[6],"#stabilize":[18],"will update the locked state to the state at the given timestamp":[20],"will deactivate the stable commands in the command organizer":[24],"will process the remaining active commands to leave the active state entirely current":[28]},"/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/organizer_spec.coffee":{"Organizer":[3],"#addCommand":[14],"will add unsynced commands":[16],"will add synced commands":[20],"#addCommands":[24],"will add multiple unsynced commands":[26],"will add multiple synced commands":[30],"#markAsSynced":[34],"will add the requested commands to the syncedCommands list":[36],"will remove the requested commands from the unsyncedCommands list":[41],"#markAsInactive":[46],"will add the requested commands to the inactiveCommands list":[48],"will remove requested commands from the syncedCommands list":[53],"#activeCommands":[58],"will return a concatenated list of synced and unsynced commands":[60],"will sort the list of commands by timestamp":[67]},"/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/command_spec.coffee":{"Command":[3],"#toHash":[9],"will return the command serialized as a hash":[11]},"/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/client_spec.coffee":{"Client":[3],"#revertState":[10],"will revert the active state to the locked state":[12],"#lockState":[16],"will lock the state to the active state":[18]},"/Users/tshelburne/Sites/musicone/leonidas/spec/jasmine/tests/commands/processor_spec.coffee":{"Processor":[4],"#processCommand":[12],"will run a command":[14],"#processCommands":[18],"will run multiple commands":[20]}}; }
43
+ </script>
44
+ </head>
45
+ <body>
46
+ <script type="text/javascript">
47
+ jasmine.getEnv().console = {
48
+ log: function(msg) { JHW.stdout.puts(msg) }
49
+ }
50
+
51
+ window._onload = window.onload;
52
+
53
+ window.onload = function() {
54
+ if (window._onload && (window._onload != window.onload)) {
55
+ window._onload();
56
+ }
57
+
58
+ if (window.JHW) {
59
+ jasmine.getEnv().addReporter(new jasmine.HeadlessConsoleReporter());
60
+ } else {
61
+ types = [ 'HtmlReporter', 'TrivialReporter' ];
62
+
63
+ for (var i = 0, j = types.length; i < j; ++i) {
64
+ var type = jasmine[types[i]]
65
+ if (type) {
66
+ jasmine.getEnv().addReporter(new type());
67
+ break;
68
+ }
69
+ }
70
+ }
71
+
72
+ jasmine.getEnv().execute();
73
+ }
74
+ </script>
75
+ </body>
76
+ </html>
77
+