fron 0.1.4 → 0.2.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.reek +11 -0
  4. data/.rubocop.yml +54 -0
  5. data/.travis.yml +11 -0
  6. data/.yardopts +4 -0
  7. data/Changelog.md +7 -0
  8. data/Gemfile +3 -1
  9. data/Gemfile.lock +106 -15
  10. data/Rakefile +19 -15
  11. data/Readme.md +23 -0
  12. data/fron.gemspec +2 -2
  13. data/lib/fron/version.rb +2 -1
  14. data/opal/fron.rb +5 -5
  15. data/opal/fron/core.rb +3 -10
  16. data/opal/fron/core/behaviors/components.rb +42 -0
  17. data/opal/fron/core/behaviors/events.rb +27 -0
  18. data/opal/fron/core/behaviors/routes.rb +59 -0
  19. data/opal/fron/core/component.rb +64 -90
  20. data/opal/fron/core/eventable.rb +18 -0
  21. data/opal/fron/core/logger.rb +10 -1
  22. data/opal/fron/core_ext.rb +9 -0
  23. data/opal/fron/core_ext/array.rb +12 -0
  24. data/opal/fron/core_ext/date.rb +57 -0
  25. data/opal/fron/core_ext/hash.rb +52 -0
  26. data/opal/fron/core_ext/kernel.rb +57 -0
  27. data/opal/fron/core_ext/nil.rb +7 -0
  28. data/opal/fron/core_ext/numeric.rb +19 -0
  29. data/opal/fron/core_ext/object.rb +11 -0
  30. data/opal/fron/core_ext/proc.rb +19 -0
  31. data/opal/fron/{core-ext → core_ext}/string.rb +4 -0
  32. data/opal/fron/dom.rb +15 -13
  33. data/opal/fron/dom/document.rb +22 -6
  34. data/opal/fron/dom/element.rb +105 -67
  35. data/opal/fron/dom/event.rb +110 -40
  36. data/opal/fron/dom/{file-reader.rb → file_reader.rb} +6 -1
  37. data/opal/fron/dom/fragment.rb +2 -0
  38. data/opal/fron/dom/modules/attributes.rb +43 -0
  39. data/opal/fron/dom/modules/classlist.rb +26 -13
  40. data/opal/fron/dom/modules/dimensions.rb +79 -9
  41. data/opal/fron/dom/modules/element_accessor.rb +35 -0
  42. data/opal/fron/dom/modules/events.rb +67 -20
  43. data/opal/fron/dom/node.rb +98 -39
  44. data/opal/fron/dom/nodelist.rb +9 -2
  45. data/opal/fron/dom/style.rb +23 -2
  46. data/opal/fron/dom/text.rb +4 -0
  47. data/opal/fron/dom/window.rb +31 -2
  48. data/opal/fron/event_mock.rb +54 -0
  49. data/opal/fron/js/syntetic_event.js +16 -0
  50. data/opal/fron/request.rb +2 -2
  51. data/opal/fron/request/request.rb +77 -14
  52. data/opal/fron/request/response.rb +33 -6
  53. data/opal/fron/storage.rb +1 -1
  54. data/opal/fron/storage/local_storage.rb +54 -0
  55. data/opal/fron/utils/drag.rb +135 -0
  56. data/opal/fron/utils/keyboard.rb +70 -0
  57. data/opal/fron/utils/point.rb +78 -0
  58. data/opal/fron/utils/render_proc.rb +27 -0
  59. data/spec/core-ext/array_spec.rb +15 -0
  60. data/spec/core-ext/date_spec.rb +54 -0
  61. data/spec/core-ext/hash_spec.rb +18 -2
  62. data/spec/core-ext/kernel_spec.rb +57 -0
  63. data/spec/core-ext/nil_spec.rb +9 -0
  64. data/spec/core-ext/numeric_spec.rb +25 -0
  65. data/spec/core-ext/proc_spec.rb +15 -0
  66. data/spec/core-ext/string_spec.rb +11 -0
  67. data/spec/core/behaviors/events_spec.rb +25 -0
  68. data/spec/core/behaviors/routes_spec.rb +59 -0
  69. data/spec/core/component_inheritance_spec.rb +26 -16
  70. data/spec/core/component_spec.rb +25 -29
  71. data/spec/core/eventable_spec.rb +19 -19
  72. data/spec/core/logger_spec.rb +5 -6
  73. data/spec/dom/document_spec.rb +4 -5
  74. data/spec/dom/element_spec.rb +106 -15
  75. data/spec/dom/event_spec.rb +101 -61
  76. data/spec/dom/file_reader_spec.rb +11 -0
  77. data/spec/dom/fragment_spec.rb +3 -4
  78. data/spec/dom/instance_retaining_spec.rb +58 -0
  79. data/spec/dom/modules/classlist_spec.rb +18 -19
  80. data/spec/dom/modules/dimensions_spec.rb +87 -22
  81. data/spec/dom/modules/events_spec.rb +22 -8
  82. data/spec/dom/node_spec.rb +25 -17
  83. data/spec/dom/nodelist_spec.rb +2 -3
  84. data/spec/dom/style_spec.rb +6 -5
  85. data/spec/dom/text_spec.rb +4 -3
  86. data/spec/dom/window_spec.rb +24 -9
  87. data/spec/js/mocks.js +14 -0
  88. data/spec/request/request_spec.rb +34 -15
  89. data/spec/request/response_spec.rb +9 -10
  90. data/spec/spec_helper.rb +11 -0
  91. data/spec/storage/{local-storage_spec.rb → local_storage_spec.rb} +6 -7
  92. data/spec/utils/drag_spec.rb +136 -0
  93. data/spec/utils/keyboard_spec.rb +75 -0
  94. data/spec/utils/point_spec.rb +55 -0
  95. data/spec/utils/render_proc_spec.rb +18 -0
  96. metadata +58 -36
  97. data/docs/application.md +0 -7
  98. data/docs/configuration.md +0 -29
  99. data/docs/controllers.md +0 -35
  100. data/docs/routing.md +0 -63
  101. data/opal/fron/core-ext.rb +0 -5
  102. data/opal/fron/core-ext/hash.rb +0 -31
  103. data/opal/fron/core-ext/kernel.rb +0 -10
  104. data/opal/fron/core-ext/numeric.rb +0 -9
  105. data/opal/fron/core-ext/proc.rb +0 -9
  106. data/opal/fron/core/adapters/local.rb +0 -43
  107. data/opal/fron/core/adapters/rails.rb +0 -65
  108. data/opal/fron/core/application.rb +0 -42
  109. data/opal/fron/core/configuration.rb +0 -29
  110. data/opal/fron/core/controller.rb +0 -41
  111. data/opal/fron/core/model.rb +0 -90
  112. data/opal/fron/core/router.rb +0 -86
  113. data/opal/fron/storage/local-storage.rb +0 -34
  114. data/spec/core/adapter/local_spec.rb +0 -65
  115. data/spec/core/adapter/rails_spec.rb +0 -77
  116. data/spec/core/application_spec.rb +0 -35
  117. data/spec/core/configuration_spec.rb +0 -20
  118. data/spec/core/controlller_spec.rb +0 -68
  119. data/spec/core/model_spec.rb +0 -125
  120. data/spec/core/router_spec.rb +0 -124
@@ -1,9 +1,10 @@
1
- describe DOM::Text do
1
+ require 'spec_helper'
2
2
 
3
+ describe DOM::Text do
3
4
  subject { described_class.new('test') }
4
- let(:el) { subject.instance_variable_get("@el") }
5
+ let(:el) { subject.instance_variable_get('@el') }
5
6
 
6
- describe "#initailize" do
7
+ describe '#initailize' do
7
8
  it 'should create textNode with given value' do
8
9
  subject.text.should eq 'test'
9
10
  `#{el} instanceof Text`.should be true
@@ -1,30 +1,45 @@
1
- describe DOM::Window do
1
+ require 'spec_helper'
2
2
 
3
+ describe DOM::Window do
3
4
  subject { described_class }
4
5
 
5
- describe "#hash" do
6
+ describe '#state' do
7
+ it 'should return the pathname' do
8
+ subject.state.should eq '/'
9
+ end
10
+ end
11
+
12
+ describe '#state=' do
13
+ it 'should set the state' do
14
+ subject.should receive(:trigger).with 'popstate'
15
+ subject.state = '/test'
16
+ subject.state.should eq '/test'
17
+ end
18
+ end
19
+
20
+ describe '#hash' do
6
21
  it 'should return the hash of the url' do
7
22
  `window.location.hash = 'test'`
8
23
  subject.hash.should eq 'test'
9
24
  end
10
25
  end
11
26
 
12
- describe "#hash=" do
27
+ describe '#hash=' do
13
28
  it 'should set the hash of the url' do
14
- subject.hash = 'test'
15
- `window.location.hash.slice(1)`.should eq 'test'
29
+ subject.hash = 'test2'
30
+ `window.location.hash.slice(1)`.should eq 'test2'
16
31
  end
17
32
  end
18
33
 
19
- describe "scrollY" do
34
+ describe 'scrollY' do
20
35
  it 'should return the vertical scroll position' do
21
- subject.scrollY.should eq 0
36
+ subject.scroll_y.should eq 0
22
37
  end
23
38
  end
24
39
 
25
- describe "scrollX" do
40
+ describe 'scrollX' do
26
41
  it 'should return the horizontal scroll position' do
27
- subject.scrollX.should eq 0
42
+ subject.scroll_x.should eq 0
28
43
  end
29
44
  end
30
45
  end
@@ -0,0 +1,14 @@
1
+ window.requestAnimationFrame = function(callback){ callback() }
2
+ window.setTimeout = function(callback) { callback() }
3
+ window.clearTimeout = function() { return true }
4
+ window.alert = function(text) { return 'alert' }
5
+ window.confirm = function(text) { return true }
6
+ window.prompt = function(text, value) { return value }
7
+
8
+ window.FileReader = function(){}
9
+ window.FileReader.prototype.readAsDataURL = function(){
10
+ return 'data:image/gif;base64,R0lGODlhyAAiALM...DfD0QAADs='
11
+ }
12
+
13
+ window.throttle = function(fn){ return fn }
14
+ window.debounce = function(fn){ return fn }
@@ -1,23 +1,26 @@
1
- require 'fron/request'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Fron::Request do
4
-
5
- subject { described_class.new 'url' }
6
- let(:request) {%x{
7
- return { readyState: 0,
8
- open: function(){this.opened = true},
9
- send: function(){this.sent = true}}
10
- }}
11
- let(:data) { double :data, to_query_string: '', to_form_data: true }
4
+ subject { described_class.new 'url', 'Content-Type' => 'application/json' }
5
+ let(:request) {
6
+ %x{
7
+ return { readyState: 0,
8
+ open: function(){this.opened = true},
9
+ send: function(){this.sent = true},
10
+ setRequestHeader: function(){},
11
+ getAllResponseHeaders: function(){return ''}}
12
+ }
13
+ }
14
+ let(:data) { Hash.new }
12
15
 
13
16
  before do
14
- subject.instance_variable_set("@request", request)
17
+ subject.instance_variable_set('@request', request)
15
18
  end
16
19
 
17
- describe "#request" do
20
+ describe '#request' do
18
21
  it 'should raise if the rquest is already running' do
19
22
  allow(subject).to receive(:ready_state).and_return 1
20
- expect(Proc.new {subject.request} ).to raise_error
23
+ expect(proc { subject.request }).to raise_error
21
24
  end
22
25
 
23
26
  it 'should call #open on request' do
@@ -30,6 +33,11 @@ describe Fron::Request do
30
33
  expect(`#{request}.sent`).to be true
31
34
  end
32
35
 
36
+ it 'should call #to_form_data on data if it is an UPLOAD' do
37
+ expect(data).to receive(:to_form_data)
38
+ subject.request 'UPLOAD', data
39
+ end
40
+
33
41
  it 'should call #to_query_string on data if it is a GET' do
34
42
  expect(data).to receive(:to_query_string)
35
43
  expect(data).not_to receive(:to_json)
@@ -48,24 +56,35 @@ describe Fron::Request do
48
56
  end
49
57
  end
50
58
 
51
- describe "#get" do
59
+ describe '#get' do
52
60
  it 'should call #request with GET' do
53
61
  expect(subject).to receive(:request).once
54
62
  subject.get
55
63
  end
56
64
  end
57
65
 
58
- describe "#post" do
66
+ describe '#post' do
59
67
  it 'should call #request with POST' do
60
68
  expect(subject).to receive(:request).once
61
69
  subject.post
62
70
  end
63
71
  end
64
72
 
65
- describe "#put" do
73
+ describe '#put' do
66
74
  it 'should call #request with PUT' do
67
75
  expect(subject).to receive(:request).once
68
76
  subject.put
69
77
  end
70
78
  end
79
+
80
+ describe '#handle_state_change' do
81
+ it 'should run callback' do
82
+ callback = proc {}
83
+ subject.instance_variable_set('@callback', callback)
84
+ callback.should receive(:call)
85
+ subject.should receive(:ready_state).and_return 4
86
+ subject.should receive(:trigger).with :loaded
87
+ subject.handle_state_change
88
+ end
89
+ end
71
90
  end
@@ -1,14 +1,13 @@
1
- require 'fron/request'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Fron::Response do
4
-
5
- let(:headers) { "Content-Type: application/json"}
4
+ let(:headers) { 'Content-Type: application/json' }
6
5
  let(:status) { 200 }
7
- let(:body) {'<div></div>'}
6
+ let(:body) { '<div></div>' }
8
7
  subject { described_class.new status, body, headers }
9
8
 
10
- describe "#json" do
11
- let(:body) { {key: 'value'}.to_json }
9
+ describe '#json' do
10
+ let(:body) { { key: 'value' }.to_json }
12
11
 
13
12
  it 'should return the json body as a hash' do
14
13
  subject.json.class.should eq Hash
@@ -16,14 +15,14 @@ describe Fron::Response do
16
15
  end
17
16
  end
18
17
 
19
- describe "#ok?" do
20
- context "200" do
18
+ describe '#ok?' do
19
+ context '200' do
21
20
  it 'should return true if status is 200' do
22
21
  subject.ok?.should be true
23
22
  end
24
23
  end
25
24
 
26
- context "404" do
25
+ context '404' do
27
26
  let(:status) { 404 }
28
27
  it 'should return false if status is not 200' do
29
28
  subject.ok?.should be false
@@ -31,7 +30,7 @@ describe Fron::Response do
31
30
  end
32
31
  end
33
32
 
34
- describe "#dom" do
33
+ describe '#dom' do
35
34
  it 'should return with a Fragment' do
36
35
  subject.dom.class.should eq DOM::Fragment
37
36
  subject.dom.children[0].should_not be nil
@@ -0,0 +1,11 @@
1
+ require 'rspec_coverage_helper'
2
+ require 'js/mocks'
3
+ require 'fron'
4
+ require 'fron/event_mock'
5
+
6
+ ::RSpec.configure do |c|
7
+ c.after(:each) do
8
+ DOM::Document.body.off
9
+ DOM::Window.off
10
+ end
11
+ end
@@ -1,15 +1,14 @@
1
- require 'fron/storage'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Fron::Storage::LocalStorage do
4
-
5
4
  subject { described_class }
6
5
 
7
6
  before do
8
7
  subject.clear
9
- subject.set 'key', { data: 'value' }
8
+ subject.set 'key', data: 'value'
10
9
  end
11
10
 
12
- describe "#get" do
11
+ describe '#get' do
13
12
  it 'should get the data for the key' do
14
13
  data = subject.get('key')
15
14
  data.class.should eq Hash
@@ -17,9 +16,9 @@ describe Fron::Storage::LocalStorage do
17
16
  end
18
17
  end
19
18
 
20
- describe "#set" do
19
+ describe '#set' do
21
20
  it 'should set data for the key' do
22
- subject.set 'key2', { data: 'value' }
21
+ subject.set 'key2', data: 'value'
23
22
  subject.keys.include?('key2').should be true
24
23
  subject.all.length.should be 2
25
24
  end
@@ -40,7 +39,7 @@ describe Fron::Storage::LocalStorage do
40
39
  end
41
40
  end
42
41
 
43
- describe "#all" do
42
+ describe '#all' do
44
43
  it 'should get the data for all key' do
45
44
  data = subject.all[0]
46
45
  data.class.should eq Hash
@@ -0,0 +1,136 @@
1
+ require 'spec_helper'
2
+ require 'fron/utils/drag'
3
+
4
+ describe Fron::Drag do
5
+ let(:event) { double(pageX: 0, pageY: 0, preventDefult: true, stop: true, target: true) }
6
+ let(:base) { DOM::Element.new 'div' }
7
+ let(:position) { double }
8
+
9
+ subject { described_class.new base }
10
+
11
+ before do
12
+ allow(subject).to receive(:request_animation_frame)
13
+ end
14
+
15
+ around(:each) do |example|
16
+ EventMock.mock_events(&example)
17
+ end
18
+
19
+ describe 'Events' do
20
+ it 'should call start on mousedown' do
21
+ subject.should receive(:start)
22
+ subject.base.trigger 'mousedown'
23
+ end
24
+
25
+ it 'should call pos when mouse moves' do
26
+ subject.should receive(:pos)
27
+ subject.should receive(:request_animation_frame) do |&block|
28
+ subject.instance_variable_set('@mouse_is_down', false)
29
+ block.call
30
+ end
31
+ subject.start event
32
+ subject.body.trigger 'mousemove'
33
+ end
34
+
35
+ it 'should call up when mouse moves' do
36
+ subject.should receive(:up)
37
+ subject.start event
38
+ subject.body.trigger 'mouseup'
39
+ end
40
+ end
41
+
42
+ describe '#initialize' do
43
+ it 'should set the body' do
44
+ subject.body.should eq DOM::Document.body
45
+ end
46
+
47
+ it 'should add mousedown event listener to the base' do
48
+ subject.base.listeners['mousedown'].length.should eq 1
49
+ end
50
+ end
51
+
52
+ describe '#diff' do
53
+ it 'should diff start position and current position' do
54
+ subject.instance_variable_set('@start_position', position)
55
+ position.should receive(:-)
56
+ subject.diff
57
+ end
58
+ end
59
+
60
+ describe '#start' do
61
+ it 'should call request_animation_frame' do
62
+ subject.should receive(:request_animation_frame).once
63
+ subject.start event
64
+ end
65
+
66
+ it 'should remove events if the dragging not finished properly' do
67
+ subject.instance_variable_set('@pos_method', true)
68
+ subject.should receive(:off)
69
+ subject.start event
70
+ end
71
+ end
72
+
73
+ describe '#pos' do
74
+ it 'it should set position' do
75
+ event.should receive(:stop)
76
+ position.should receive(:distance).and_return 0
77
+ subject.should receive(:diff).and_return position
78
+ subject.should receive(:position).and_return position
79
+ subject.pos event
80
+ pos = subject.instance_variable_get('@position')
81
+ pos.should eq position
82
+ end
83
+ end
84
+
85
+ describe '#up' do
86
+ it 'should stop dragging and reset things' do
87
+ event.should receive(:stop)
88
+ event.should receive(:preventDefault)
89
+ subject.instance_variable_set('@started', true)
90
+ subject.should receive(:reset)
91
+ subject.should receive(:off)
92
+ subject.should receive(:trigger).with 'end'
93
+ subject.up event
94
+ end
95
+ end
96
+
97
+ describe '#move' do
98
+ it 'should call request_animation_frame if mouse is down' do
99
+ subject.instance_variable_set('@mouse_is_down', true)
100
+ subject.should receive(:request_animation_frame) do |&block|
101
+ subject.instance_variable_set('@mouse_is_down', false)
102
+ block.call
103
+ end
104
+ subject.move
105
+ end
106
+
107
+ it 'should trigger move if dragging' do
108
+ subject.instance_variable_set('@started', true)
109
+ subject.instance_variable_set('@position', position)
110
+ subject.should receive(:trigger).with 'move', position
111
+ subject.move
112
+ end
113
+
114
+ it 'should not trigger move if not dragging' do
115
+ subject.should_not receive(:trigger)
116
+ subject.should_not receive(:request_animation_frame)
117
+ subject.move
118
+ end
119
+ end
120
+
121
+ describe '#off' do
122
+ it 'should remove events' do
123
+ subject.body.should receive(:off).at_least(2).times
124
+ subject.off
125
+ end
126
+ end
127
+
128
+ describe '#position' do
129
+ it 'should return the current position' do
130
+ pos = subject.position event
131
+ pos.should be_a Fron::Point
132
+ pos.x.should eq 0
133
+ pos.y.should eq 0
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ require 'fron/utils/keyboard'
3
+
4
+ # Test Keyboard Class
5
+ class TestKeyboard < Fron::Keyboard
6
+ sc 'ctrl+up'
7
+ end
8
+
9
+ describe TestKeyboard do
10
+ let(:event) { DOM::Event.new `{ctrlKey: true, altKey: true, shiftKey: true, keyCode: 38}` }
11
+
12
+ describe Fron::Keyboard do
13
+ it 'should work on its own' do
14
+ Fron::Keyboard.new.should be_a Fron::Keyboard
15
+ end
16
+ end
17
+
18
+ describe 'DSL' do
19
+ subject { described_class }
20
+
21
+ describe '#sc' do
22
+ it 'should define a shortcut with action' do
23
+ subject.sc 'ctrl+down', :test
24
+ subject.shortcuts.last.should eq(
25
+ parts: %w(ctrl down),
26
+ action: :test,
27
+ block: nil
28
+ )
29
+ end
30
+
31
+ it 'should define a shortcut with block' do
32
+ sc = subject.shortcuts.first
33
+ sc[:parts].should eq %w(ctrl up)
34
+ sc[:action].should eq nil
35
+ end
36
+ end
37
+ end
38
+
39
+ describe 'Events' do
40
+ it 'should handle keydown' do
41
+ subject.should receive(:keydown)
42
+ DOM::Document.body.listeners[:keydown].count.should eq 1
43
+ DOM::Document.body.listeners[:keydown][0].call {}
44
+ end
45
+ end
46
+
47
+ describe '#keydown' do
48
+ let(:shortcut) { { parts: %w(ctrl alt shift up) } }
49
+
50
+ it 'should match shortcuts to the combo' do
51
+ described_class.instance_variable_set('@shortcuts', [{ parts: [] }, shortcut])
52
+ subject.should receive(:handle_shortcut).with shortcut
53
+ event.should receive(:stop)
54
+ subject.keydown event
55
+ end
56
+ end
57
+
58
+ describe 'handle_shortcut' do
59
+ it 'should run block if block given' do
60
+ sc = { block: proc {} }
61
+ subject.should receive(:instance_exec)
62
+ subject.handle_shortcut sc
63
+ end
64
+
65
+ it 'should call action method if given' do
66
+ subject.should receive(:test)
67
+ subject.handle_shortcut action: :test
68
+ end
69
+
70
+ it 'should warn if method is not exists' do
71
+ subject.should receive(:warn)
72
+ subject.handle_shortcut action: :test2, parts: %w(a b)
73
+ end
74
+ end
75
+ end