volt 0.9.3.pre3 → 0.9.3.pre4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -2
- data/app/volt/models/user.rb +5 -0
- data/app/volt/tasks/store_tasks.rb +2 -2
- data/app/volt/tasks/user_tasks.rb +1 -1
- data/lib/volt/cli/asset_compile.rb +0 -2
- data/lib/volt/cli/generate.rb +8 -3
- data/lib/volt/cli.rb +3 -9
- data/lib/volt/controllers/actions.rb +6 -1
- data/lib/volt/controllers/http_controller.rb +16 -7
- data/lib/volt/controllers/model_controller.rb +21 -0
- data/lib/volt/models/array_model.rb +26 -3
- data/lib/volt/models/model.rb +18 -19
- data/lib/volt/models/persistors/array_store.rb +2 -10
- data/lib/volt/models/root_models/store_root.rb +17 -4
- data/lib/volt/models/validations/validations.rb +1 -1
- data/lib/volt/models/validators/unique_validator.rb +1 -1
- data/lib/volt/models.rb +1 -1
- data/lib/volt/page/bindings/attribute_binding.rb +5 -4
- data/lib/volt/page/bindings/base_binding.rb +17 -0
- data/lib/volt/page/bindings/content_binding.rb +7 -5
- data/lib/volt/page/bindings/each_binding.rb +62 -51
- data/lib/volt/page/bindings/event_binding.rb +14 -0
- data/lib/volt/page/bindings/view_binding.rb +1 -1
- data/lib/volt/reactive/computation.rb +22 -13
- data/lib/volt/reactive/dependency.rb +0 -24
- data/lib/volt/router/routes.rb +35 -0
- data/lib/volt/server/forking_server.rb +26 -3
- data/lib/volt/server/message_bus/peer_to_peer/peer_connection.rb +1 -1
- data/lib/volt/server/message_bus/peer_to_peer/server_tracker.rb +1 -1
- data/lib/volt/server/message_bus/peer_to_peer.rb +28 -21
- data/lib/volt/server/middleware/default_middleware_stack.rb +67 -0
- data/lib/volt/server/middleware/middleware_stack.rb +58 -0
- data/lib/volt/server/rack/http_request.rb +1 -1
- data/lib/volt/server/rack/http_resource.rb +7 -0
- data/lib/volt/server/rack/keep_alive.rb +20 -0
- data/lib/volt/server/socket_connection_handler.rb +10 -1
- data/lib/volt/server.rb +6 -76
- data/lib/volt/utils/promise_extensions.rb +5 -1
- data/lib/volt/utils/set_patch.rb +25 -0
- data/lib/volt/utils/timers.rb +12 -0
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/app.rb +13 -1
- data/lib/volt/volt/server_setup/app.rb +19 -1
- data/lib/volt/volt/users.rb +11 -22
- data/lib/volt.rb +1 -0
- data/spec/apps/kitchen_sink/Gemfile +1 -1
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +1 -1
- data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +22 -0
- data/spec/apps/kitchen_sink/app/main/views/main/bindings.html +10 -0
- data/spec/apps/kitchen_sink/app/main/views/main/store_demo.html +9 -0
- data/spec/controllers/http_controller_spec.rb +27 -0
- data/spec/integration/bindings_spec.rb +29 -0
- data/spec/integration/store_spec.rb +7 -7
- data/spec/models/associations_spec.rb +1 -1
- data/spec/models/model_spec.rb +10 -0
- data/spec/models/permissions_spec.rb +7 -4
- data/spec/reactive/computation_spec.rb +33 -5
- data/spec/router/routes_spec.rb +69 -0
- data/spec/server/middleware/middleware_handler.rb +24 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/tasks/user_tasks_spec.rb +3 -2
- data/templates/project/Gemfile.tt +2 -2
- data/templates/project/config/base/index.html +5 -1
- metadata +10 -5
- data/spec/apps/kitchen_sink/app/main/views/main/store.html +0 -9
- data/templates/project/app/main/models/.empty_directory +0 -0
@@ -38,7 +38,16 @@ module Volt
|
|
38
38
|
# Messages are json and wrapped in an array
|
39
39
|
message = JSON.parse(message).first
|
40
40
|
|
41
|
-
|
41
|
+
begin
|
42
|
+
@@dispatcher.dispatch(self, message)
|
43
|
+
rescue => e
|
44
|
+
if defined?(DRb::DRbConnError) && e.is_a?(DRb::DRbConnError)
|
45
|
+
# The child process was restarting, so drb failed to send
|
46
|
+
else
|
47
|
+
# re-raise the issue
|
48
|
+
raise
|
49
|
+
end
|
50
|
+
end
|
42
51
|
end
|
43
52
|
|
44
53
|
def send_message(*args)
|
data/lib/volt/server.rb
CHANGED
@@ -7,43 +7,17 @@ require 'sass'
|
|
7
7
|
require 'volt/utils/tilt_patch'
|
8
8
|
require 'sprockets-sass'
|
9
9
|
|
10
|
-
|
11
10
|
require 'volt'
|
12
11
|
require 'volt/tasks/dispatcher'
|
13
12
|
require 'volt/tasks/task'
|
14
13
|
require 'volt/server/component_handler'
|
15
14
|
require 'volt/server/rack/component_paths'
|
16
|
-
require 'volt/server/rack/index_files'
|
17
|
-
require 'volt/server/rack/http_resource'
|
18
|
-
require 'volt/server/rack/opal_files'
|
19
|
-
require 'volt/server/rack/quiet_common_logger'
|
20
15
|
require 'volt/page/page'
|
21
16
|
|
22
|
-
require 'volt/volt/core'
|
23
17
|
require 'volt/server/websocket/websocket_handler'
|
24
18
|
require 'volt/utils/read_write_lock'
|
25
19
|
require 'volt/server/forking_server'
|
26
20
|
|
27
|
-
module Rack
|
28
|
-
# TODO: For some reason in Rack (or maybe thin), 304 headers close
|
29
|
-
# the http connection. We might need to make this check if keep
|
30
|
-
# alive was in the request.
|
31
|
-
class KeepAlive
|
32
|
-
def initialize(app)
|
33
|
-
@app = app
|
34
|
-
end
|
35
|
-
|
36
|
-
def call(env)
|
37
|
-
status, headers, body = @app.call(env)
|
38
|
-
|
39
|
-
if status == 304 && env['HTTP_CONNECTION'] && env['HTTP_CONNECTION'].downcase == 'keep-alive'
|
40
|
-
headers['Connection'] = 'keep-alive'
|
41
|
-
end
|
42
|
-
|
43
|
-
[status, headers, body]
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
21
|
|
48
22
|
module Volt
|
49
23
|
class Server
|
@@ -54,7 +28,7 @@ module Volt
|
|
54
28
|
@root_path = root_path || Dir.pwd
|
55
29
|
@volt_app = app
|
56
30
|
|
57
|
-
@app_path
|
31
|
+
@app_path = File.expand_path(File.join(@root_path, 'app'))
|
58
32
|
|
59
33
|
display_welcome
|
60
34
|
end
|
@@ -70,7 +44,10 @@ module Volt
|
|
70
44
|
@volt_app ||= Volt.boot(@root_path)
|
71
45
|
end
|
72
46
|
|
73
|
-
# App returns the main rack app. In development it will
|
47
|
+
# App returns the main rack app. In development it will use ForkingServer,
|
48
|
+
# which forks the app and processes responses in a child process, that is
|
49
|
+
# killed when code changes and reforked. (This provides simple fast code
|
50
|
+
# reloading)
|
74
51
|
def app
|
75
52
|
app = Rack::Builder.new
|
76
53
|
|
@@ -94,7 +71,7 @@ module Volt
|
|
94
71
|
|
95
72
|
# Setup the dispatcher (it stays this class during its run)
|
96
73
|
SocketConnectionHandler.dispatcher = Dispatcher.new(@volt_app)
|
97
|
-
app.run(
|
74
|
+
app.run(@volt_app.middleware)
|
98
75
|
else
|
99
76
|
# In developer
|
100
77
|
app.run ForkingServer.new(self)
|
@@ -102,52 +79,5 @@ module Volt
|
|
102
79
|
|
103
80
|
app
|
104
81
|
end
|
105
|
-
|
106
|
-
# new_server returns the core of the Rack app.
|
107
|
-
# Volt.boot should be called before generating the new server
|
108
|
-
def new_server
|
109
|
-
@rack_app = Rack::Builder.new
|
110
|
-
|
111
|
-
# Should only be used in production
|
112
|
-
if Volt.config.deflate
|
113
|
-
@rack_app.use Rack::Deflater
|
114
|
-
@rack_app.use Rack::Chunked
|
115
|
-
end
|
116
|
-
|
117
|
-
@rack_app.use Rack::ContentLength
|
118
|
-
|
119
|
-
@rack_app.use Rack::KeepAlive
|
120
|
-
@rack_app.use Rack::ConditionalGet
|
121
|
-
@rack_app.use Rack::ETag
|
122
|
-
|
123
|
-
@rack_app.use QuietCommonLogger
|
124
|
-
@rack_app.use Rack::ShowExceptions
|
125
|
-
|
126
|
-
component_paths = @volt_app.component_paths
|
127
|
-
@rack_app.map '/components' do
|
128
|
-
run ComponentHandler.new(component_paths)
|
129
|
-
end
|
130
|
-
|
131
|
-
# Serve the opal files
|
132
|
-
opal_files = OpalFiles.new(@rack_app, @app_path, @volt_app.component_paths)
|
133
|
-
|
134
|
-
# Serve the main html files from public, also figure out
|
135
|
-
# which JS/CSS files to serve.
|
136
|
-
@rack_app.use IndexFiles, @volt_app, @volt_app.component_paths, opal_files
|
137
|
-
|
138
|
-
@rack_app.use HttpResource, @volt_app, @volt_app.router
|
139
|
-
|
140
|
-
@rack_app.use Rack::Static,
|
141
|
-
urls: ['/'],
|
142
|
-
root: 'config/base',
|
143
|
-
index: '',
|
144
|
-
header_rules: [
|
145
|
-
[:all, { 'Cache-Control' => 'public, max-age=86400' }]
|
146
|
-
]
|
147
|
-
|
148
|
-
@rack_app.run lambda { |env| [404, { 'Content-Type' => 'text/html; charset=utf-8' }, ['404 - page not found']] }
|
149
|
-
|
150
|
-
@rack_app
|
151
|
-
end
|
152
82
|
end
|
153
83
|
end
|
@@ -12,6 +12,10 @@ class Promise
|
|
12
12
|
promise
|
13
13
|
end
|
14
14
|
|
15
|
+
def respond_to_missing(method_name, include_private = false)
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
15
19
|
# Allow .each to be called directly on promises
|
16
20
|
def each(&block)
|
17
21
|
raise ArgumentError, 'no block given' unless block
|
@@ -69,7 +73,7 @@ class Promise
|
|
69
73
|
|
70
74
|
if error
|
71
75
|
err_str = "Exception in Promise at .sync: #{error.inspect}"
|
72
|
-
err_str += error.backtrace.join("\n")
|
76
|
+
err_str += error.backtrace.join("\n") if error.respond_to?(:backtrace)
|
73
77
|
Volt.logger.error(err_str)
|
74
78
|
fail error
|
75
79
|
else
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Temp until https://github.com/opal/opal/pull/596
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
class Set
|
5
|
+
def delete(o)
|
6
|
+
if include?(o)
|
7
|
+
@hash.delete(o)
|
8
|
+
true
|
9
|
+
else
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def delete_if
|
15
|
+
block_given? or return enum_for(__method__)
|
16
|
+
# @hash.delete_if should be faster, but using it breaks the order
|
17
|
+
# of enumeration in subclasses.
|
18
|
+
select { |o| yield o }.each { |o| @hash.delete(o) }
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_a
|
23
|
+
@hash.keys
|
24
|
+
end
|
25
|
+
end
|
data/lib/volt/utils/timers.rb
CHANGED
@@ -14,6 +14,18 @@ module Volt
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
# yields the passed in block after interval ms, or immediately if on the
|
18
|
+
# server.
|
19
|
+
def self.client_set_timeout(interval)
|
20
|
+
if Volt.in_browser?
|
21
|
+
`setTimeout(function() {`
|
22
|
+
yield
|
23
|
+
`}, interval)`
|
24
|
+
else
|
25
|
+
yield
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
17
29
|
# On the server, we need to manually flush next tick timers.
|
18
30
|
# This is done automatically in the console after each enter.
|
19
31
|
def self.flush_next_tick_timers!
|
data/lib/volt/version.rb
CHANGED
data/lib/volt/volt/app.rb
CHANGED
@@ -37,7 +37,8 @@ module Volt
|
|
37
37
|
end
|
38
38
|
|
39
39
|
attr_reader :component_paths, :router, :page, :live_query_pool,
|
40
|
-
:channel_live_queries, :app_path, :database, :message_bus
|
40
|
+
:channel_live_queries, :app_path, :database, :message_bus,
|
41
|
+
:middleware
|
41
42
|
|
42
43
|
def initialize(app_path=nil)
|
43
44
|
if Volt.server? && !app_path
|
@@ -53,6 +54,14 @@ module Volt
|
|
53
54
|
setup_page
|
54
55
|
|
55
56
|
if RUBY_PLATFORM != 'opal'
|
57
|
+
# We need to run the root config first so we can setup the Rack::Session
|
58
|
+
# middleware.
|
59
|
+
run_config
|
60
|
+
|
61
|
+
# Setup all of the middleware we can before we load the users components
|
62
|
+
# since the users components might want to add middleware during boot.
|
63
|
+
setup_preboot_middleware
|
64
|
+
|
56
65
|
# Setup all app paths
|
57
66
|
setup_paths
|
58
67
|
|
@@ -69,6 +78,9 @@ module Volt
|
|
69
78
|
|
70
79
|
reset_query_pool!
|
71
80
|
|
81
|
+
# Setup the middleware that we can only setup after all components boot.
|
82
|
+
setup_postboot_middleware
|
83
|
+
|
72
84
|
start_message_bus
|
73
85
|
end
|
74
86
|
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# The following setup handles setting up the app on the server.
|
2
2
|
unless RUBY_PLATFORM == 'opal'
|
3
3
|
require 'volt/server/message_bus/peer_to_peer'
|
4
|
+
require 'volt/server/middleware/middleware_stack'
|
5
|
+
require 'volt/server/middleware/default_middleware_stack'
|
6
|
+
require 'volt/volt/core'
|
7
|
+
|
4
8
|
end
|
5
9
|
|
6
10
|
module Volt
|
@@ -21,6 +25,16 @@ module Volt
|
|
21
25
|
@router = Routes.new
|
22
26
|
end
|
23
27
|
|
28
|
+
|
29
|
+
def setup_preboot_middleware
|
30
|
+
@middleware = MiddlewareStack.new
|
31
|
+
DefaultMiddlewareStack.preboot_setup(self, @middleware)
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup_postboot_middleware
|
35
|
+
DefaultMiddlewareStack.postboot_setup(self, @middleware)
|
36
|
+
end
|
37
|
+
|
24
38
|
def require_http_controllers
|
25
39
|
@component_paths.app_folders do |app_folder|
|
26
40
|
# Sort so we get consistent load order across platforms
|
@@ -32,11 +46,15 @@ module Volt
|
|
32
46
|
end
|
33
47
|
end
|
34
48
|
|
49
|
+
# This config needs to run earlier than others
|
50
|
+
def run_config
|
51
|
+
require("#{Volt.root}/config/app.rb")
|
52
|
+
end
|
35
53
|
|
36
54
|
# Load in all .rb files in the initializers folders and the config/app.rb
|
37
55
|
# file.
|
38
56
|
def run_app_and_initializers
|
39
|
-
files = [
|
57
|
+
files = []
|
40
58
|
|
41
59
|
# Include the root initializers
|
42
60
|
files += Dir[Volt.root + '/config/initializers/*.rb']
|
data/lib/volt/volt/users.rb
CHANGED
@@ -53,13 +53,19 @@ module Volt
|
|
53
53
|
|
54
54
|
# True if the user is logged in and the user is loaded
|
55
55
|
def current_user?
|
56
|
-
|
56
|
+
current_user.then do |user|
|
57
|
+
!!user
|
58
|
+
end
|
57
59
|
end
|
58
60
|
|
59
61
|
# Return the current user.
|
60
62
|
def current_user
|
61
|
-
|
62
|
-
|
63
|
+
user_id = current_user_id
|
64
|
+
if user_id
|
65
|
+
$page.store._users.where(id: user_id).first
|
66
|
+
else
|
67
|
+
Promise.new.resolve(nil)
|
68
|
+
end
|
63
69
|
end
|
64
70
|
|
65
71
|
# Put in a deprecation placeholder
|
@@ -69,13 +75,8 @@ module Volt
|
|
69
75
|
end
|
70
76
|
|
71
77
|
def fetch_current_user
|
72
|
-
|
73
|
-
|
74
|
-
u_query.fetch_first
|
75
|
-
else
|
76
|
-
# No user, resolve nil
|
77
|
-
Promise.new.resolve(nil)
|
78
|
-
end
|
78
|
+
Volt.logger.warn("Deprication Warning: fetch current user have been depricated, Volt.current_user returns a promise now.")
|
79
|
+
current_user
|
79
80
|
end
|
80
81
|
|
81
82
|
# Login the user, return a promise for success
|
@@ -110,17 +111,5 @@ module Volt
|
|
110
111
|
|
111
112
|
user_id_signature
|
112
113
|
end
|
113
|
-
|
114
|
-
private
|
115
|
-
|
116
|
-
# Returns a query for the current user_id or nil if there is no user_id
|
117
|
-
def user_query
|
118
|
-
user_id = current_user_id
|
119
|
-
if user_id
|
120
|
-
$page.store._users.where(_id: user_id)
|
121
|
-
else
|
122
|
-
nil
|
123
|
-
end
|
124
|
-
end
|
125
114
|
end
|
126
115
|
end
|
data/lib/volt.rb
CHANGED
@@ -5,6 +5,7 @@ require 'volt/reactive/dependency'
|
|
5
5
|
require 'volt/utils/modes'
|
6
6
|
require 'volt/utils/volt_user_error'
|
7
7
|
require 'volt/utils/boolean_patch'
|
8
|
+
require 'volt/utils/set_patch'
|
8
9
|
|
9
10
|
require 'volt/config'
|
10
11
|
require 'volt/data_stores/data_store' unless RUBY_PLATFORM == 'opal'
|
@@ -3,7 +3,7 @@
|
|
3
3
|
client '/bindings/{{ route_test }}', action: 'bindings'
|
4
4
|
client '/bindings', action: 'bindings'
|
5
5
|
client '/form', action: 'form'
|
6
|
-
client '/store', action: '
|
6
|
+
client '/store', action: 'store_demo'
|
7
7
|
client '/cookie_test', action: 'cookie_test'
|
8
8
|
client '/flash', action: 'flash'
|
9
9
|
client '/yield', action: 'yield'
|
@@ -10,6 +10,10 @@ module Main
|
|
10
10
|
a[{}] = 5
|
11
11
|
end
|
12
12
|
|
13
|
+
def store_demo
|
14
|
+
puts "STORE DEMO"
|
15
|
+
end
|
16
|
+
|
13
17
|
def form_ready
|
14
18
|
`$('#title').html('form_ready')`
|
15
19
|
`$('select#location').val('AL').change()` # have to trigger manually as this is not user initiaized action
|
@@ -54,6 +58,24 @@ module Main
|
|
54
58
|
page._show = value
|
55
59
|
end
|
56
60
|
|
61
|
+
def show_with_delay
|
62
|
+
changes = Promise.new
|
63
|
+
page._items = changes
|
64
|
+
`
|
65
|
+
setTimeout(function () {
|
66
|
+
#{changes.resolve(0.upto(100).to_a)}
|
67
|
+
}, 50);
|
68
|
+
`
|
69
|
+
page._items = 901.upto(1000).to_a
|
70
|
+
end
|
71
|
+
|
72
|
+
def show_without_delay
|
73
|
+
changes = Promise.new
|
74
|
+
changes.resolve(1.upto(200).to_a)
|
75
|
+
page._items = 901.upto(1000).to_a
|
76
|
+
page._items = changes
|
77
|
+
end
|
78
|
+
|
57
79
|
private
|
58
80
|
|
59
81
|
# the main template contains a #template binding that shows another
|
@@ -134,6 +134,16 @@
|
|
134
134
|
<a id='showtrue' e-click='set_show(true)'>set _show true</a>
|
135
135
|
<a id='showfalse' e-click='set_show(false)'>set _show false</a>
|
136
136
|
|
137
|
+
<h2>Each Bindings</h2>
|
138
|
+
<ul id='eachbinding'>
|
139
|
+
{{ _items.each do |item| }}
|
140
|
+
<li>{{ item }}</li>
|
141
|
+
{{ end }}
|
142
|
+
</ul>
|
143
|
+
|
144
|
+
<a id='each-show-with-delay' e-click='show_with_delay'>Show with Delay</a>
|
145
|
+
<a id='each-show-without-delay' e-click='show_without_delay'>Show without Delay</a>
|
146
|
+
|
137
147
|
<h2>Content</h2>
|
138
148
|
|
139
149
|
<p id="escapeContent">{{{this is {{escaped}}}}}</p>
|
@@ -7,7 +7,12 @@ if RUBY_PLATFORM != 'opal'
|
|
7
7
|
|
8
8
|
describe Volt::HttpController do
|
9
9
|
class TestHttpController < Volt::HttpController
|
10
|
+
attr_reader :ran_action1
|
10
11
|
attr_reader :action_called
|
12
|
+
attr_reader :stoped_action_called
|
13
|
+
|
14
|
+
before_action :run_action1
|
15
|
+
before_action :run_action2, only: [:stoped_action]
|
11
16
|
|
12
17
|
def just_call_an_action
|
13
18
|
@action_called = true
|
@@ -45,6 +50,18 @@ if RUBY_PLATFORM != 'opal'
|
|
45
50
|
def access_body
|
46
51
|
render json: JSON.parse(request.body.read)
|
47
52
|
end
|
53
|
+
|
54
|
+
def stoped_action
|
55
|
+
@stoped_action_called = true
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_action1
|
59
|
+
@ran_action1 = true
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_action2
|
63
|
+
stop_chain
|
64
|
+
end
|
48
65
|
end
|
49
66
|
|
50
67
|
let(:app) { ->(env) { [404, env, 'app'] } }
|
@@ -128,5 +145,15 @@ if RUBY_PLATFORM != 'opal'
|
|
128
145
|
{ test: 'params' }.to_json)
|
129
146
|
expect(response.body).to eq({ test: 'params' }.to_json)
|
130
147
|
end
|
148
|
+
|
149
|
+
it 'should run the before action' do
|
150
|
+
controller.perform(:render_plain_text)
|
151
|
+
expect(controller.ran_action1).to be(true)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should not call the stoped_action' do
|
155
|
+
controller.perform(:stoped_action)
|
156
|
+
expect(controller.stoped_action_called).to be_nil
|
157
|
+
end
|
131
158
|
end
|
132
159
|
end
|
@@ -186,6 +186,35 @@ describe 'bindings test', type: :feature, sauce: true do
|
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|
189
|
+
describe 'each binding' do
|
190
|
+
it 'should display the last assignment even if the previous assignment resolved afterwards' do
|
191
|
+
visit '/'
|
192
|
+
|
193
|
+
click_link 'Bindings'
|
194
|
+
|
195
|
+
click_link 'Show with Delay'
|
196
|
+
|
197
|
+
sleep 0.2
|
198
|
+
|
199
|
+
expect(find('#eachbinding li:first-child')).to have_content('901')
|
200
|
+
expect(page).to have_selector('#eachbinding li', count: 100)
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should display the last assignment regardless whether the previous promise has already been resolved' do
|
204
|
+
visit '/'
|
205
|
+
|
206
|
+
click_link 'Bindings'
|
207
|
+
|
208
|
+
click_link 'Show without Delay'
|
209
|
+
|
210
|
+
sleep 0.2
|
211
|
+
|
212
|
+
expect(find('#eachbinding li:first-child')).to have_content('1')
|
213
|
+
expect(page).to have_selector('#eachbinding li', count: 200)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
|
189
218
|
describe 'if/unless binding' do
|
190
219
|
it 'should show corret text' do
|
191
220
|
visit '/'
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe 'store', type: :feature, sauce: true do
|
4
|
-
|
5
|
-
|
3
|
+
# describe 'store', type: :feature, sauce: true do
|
4
|
+
# it 'should sync between nested root properties on store' do
|
5
|
+
# visit '/store'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
7
|
+
# fill_in('field1', with: 'should sync')
|
8
|
+
# expect(find('#field2').value).to eq('should sync')
|
9
|
+
# end
|
10
|
+
# end
|
data/spec/models/model_spec.rb
CHANGED
@@ -591,4 +591,14 @@ describe Volt::Model do
|
|
591
591
|
'Model does not have a parent and cannot be deleted.')
|
592
592
|
end
|
593
593
|
end
|
594
|
+
|
595
|
+
describe 'serialization' do
|
596
|
+
it 'supports JSON via to_json' do
|
597
|
+
model = Volt::Model.new({})
|
598
|
+
expect(model.to_json).to eq(model.to_h.to_json)
|
599
|
+
expect(model.to_json).to eq(model.to_h.to_json)
|
600
|
+
array_model = Volt::ArrayModel.new([model])
|
601
|
+
expect(array_model.to_json).to eq(array_model.to_a.to_json)
|
602
|
+
end
|
603
|
+
end
|
594
604
|
end
|
@@ -92,7 +92,7 @@ describe 'model permissions' do
|
|
92
92
|
# Clear the identity map, so we can load up a fresh copy
|
93
93
|
model.save_to.persistor.clear_identity_map
|
94
94
|
|
95
|
-
reloaded = store._test_deny_read_names.
|
95
|
+
reloaded = store._test_deny_read_names.first.sync
|
96
96
|
|
97
97
|
expect(reloaded._name).to eq(nil)
|
98
98
|
expect(reloaded._other).to eq('should be visible')
|
@@ -106,13 +106,16 @@ describe 'model permissions' do
|
|
106
106
|
# Saved
|
107
107
|
count = 0
|
108
108
|
|
109
|
-
store._test_deny_deletes.delete(model).
|
109
|
+
store._test_deny_deletes.delete(model).fail do |err|
|
110
110
|
# deleted
|
111
111
|
count += 1
|
112
|
-
|
112
|
+
|
113
|
+
match = !!(err =~ /permissions did not allow delete for /)
|
114
|
+
expect(match).to eq(true)
|
115
|
+
end.sync
|
113
116
|
|
114
117
|
expect(count).to eq(1)
|
115
|
-
end
|
118
|
+
end.sync
|
116
119
|
end
|
117
120
|
|
118
121
|
it 'should not check the read permissions when updating (so that all fields are present for the permissions check)' do
|