unpoly-rails 0.56.7 → 0.57.0

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.

Potentially problematic release.


This version of unpoly-rails might be problematic. Click here for more details.

Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +74 -1
  3. data/dist/unpoly.js +1569 -793
  4. data/dist/unpoly.min.js +4 -4
  5. data/lib/assets/javascripts/unpoly.coffee +2 -0
  6. data/lib/assets/javascripts/unpoly/browser.coffee.erb +25 -41
  7. data/lib/assets/javascripts/unpoly/bus.coffee.erb +20 -6
  8. data/lib/assets/javascripts/unpoly/classes/cache.coffee +23 -13
  9. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +87 -0
  10. data/lib/assets/javascripts/unpoly/classes/focus_tracker.coffee +29 -0
  11. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +7 -4
  12. data/lib/assets/javascripts/unpoly/classes/record.coffee +1 -1
  13. data/lib/assets/javascripts/unpoly/classes/request.coffee +38 -45
  14. data/lib/assets/javascripts/unpoly/classes/response.coffee +16 -1
  15. data/lib/assets/javascripts/unpoly/classes/store/memory.coffee +26 -0
  16. data/lib/assets/javascripts/unpoly/classes/store/session.coffee +59 -0
  17. data/lib/assets/javascripts/unpoly/cookie.coffee +56 -0
  18. data/lib/assets/javascripts/unpoly/dom.coffee.erb +67 -39
  19. data/lib/assets/javascripts/unpoly/feedback.coffee +2 -2
  20. data/lib/assets/javascripts/unpoly/form.coffee.erb +23 -12
  21. data/lib/assets/javascripts/unpoly/history.coffee +2 -2
  22. data/lib/assets/javascripts/unpoly/layout.coffee.erb +118 -99
  23. data/lib/assets/javascripts/unpoly/link.coffee.erb +12 -5
  24. data/lib/assets/javascripts/unpoly/log.coffee +6 -5
  25. data/lib/assets/javascripts/unpoly/modal.coffee.erb +9 -2
  26. data/lib/assets/javascripts/unpoly/motion.coffee.erb +2 -6
  27. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +2 -2
  28. data/lib/assets/javascripts/unpoly/params.coffee.erb +522 -0
  29. data/lib/assets/javascripts/unpoly/popup.coffee.erb +3 -3
  30. data/lib/assets/javascripts/unpoly/proxy.coffee +42 -34
  31. data/lib/assets/javascripts/unpoly/{syntax.coffee → syntax.coffee.erb} +59 -117
  32. data/lib/assets/javascripts/unpoly/{util.coffee → util.coffee.erb} +206 -171
  33. data/lib/unpoly/rails/version.rb +1 -1
  34. data/package.json +1 -1
  35. data/spec_app/Gemfile.lock +1 -1
  36. data/spec_app/app/assets/javascripts/integration_test.coffee +0 -4
  37. data/spec_app/app/assets/stylesheets/integration_test.sass +7 -1
  38. data/spec_app/app/controllers/pages_controller.rb +4 -0
  39. data/spec_app/app/views/form_test/basics/new.erb +34 -5
  40. data/spec_app/app/views/form_test/submission_result.erb +2 -2
  41. data/spec_app/app/views/form_test/uploads/new.erb +15 -2
  42. data/spec_app/app/views/hash_test/unpoly.erb +30 -0
  43. data/spec_app/app/views/pages/start.erb +2 -1
  44. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +17 -2
  45. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +5 -0
  46. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +1 -1
  47. data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +5 -0
  48. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +8 -8
  49. data/spec_app/spec/javascripts/up/bus_spec.js.coffee +58 -20
  50. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +78 -0
  51. data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +31 -0
  52. data/spec_app/spec/javascripts/up/classes/request_spec.coffee +50 -0
  53. data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +67 -0
  54. data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +113 -0
  55. data/spec_app/spec/javascripts/up/dom_spec.js.coffee +133 -45
  56. data/spec_app/spec/javascripts/up/form_spec.js.coffee +13 -13
  57. data/spec_app/spec/javascripts/up/layout_spec.js.coffee +110 -26
  58. data/spec_app/spec/javascripts/up/link_spec.js.coffee +1 -1
  59. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +1 -0
  60. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +52 -51
  61. data/spec_app/spec/javascripts/up/namespace_spec.js.coffee +2 -2
  62. data/spec_app/spec/javascripts/up/params_spec.coffee +768 -0
  63. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +75 -36
  64. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +48 -15
  65. data/spec_app/spec/javascripts/up/util_spec.js.coffee +148 -131
  66. metadata +17 -5
  67. data/spec_app/spec/javascripts/up/classes/.keep +0 -0
@@ -4,6 +4,6 @@ module Unpoly
4
4
  # The current version of the unpoly-rails gem.
5
5
  # This version number is also used for releases of the Unpoly
6
6
  # frontend code.
7
- VERSION = '0.56.7'
7
+ VERSION = '0.57.0'
8
8
  end
9
9
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unpoly",
3
- "version": "0.56.7",
3
+ "version": "0.57.0",
4
4
  "description": "Unobtrusive JavaScript framework",
5
5
  "main": "dist/unpoly.js",
6
6
  "files": [
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- unpoly-rails (0.56.6)
4
+ unpoly-rails (0.56.7)
5
5
  rails (>= 3)
6
6
 
7
7
  GEM
@@ -3,7 +3,3 @@
3
3
  #= require es6-promise.auto
4
4
  #= require helpers/knife
5
5
  #= require unpoly
6
-
7
- up.compiler '.compiler', ($element) ->
8
- console.error('*** Compiler called for %o', $element.get(0))
9
- -> console.error('*** Destructor called for %o', $element.get(0))
@@ -11,6 +11,7 @@ $block-spacing: 25px
11
11
  body
12
12
  margin: 0
13
13
  background: image-url('grid.png') repeat
14
+
14
15
  font-family: arial, sans-serif
15
16
 
16
17
  h1, h2, h3, h4, p
@@ -29,7 +30,8 @@ a
29
30
  height: 150px
30
31
  content: 'Free space'
31
32
 
32
- .fixed-top-bar
33
+ .fixed-top-bar,
34
+ .fixed-bottom-bar
33
35
  position: fixed
34
36
  z-index: 9999999
35
37
  top: 0
@@ -38,6 +40,10 @@ a
38
40
  background-color: transparentize(blue, 0.5)
39
41
  padding: 50px
40
42
 
43
+ .fixed-bottom-bar
44
+ top: auto
45
+ bottom: 0
46
+
41
47
  .example
42
48
  margin: 50px
43
49
  +clear-after
@@ -2,4 +2,8 @@ class PagesController < ApplicationController
2
2
 
3
3
  layout 'integration_test'
4
4
 
5
+ # def start
6
+ # cookies['baram'] = { value: 'baz;bam', expires: 2.days.from_now }
7
+ # end
8
+
5
9
  end
@@ -5,17 +5,46 @@
5
5
  <%= form_tag "/form_test/basic", method: :post, 'up-target' => '.result' do %>
6
6
 
7
7
  <p>
8
- <input type="text" name="text-param" value="text-value" />
8
+ <label>
9
+ input[type=text]
10
+ <input type="text" name="text-param" value="text-value" />
11
+ </label>
9
12
  </p>
10
13
 
11
14
  <p>
12
- <input type="password" name="password-param" value="password-value" />
15
+ <label>
16
+ input[type=password]
17
+ <input type="password" name="password-param" value="password-value" />
18
+ </label>
13
19
  </p>
14
20
 
15
21
  <p>
16
- <select name="select-param">
17
- <option value="select-value">select-label</option>
18
- </select>
22
+ <label>
23
+ input[type=checkbox]
24
+ <select name="checkbox-param">
25
+ <option value="checkbox-value">checkbox-label</option>
26
+ </select>
27
+ </label>
28
+ </p>
29
+
30
+ <p>
31
+ <label>
32
+ select
33
+ <select name="select-param">
34
+ <option value="select-value">select-label</option>
35
+ </select>
36
+ </label>
37
+ </p>
38
+
39
+ <p>
40
+ <label>
41
+ select[multiple]
42
+ <select name="multiple-select-param[]" multiple>
43
+ <option value="multiple-select-value-1">multiple-select-label-1</option>
44
+ <option value="multiple-select-value-2">multiple-select-label-2</option>
45
+ <option value="multiple-select-value-3">multiple-select-label-3</option>
46
+ </select>
47
+ </label>
19
48
  </p>
20
49
 
21
50
  <p>
@@ -11,7 +11,7 @@
11
11
  <dt><code><%= key %></code></dt>
12
12
  <dd>
13
13
  <% if value.is_a?(String) %>
14
- <pre><code><%= value %></code></pre>
14
+ <code><%= value %></code>
15
15
  <% elsif value.is_a?(ActionDispatch::Http::UploadedFile) %>
16
16
  <% if value.original_filename.ends_with?('.jpg') %>
17
17
  <img src="data:image/jpeg;base64,<%= Base64.encode64(value.read) %>">
@@ -21,7 +21,7 @@
21
21
  <%= value.original_filename %> (<%= value.size %> bytes)
22
22
  <% end %>
23
23
  <% else %>
24
- <%= value.inspect %>
24
+ <code><%= value.inspect %></code>
25
25
  <% end %>
26
26
  </dd>
27
27
  <% end %>
@@ -5,11 +5,24 @@
5
5
  <%= form_tag "/form_test/upload", method: :post, multipart: true, 'up-target' => '.result' do %>
6
6
 
7
7
  <p>
8
- <input type="text" name="text-param" value="text-value" />
8
+ <label>
9
+ input[type=text]
10
+ <input type="text" name="text-param" value="text-value" />
11
+ </label>
9
12
  </p>
10
13
 
11
14
  <p>
12
- <input type="file" name="file-param" />
15
+ <label>
16
+ input[type=file]
17
+ <input type="file" name="file-param" />
18
+ </label>
19
+ </p>
20
+
21
+ <p>
22
+ <label>
23
+ input[type=file][multiple]
24
+ <input type="file" name="multiple-file-param" multiple />
25
+ </label>
13
26
  </p>
14
27
 
15
28
  <p>
@@ -0,0 +1,30 @@
1
+ <div class="fixed-top-bar" up-fixed="top" style="background-color: rgba(40, 40, 40, 0.85)">
2
+ Obstruction
3
+ </div>
4
+
5
+ <div class="spacer">
6
+ </div>
7
+
8
+ <h1 style="margin: 0">Hash links (with Unpoly)</h1>
9
+
10
+ <div class="example" id="one" style="height: 1000px; background-color: yellow; margin: 0">
11
+ <h2 style="margin: 0">This is #one</h2>
12
+
13
+ <a href="#two" up-target=".page">Scroll down to #two</a>
14
+ </div>
15
+
16
+ <div class="example" id="two" style="height: 200px; background-color: green; margin: 0">
17
+ <h2 style="margin: 0">This is #two</h2>
18
+
19
+ <a href="#three" up-target=".page">Scroll down to #three</a>
20
+ </div>
21
+
22
+ <div class="example" id="three" style="height: 1000px; background-color: cyan; margin: 0">
23
+ <h2 style="margin: 0">This is #three</h2>
24
+
25
+ <a href="#one" up-target=".page">Scroll up to #one</a>
26
+ </div>
27
+
28
+ <div class="fixed-bottom-bar" up-fixed="bottom" style="background-color: rgba(40, 40, 40, 0.85)">
29
+ Obstruction
30
+ </div>
@@ -60,7 +60,8 @@
60
60
  <li><%= link_to 'Error', '/error_test/trigger' %></li>
61
61
  <li><%= link_to 'Booting with non-GET method', '/method_test/page1' %></li>
62
62
  <li><%= link_to 'Fragment update', '/replace_test/page1' %></li>
63
- <li><%= link_to 'Hash links (without Unpoly)', '/hash_test/vanilla' %></li>
63
+ <li><%= link_to 'Hash links (without Unpoly)', '/hash_test/vanilla#one' %></li>
64
+ <li><%= link_to 'Hash links (with Unpoly)', '/hash_test/unpoly#one' %></li>
64
65
  <li><%= link_to 'Revealing long pages', '/reveal_test/long1' %></li>
65
66
  <li><%= link_to 'Animations', '/motion_test/animations' %></li>
66
67
  <li><%= link_to 'Transitions', '/motion_test/transitions' %></li>
@@ -5,5 +5,20 @@ beforeEach ->
5
5
  up.util.isFormData(xhr.params)
6
6
 
7
7
  parse: (params) ->
8
- # Just return it
9
- params
8
+ if up.browser.canInspectFormData()
9
+ array = up.params.toArray(params)
10
+ else if params.originalArray
11
+ # In browser that don't support FormData#entries(),
12
+ # up.params.toArray() stores the original array with the generated
13
+ # FormData object.
14
+ array = params.originalArray
15
+ else
16
+ throw "Cannot parse FormData for inspection in tests"
17
+
18
+ obj = {}
19
+
20
+ for entry in array
21
+ obj[entry.name] ||= []
22
+ obj[entry.name].push(entry.value)
23
+
24
+ obj
@@ -1,10 +1,15 @@
1
1
  afterEach (done) ->
2
+ # If the spec has installed the Jasmine clock, uninstall it so
3
+ # the timeout below will actually happen.
4
+ jasmine.clock().uninstall()
5
+
2
6
  # Wait one more frame so pending callbacks have a chance to run.
3
7
  # Pending callbacks might change the URL or cause errors that bleed into
4
8
  # the next example.
5
9
 
6
10
  up.util.nextFrame =>
7
11
  up.reset()
12
+ up.browser.popCookie(up.protocol.config.methodCookie)
8
13
 
9
14
  # Give async reset behavior another frame to play out,
10
15
  # then start the next example.
@@ -2,4 +2,4 @@ beforeEach ->
2
2
  jasmine.addMatchers
3
3
  toBeError: (util, customEqualityTesters) ->
4
4
  compare: (actual, message) ->
5
- pass: (actual instanceof Error) && (!message || (message instanceof RegExp && actual.message =~ message) || actual.message == message)
5
+ pass: (actual instanceof Error) && (!message || (message instanceof RegExp && message.test(actual.message)) || actual.message == message)
@@ -0,0 +1,5 @@
1
+ beforeEach ->
2
+ jasmine.addMatchers
3
+ toMatchSelector: (util, customEqualityTesters) ->
4
+ compare: (actualElement, expectedSelector) ->
5
+ pass: $(actualElement).is(expectedSelector)
@@ -13,9 +13,9 @@ describe 'up.browser', ->
13
13
 
14
14
  describe "for GET requests", ->
15
15
 
16
- it "creates a GET form, adds all { data } params as hidden fields and submits the form", ->
16
+ it "creates a GET form, adds all { params } as hidden fields and submits the form", ->
17
17
  submitForm = spyOn(up.browser, 'submitForm')
18
- up.browser.navigate('/foo', method: 'GET', data: { param1: 'param1 value', param2: 'param2 value' })
18
+ up.browser.navigate('/foo', method: 'GET', params: { param1: 'param1 value', param2: 'param2 value' })
19
19
  expect(submitForm).toHaveBeenCalled()
20
20
  $form = $('form.up-page-loader')
21
21
  expect($form).toExist()
@@ -25,9 +25,9 @@ describe 'up.browser', ->
25
25
  expect($form.find('input[name="param1"][value="param1 value"]')).toExist()
26
26
  expect($form.find('input[name="param2"][value="param2 value"]')).toExist()
27
27
 
28
- it 'merges params from the given URL and the { data } option', ->
28
+ it 'merges params from the given URL and the { params } option', ->
29
29
  submitForm = spyOn(up.browser, 'submitForm')
30
- up.browser.navigate('/foo?param1=param1%20value', method: 'GET', data: { param2: 'param2 value' })
30
+ up.browser.navigate('/foo?param1=param1%20value', method: 'GET', params: { param2: 'param2 value' })
31
31
  expect(submitForm).toHaveBeenCalled()
32
32
  $form = $('form.up-page-loader')
33
33
  expect($form).toExist()
@@ -39,9 +39,9 @@ describe 'up.browser', ->
39
39
 
40
40
  describe "for POST requests", ->
41
41
 
42
- it "creates a POST form, adds all { data } params as hidden fields and submits the form", ->
42
+ it "creates a POST form, adds all { params } params as hidden fields and submits the form", ->
43
43
  submitForm = spyOn(up.browser, 'submitForm')
44
- up.browser.navigate('/foo', method: 'POST', data: { param1: 'param1 value', param2: 'param2 value' })
44
+ up.browser.navigate('/foo', method: 'POST', params: { param1: 'param1 value', param2: 'param2 value' })
45
45
  expect(submitForm).toHaveBeenCalled()
46
46
  $form = $('form.up-page-loader')
47
47
  expect($form).toExist()
@@ -50,9 +50,9 @@ describe 'up.browser', ->
50
50
  expect($form.find('input[name="param1"][value="param1 value"]')).toExist()
51
51
  expect($form.find('input[name="param2"][value="param2 value"]')).toExist()
52
52
 
53
- it 'merges params from the given URL and the { data } option', ->
53
+ it 'merges params from the given URL and the { params } option', ->
54
54
  submitForm = spyOn(up.browser, 'submitForm')
55
- up.browser.navigate('/foo?param1=param1%20value', method: 'POST', data: { param2: 'param2 value' })
55
+ up.browser.navigate('/foo?param1=param1%20value', method: 'POST', params: { param2: 'param2 value' })
56
56
  expect(submitForm).toHaveBeenCalled()
57
57
  $form = $('form.up-page-loader')
58
58
  expect($form).toExist()
@@ -31,30 +31,68 @@ describe 'up.bus', ->
31
31
  next =>
32
32
  expect(clickSpy.calls.count()).toEqual(1)
33
33
 
34
- it 'parses an up-data attribute as JSON and passes the parsed object as a third argument to the initializer', asyncSpec (next) ->
35
- $child = affix('.child')
36
- observeArgs = jasmine.createSpy()
37
- up.on 'click', '.child', (event, $element, data) ->
38
- observeArgs($element.attr('class'), data)
34
+ it 'throws an error when trying to register the same callback multiple times', ->
35
+ callback = ->
36
+ register = -> up.on 'foo', callback
37
+ register()
38
+ expect(register).toThrowError(/cannot be registered more than once/i)
39
+
40
+ it 'does not throw an error if a callback is registered, unregistered and registered a second time', ->
41
+ callback = ->
42
+ register = -> up.on 'foo', callback
43
+ unregister = -> up.off 'foo', callback
44
+ register()
45
+ unregister()
46
+ expect(register).not.toThrowError()
47
+
48
+ describe 'passing of [up-data]', ->
49
+
50
+ it 'parses an [up-data] attribute as JSON and passes the parsed object as a third argument to the listener', asyncSpec (next) ->
51
+ $child = affix('.child')
52
+ observeArgs = jasmine.createSpy()
53
+ up.on 'click', '.child', (event, $element, data) ->
54
+ observeArgs($element.attr('class'), data)
55
+
56
+ data = { key1: 'value1', key2: 'value2' }
57
+ $tag = affix(".child").attr('up-data', JSON.stringify(data))
39
58
 
40
- data = { key1: 'value1', key2: 'value2' }
41
- $tag = affix(".child").attr('up-data', JSON.stringify(data))
59
+ Trigger.click($('.child'))
42
60
 
43
- Trigger.click($('.child'))
61
+ next =>
62
+ expect(observeArgs).toHaveBeenCalledWith('child', data)
44
63
 
45
- next =>
46
- expect(observeArgs).toHaveBeenCalledWith('child', data)
64
+ it 'passes an empty object as a second argument to the listener if there is no [up-data] attribute', asyncSpec (next) ->
65
+ $child = affix('.child')
66
+ observeArgs = jasmine.createSpy()
67
+ up.on 'click', '.child', (event, $element, data) ->
68
+ observeArgs($element.attr('class'), data)
47
69
 
48
- it 'passes an empty object as a second argument to the listener if there is no up-data attribute', asyncSpec (next) ->
49
- $child = affix('.child')
50
- observeArgs = jasmine.createSpy()
51
- up.on 'click', '.child', (event, $element, data) ->
52
- observeArgs($element.attr('class'), data)
70
+ Trigger.click($('.child'))
53
71
 
54
- Trigger.click($('.child'))
72
+ next =>
73
+ expect(observeArgs).toHaveBeenCalledWith('child', {})
55
74
 
56
- next =>
57
- expect(observeArgs).toHaveBeenCalledWith('child', {})
75
+ it 'does not parse an [up-data] attribute if the listener function only takes one argument', asyncSpec (next) ->
76
+ parseDataSpy = spyOn(up.syntax, 'data').and.returnValue({})
77
+
78
+ $child = affix('.child')
79
+ up.on 'click', '.child', (event) -> # no-op
80
+
81
+ Trigger.click($('.child'))
82
+
83
+ next =>
84
+ expect(parseDataSpy).not.toHaveBeenCalled()
85
+
86
+ it 'does not parse an [up-data] attribute if the listener function only takes two arguments', asyncSpec (next) ->
87
+ parseDataSpy = spyOn(up.syntax, 'data').and.returnValue({})
88
+
89
+ $child = affix('.child')
90
+ up.on 'click', '.child', (event, $element) -> # no-op
91
+
92
+ Trigger.click($('.child'))
93
+
94
+ next =>
95
+ expect(parseDataSpy).not.toHaveBeenCalled()
58
96
 
59
97
  describe 'up.off', ->
60
98
 
@@ -132,10 +170,10 @@ describe 'up.bus', ->
132
170
 
133
171
  expect(emittedEvent.$element).toEqual($element)
134
172
 
135
- describe 'up.bus.renamedEvent', ->
173
+ describe 'up.bus.deprecateRenamedEvent', ->
136
174
 
137
175
  it 'prints a warning and registers the event listener for the new event name', ->
138
- warnSpy = spyOn(up.log, 'warn')
176
+ warnSpy = spyOn(up, 'warn')
139
177
  listener = jasmine.createSpy('listener')
140
178
 
141
179
  # Reister listener for the old event name
@@ -1 +1,79 @@
1
1
  describe 'up.Cache', ->
2
+
3
+ describe '#get', ->
4
+
5
+ it 'returns an item that was previously set', ->
6
+ store = new up.Cache()
7
+ store.set('foo', 'value of foo')
8
+ store.set('bar', 'value of bar')
9
+
10
+ expect(store.get('foo')).toEqual('value of foo')
11
+ expect(store.get('bar')).toEqual('value of bar')
12
+
13
+ it 'returns undefined if no item with that key was set', ->
14
+ store = new up.Cache()
15
+ store.set('foo', 'value of foo')
16
+
17
+ expect(store.get('bar')).toBeUndefined()
18
+
19
+ it 'returns undefined if the item has expired', ->
20
+ jasmine.clock().install()
21
+ jasmine.clock().mockDate(new Date())
22
+
23
+ store = new up.Cache(expiry: 100, logPrefix: 'cache')
24
+ store.set('foo', 'value of foo')
25
+
26
+ jasmine.clock().tick(80)
27
+ expect(store.get('foo')).toEqual('value of foo')
28
+
29
+ jasmine.clock().tick(40)
30
+ expect(store.get('foo')).toBeUndefined()
31
+
32
+ describe '#set', ->
33
+
34
+ it 'removes the oldest item if setting a new item would exceed the cache size', ->
35
+ jasmine.clock().install()
36
+ store = new up.Cache(size: 2, logPrefix: 'cache')
37
+
38
+ store.set('foo', 'value of foo')
39
+ jasmine.clock().tick(10)
40
+ store.set('bar', 'value of bar')
41
+ jasmine.clock().tick(10)
42
+ store.set('baz', 'value of baz')
43
+
44
+ expect(store.get('foo')).toBeUndefined()
45
+ expect(store.get('bar')).toEqual('value of bar')
46
+ expect(store.get('baz')).toEqual('value of baz')
47
+
48
+ describe '#keys', ->
49
+
50
+ it 'returns an array of keys in the store', ->
51
+ store = new up.Cache()
52
+ store.set('foo', 'value of foo')
53
+ store.set('bar', 'value of bar')
54
+
55
+ expect(store.keys().sort()).toEqual ['bar', 'foo']
56
+
57
+ describe '#clear', ->
58
+
59
+ it 'removes all keys from the store', ->
60
+ store = new up.Cache()
61
+ store.set('foo', 'value of foo')
62
+ store.set('bar', 'value of bar')
63
+
64
+ store.clear()
65
+
66
+ expect(store.get('foo')).toBeUndefined()
67
+ expect(store.get('bar')).toBeUndefined()
68
+
69
+ describe '#remove', ->
70
+
71
+ it 'removes the given key from the store', ->
72
+ store = new up.Cache()
73
+ store.set('foo', 'value of foo')
74
+ store.set('bar', 'value of bar')
75
+
76
+ store.remove('foo')
77
+
78
+ expect(store.get('foo')).toBeUndefined()
79
+ expect(store.get('bar')).toEqual('value of bar')