appetizer-ui 0.9.0 → 0.9.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 (40) hide show
  1. data/appetizer-ui.gemspec +15 -13
  2. data/lib/appetizer/ui/assets.rb +21 -8
  3. data/lib/appetizer/ui/jasmine/js/jquery-jasmine.js +288 -0
  4. data/lib/appetizer/ui/jasmine/js/spec-runner.coffee +0 -1
  5. data/lib/appetizer/ui/jasmine/views/specs.erb +12 -4
  6. data/lib/appetizer/ui/rake.rb +29 -10
  7. data/lib/appetizer/ui/spec.rb +1 -2
  8. metadata +122 -61
  9. data/lib/appetizer/ui/app/js/appetizer.coffee +0 -15
  10. data/lib/appetizer/ui/app/js/appetizer/core.coffee +0 -20
  11. data/lib/appetizer/ui/app/js/appetizer/model.coffee +0 -1
  12. data/lib/appetizer/ui/app/js/appetizer/router.coffee +0 -70
  13. data/lib/appetizer/ui/app/js/appetizer/view.coffee +0 -139
  14. data/lib/appetizer/ui/app/js/appetizer/xdr.coffee +0 -57
  15. data/lib/appetizer/ui/app/views/client/appetizer/missing.jst.eco +0 -3
  16. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/appetizerExtensions.spec.js +0 -54
  17. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/checkboxConventionBindings.spec.js +0 -110
  18. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/configurableBindingAttributes.spec.js +0 -117
  19. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/configureAllBindingAttributes.spec.js +0 -139
  20. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/customConvention.spec.js +0 -53
  21. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/dataBindConvention.spec.js +0 -151
  22. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/dataBindMultiple.spec.js +0 -36
  23. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/dataBindSubstitutions.spec.js +0 -137
  24. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/globalConfiguraAllBindingAttributes.spec.js +0 -124
  25. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/globalConfigurableBindingAttributes.spec.js +0 -36
  26. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/helpers/SpecHelper.js +0 -4
  27. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/helpers/sample.backbone.app.js +0 -159
  28. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/html5inputConventionBinding.spec.js +0 -142
  29. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/modelUnbinding.spec.js +0 -73
  30. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/noConflict.spec.js +0 -36
  31. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/radioButtonConventionBinding.spec.js +0 -41
  32. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/selectboxConventionBindings.spec.js +0 -60
  33. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/textareaConventionBinding.spec.js +0 -29
  34. data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/textboxConventionBinding.spec.js +0 -66
  35. data/lib/appetizer/ui/vendor/js/backbone.js +0 -1290
  36. data/lib/appetizer/ui/vendor/js/backbone.modelbinding.js +0 -624
  37. data/lib/appetizer/ui/vendor/js/jquery.js +0 -9266
  38. data/lib/appetizer/ui/vendor/js/json2.js +0 -480
  39. data/lib/appetizer/ui/vendor/js/underscore.js +0 -999
  40. data/lib/appetizer/ui/vendor/js/underscore.string.js +0 -480
data/appetizer-ui.gemspec CHANGED
@@ -10,20 +10,22 @@ Gem::Specification.new do |gem|
10
10
  gem.test_files = `git ls-files -- test/*`.split("\n")
11
11
  gem.name = "appetizer-ui"
12
12
  gem.require_paths = ["lib"]
13
- gem.version = "0.9.0"
13
+ gem.version = "0.9.1"
14
14
 
15
15
  gem.required_ruby_version = ">= 1.9.2"
16
16
 
17
- gem.add_dependency "appetizer", "~> 0.0"
18
- gem.add_dependency "coffee-script", "~> 2.2"
19
- gem.add_dependency "eco", "~> 1.0"
20
- gem.add_dependency "rack-contrib", "~> 1.1"
21
- gem.add_dependency "rack-ssl", "~> 1.3"
22
- gem.add_dependency "sass", "~> 3.1"
23
- gem.add_dependency "sinatra", "~> 1.3"
24
- gem.add_dependency "sprockets", "~> 2.1"
25
- gem.add_dependency "sprockets-sass", "~> 0.6"
26
- gem.add_dependency "uglifier", "~> 1.0"
27
- gem.add_dependency "yajl-ruby", "~> 1.0"
28
- gem.add_dependency "yui-compressor", "~> 0.9"
17
+ gem.add_dependency "appetizer", "~> 0.0"
18
+ gem.add_dependency "coffee-script", "~> 2.2"
19
+ gem.add_dependency "eco", "~> 1.0"
20
+ gem.add_dependency "rack-contrib", "~> 1.1"
21
+ gem.add_dependency "rack-ssl", "~> 1.3"
22
+ gem.add_dependency "sass", "~> 3.1"
23
+ gem.add_dependency "sinatra", "~> 1.3"
24
+ gem.add_dependency "sprockets", "~> 2.11"
25
+ gem.add_dependency "sprockets-sass", "~> 1.0"
26
+ gem.add_dependency "sprockets-helpers", "~> 1.1"
27
+ gem.add_dependency "uglifier", "~> 1.0"
28
+ gem.add_dependency "vendorer", "~> 0.1"
29
+ gem.add_dependency "yajl-ruby", "~> 1.0"
30
+ gem.add_dependency "yui-compressor", "~> 0.9"
29
31
  end
@@ -1,10 +1,8 @@
1
1
  require "coffee-script"
2
2
  require "eco"
3
3
  require "fileutils"
4
- require "sass"
5
4
  require "sinatra/base"
6
- require "sprockets"
7
- require "sprockets/sass"
5
+ require "sprockets-helpers"
8
6
  require "uglifier"
9
7
  require "yui/compressor"
10
8
 
@@ -12,8 +10,10 @@ module App
12
10
  def self.assets
13
11
  @sprockets ||= Sprockets::Environment.new.tap do |s|
14
12
  if Appetizer::UI::Assets.compiled?
15
- s.register_bundle_processor "application/javascript", :uglifier do |ctx, data|
16
- Uglifier.compile data
13
+ if Appetizer::UI::Assets.uglify?
14
+ s.register_bundle_processor "application/javascript", :uglifier do |ctx, data|
15
+ Uglifier.compile data, mangle: false, squeeze: false, seqs: false
16
+ end
17
17
  end
18
18
 
19
19
  s.register_bundle_processor "text/css", :yui do |ctx, data|
@@ -21,6 +21,12 @@ module App
21
21
  end
22
22
  end
23
23
 
24
+ Sprockets::Helpers.configure do |config|
25
+ config.environment = s
26
+ config.prefix = "/assets"
27
+ config.digest = true
28
+ end
29
+
24
30
  # NOTE: Seems like Sprockets' built-in FileStore is kinda busted
25
31
  # in the way it creates directories or processes key names (or I
26
32
  # don't understand it yet), so we're manually creating the
@@ -31,11 +37,9 @@ module App
31
37
  s.cache = Sprockets::Cache::FileStore.new "tmp/sprockets"
32
38
  end
33
39
 
34
- %w(css img js views).each do |d|
40
+ %w(css img js views fonts).each do |d|
35
41
  s.append_path "./app/#{d}"
36
42
  s.append_path "./vendor/#{d}"
37
- s.append_path File.expand_path("../app/#{d}", __FILE__)
38
- s.append_path File.expand_path("../vendor/#{d}", __FILE__)
39
43
  end
40
44
  end
41
45
  end
@@ -48,6 +52,10 @@ module Appetizer
48
52
  App.production? or ENV["APPETIZER_USE_COMPILED_ASSETS"]
49
53
  end
50
54
 
55
+ def self.uglify?
56
+ compiled? and not ENV["APPETIZER_NO_UGLIFY"]
57
+ end
58
+
51
59
  def self.manifest
52
60
  return @manifest if defined? @manifest
53
61
 
@@ -63,6 +71,11 @@ module Appetizer
63
71
 
64
72
  def self.registered app
65
73
  app.helpers do
74
+ def asset_apps
75
+ apps = Dir.glob(Dir.pwd + "/app/js/*")
76
+ apps.collect { |path| File.basename(path) if File.directory?(path) }.compact
77
+ end
78
+
66
79
  def asset name
67
80
  if Appetizer::UI::Assets.compiled?
68
81
  return cdnify "/assets/#{Appetizer::UI::Assets.manifest[name]}"
@@ -0,0 +1,288 @@
1
+ var readFixtures = function() {
2
+ return jasmine.getFixtures().proxyCallTo_('read', arguments);
3
+ };
4
+
5
+ var preloadFixtures = function() {
6
+ jasmine.getFixtures().proxyCallTo_('preload', arguments);
7
+ };
8
+
9
+ var loadFixtures = function() {
10
+ jasmine.getFixtures().proxyCallTo_('load', arguments);
11
+ };
12
+
13
+ var setFixtures = function(html) {
14
+ jasmine.getFixtures().set(html);
15
+ };
16
+
17
+ var sandbox = function(attributes) {
18
+ return jasmine.getFixtures().sandbox(attributes);
19
+ };
20
+
21
+ var spyOnEvent = function(selector, eventName) {
22
+ jasmine.JQuery.events.spyOn(selector, eventName);
23
+ }
24
+
25
+ jasmine.getFixtures = function() {
26
+ return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures();
27
+ };
28
+
29
+ jasmine.Fixtures = function() {
30
+ this.containerId = 'jasmine-fixtures';
31
+ this.fixturesCache_ = {};
32
+ this.fixturesPath = 'spec/javascripts/fixtures';
33
+ };
34
+
35
+ jasmine.Fixtures.prototype.set = function(html) {
36
+ this.cleanUp();
37
+ this.createContainer_(html);
38
+ };
39
+
40
+ jasmine.Fixtures.prototype.preload = function() {
41
+ this.read.apply(this, arguments);
42
+ };
43
+
44
+ jasmine.Fixtures.prototype.load = function() {
45
+ this.cleanUp();
46
+ this.createContainer_(this.read.apply(this, arguments));
47
+ };
48
+
49
+ jasmine.Fixtures.prototype.read = function() {
50
+ var htmlChunks = [];
51
+
52
+ var fixtureUrls = arguments;
53
+ for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
54
+ htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]));
55
+ }
56
+
57
+ return htmlChunks.join('');
58
+ };
59
+
60
+ jasmine.Fixtures.prototype.clearCache = function() {
61
+ this.fixturesCache_ = {};
62
+ };
63
+
64
+ jasmine.Fixtures.prototype.cleanUp = function() {
65
+ jQuery('#' + this.containerId).remove();
66
+ };
67
+
68
+ jasmine.Fixtures.prototype.sandbox = function(attributes) {
69
+ var attributesToSet = attributes || {};
70
+ return jQuery('<div id="sandbox" />').attr(attributesToSet);
71
+ };
72
+
73
+ jasmine.Fixtures.prototype.createContainer_ = function(html) {
74
+ var container;
75
+ if(html instanceof jQuery) {
76
+ container = jQuery('<div id="' + this.containerId + '" />');
77
+ container.html(html);
78
+ } else {
79
+ container = '<div id="' + this.containerId + '">' + html + '</div>'
80
+ }
81
+ jQuery('body').append(container);
82
+ };
83
+
84
+ jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) {
85
+ if (typeof this.fixturesCache_[url] == 'undefined') {
86
+ this.loadFixtureIntoCache_(url);
87
+ }
88
+ return this.fixturesCache_[url];
89
+ };
90
+
91
+ jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
92
+ var self = this;
93
+ var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl;
94
+ jQuery.ajax({
95
+ async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
96
+ cache: false,
97
+ dataType: 'html',
98
+ url: url,
99
+ success: function(data) {
100
+ self.fixturesCache_[relativeUrl] = data;
101
+ },
102
+ error: function(jqXHR, status, errorThrown) {
103
+ throw Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')');
104
+ }
105
+ });
106
+ };
107
+
108
+ jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {
109
+ return this[methodName].apply(this, passedArguments);
110
+ };
111
+
112
+
113
+ jasmine.JQuery = function() {};
114
+
115
+ jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
116
+ return jQuery('<div/>').append(html).html();
117
+ };
118
+
119
+ jasmine.JQuery.elementToString = function(element) {
120
+ return jQuery('<div />').append(element.clone()).html();
121
+ };
122
+
123
+ jasmine.JQuery.matchersClass = {};
124
+
125
+ (function(namespace) {
126
+ var data = {
127
+ spiedEvents: {},
128
+ handlers: []
129
+ };
130
+
131
+ namespace.events = {
132
+ spyOn: function(selector, eventName) {
133
+ var handler = function(e) {
134
+ data.spiedEvents[[selector, eventName]] = e;
135
+ };
136
+ jQuery(selector).bind(eventName, handler);
137
+ data.handlers.push(handler);
138
+ },
139
+
140
+ wasTriggered: function(selector, eventName) {
141
+ return !!(data.spiedEvents[[selector, eventName]]);
142
+ },
143
+
144
+ cleanUp: function() {
145
+ data.spiedEvents = {};
146
+ data.handlers = [];
147
+ }
148
+ }
149
+ })(jasmine.JQuery);
150
+
151
+ (function(){
152
+ var jQueryMatchers = {
153
+ toHaveClass: function(className) {
154
+ return this.actual.hasClass(className);
155
+ },
156
+
157
+ toBeVisible: function() {
158
+ return this.actual.is(':visible');
159
+ },
160
+
161
+ toBeHidden: function() {
162
+ return this.actual.is(':hidden');
163
+ },
164
+
165
+ toBeSelected: function() {
166
+ return this.actual.is(':selected');
167
+ },
168
+
169
+ toBeChecked: function() {
170
+ return this.actual.is(':checked');
171
+ },
172
+
173
+ toBeEmpty: function() {
174
+ return this.actual.is(':empty');
175
+ },
176
+
177
+ toExist: function() {
178
+ return this.actual.size() > 0;
179
+ },
180
+
181
+ toHaveAttr: function(attributeName, expectedAttributeValue) {
182
+ return hasProperty(this.actual.attr(attributeName), expectedAttributeValue);
183
+ },
184
+
185
+ toHaveId: function(id) {
186
+ return this.actual.attr('id') == id;
187
+ },
188
+
189
+ toHaveHtml: function(html) {
190
+ return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html);
191
+ },
192
+
193
+ toHaveText: function(text) {
194
+ if (text && jQuery.isFunction(text.test)) {
195
+ return text.test(this.actual.text());
196
+ } else {
197
+ return this.actual.text() == text;
198
+ }
199
+ },
200
+
201
+ toHaveValue: function(value) {
202
+ return this.actual.val() == value;
203
+ },
204
+
205
+ toHaveData: function(key, expectedValue) {
206
+ return hasProperty(this.actual.data(key), expectedValue);
207
+ },
208
+
209
+ toBe: function(selector) {
210
+ return this.actual.is(selector);
211
+ },
212
+
213
+ toContain: function(selector) {
214
+ return this.actual.find(selector).size() > 0;
215
+ },
216
+
217
+ toBeDisabled: function(selector){
218
+ return this.actual.is(':disabled');
219
+ },
220
+
221
+ // tests the existence of a specific event binding
222
+ toHandle: function(eventName) {
223
+ var events = this.actual.data("events");
224
+ return events && events[eventName].length > 0;
225
+ },
226
+
227
+ // tests the existence of a specific event binding + handler
228
+ toHandleWith: function(eventName, eventHandler) {
229
+ var stack = this.actual.data("events")[eventName];
230
+ var i;
231
+ for (i = 0; i < stack.length; i++) {
232
+ if (stack[i].handler == eventHandler) {
233
+ return true;
234
+ }
235
+ }
236
+ return false;
237
+ }
238
+ };
239
+
240
+ var hasProperty = function(actualValue, expectedValue) {
241
+ if (expectedValue === undefined) {
242
+ return actualValue !== undefined;
243
+ }
244
+ return actualValue == expectedValue;
245
+ };
246
+
247
+ var bindMatcher = function(methodName) {
248
+ var builtInMatcher = jasmine.Matchers.prototype[methodName];
249
+
250
+ jasmine.JQuery.matchersClass[methodName] = function() {
251
+ if (this.actual instanceof jQuery) {
252
+ var result = jQueryMatchers[methodName].apply(this, arguments);
253
+ this.actual = jasmine.JQuery.elementToString(this.actual);
254
+ return result;
255
+ }
256
+
257
+ if (builtInMatcher) {
258
+ return builtInMatcher.apply(this, arguments);
259
+ }
260
+
261
+ return false;
262
+ };
263
+ };
264
+
265
+ for(var methodName in jQueryMatchers) {
266
+ bindMatcher(methodName);
267
+ }
268
+ })();
269
+
270
+ beforeEach(function() {
271
+ this.addMatchers(jasmine.JQuery.matchersClass);
272
+ this.addMatchers({
273
+ toHaveBeenTriggeredOn: function(selector) {
274
+ this.message = function() {
275
+ return [
276
+ "Expected event " + this.actual + " to have been triggered on" + selector,
277
+ "Expected event " + this.actual + " not to have been triggered on" + selector
278
+ ];
279
+ };
280
+ return jasmine.JQuery.events.wasTriggered(selector, this.actual);
281
+ }
282
+ })
283
+ });
284
+
285
+ afterEach(function() {
286
+ jasmine.getFixtures().cleanUp();
287
+ jasmine.JQuery.events.cleanUp();
288
+ });
@@ -1,7 +1,6 @@
1
1
  #= require ./jasmine
2
2
  #= require ./jasmine-html
3
3
  #= require ./jasmine-jquery-matchers
4
- #= require_tree ./backbone.modelbinding
5
4
 
6
5
  jasmineEnv = jasmine.getEnv()
7
6
  jasmineEnv.updateInterval = 1000
@@ -4,14 +4,22 @@
4
4
  <head>
5
5
  <title>Specs</title>
6
6
 
7
- <script>App = {}</script>
7
+ <script>
8
+ App = {}
9
+ </script>
8
10
 
9
11
  <% assets("jasmine.css").each do |css| %>
10
- <link href="<%= css %>" rel="stylesheet" type="text/css">
12
+ <link href="<%= css %>" rel="stylesheet" type="text/css">
11
13
  <% end %>
12
14
 
13
- <% assets("app.js", "spec-runner.js", "spec-helper.js").each do |js| %>
14
- <script src="<%= js %>"></script>
15
+ <% assets("spec-runner.js", "jasmine-jquery.js", "jasmine-mocks.js").each do |js| %>
16
+ <script src="<%= js %>"></script>
17
+ <% end %>
18
+
19
+ <% asset_apps.each do |app| %>
20
+ <% assets("#{app}/app.js", "#{app}/spec-helper.js", "#{app}/fixtures.js").each do |js| %>
21
+ <script src="<%= js %>"></script>
22
+ <% end %>
15
23
  <% end %>
16
24
  </head>
17
25
 
@@ -1,29 +1,38 @@
1
1
  require "appetizer/rake"
2
+ require "appetizer/ui/assets"
3
+ require "vendorer"
2
4
 
3
5
  # For Heroku.
4
6
 
7
+ desc "Download vendored assets"
8
+ task :vendorer => :init do
9
+ Vendorer.new(update: true).parse File.read('Vendorfile')
10
+ end
11
+
5
12
  task "assets:precompile" => :compile
6
13
 
7
14
  desc "Compile the app's CSS and JS files."
8
15
  task :compile => :init do
9
16
  ENV["APPETIZER_MINIFY_ASSETS"] = "true"
10
17
 
11
- require "appetizer/ui/assets"
12
18
  require "fileutils"
13
19
  require "yaml"
14
20
 
15
- manifest = {}
21
+ entry_points = ENV["APPETIZER_ASSETS_ENTRY_POINTS"] || "app.scss, app.coffee"
16
22
 
17
- App.assets.each_file do |path|
18
- next if File.basename(path).start_with? "_"
19
- next if %r|app/views| =~ path.to_s and not %r|app/views/client| =~ path.to_s
23
+ assets = App.assets.each_file
24
+
25
+ manifest = {}
20
26
 
21
- if asset = App.assets[path]
22
- manifest[asset.logical_path] = asset.digest_path
23
- file = "public/assets/#{asset.digest_path}"
27
+ assets.each do |path|
28
+ if entry_points.include? File.basename(path)
29
+ if asset = App.assets[path]
30
+ manifest[asset.logical_path] = asset.digest_path
31
+ file = "public/assets/#{asset.digest_path}"
24
32
 
25
- FileUtils.mkdir_p File.dirname file
26
- asset.write_to file
33
+ FileUtils.mkdir_p File.dirname file
34
+ asset.write_to file
35
+ end
27
36
  end
28
37
  end
29
38
 
@@ -31,3 +40,13 @@ task :compile => :init do
31
40
  YAML.dump manifest, f
32
41
  end
33
42
  end
43
+
44
+ if Gem::Specification.find { |spec| spec.name == "jasmine-headless-webkit" }
45
+ require "jasmine-headless-webkit"
46
+
47
+ Jasmine::Headless::Task.new("test") do |t|
48
+ t.colors = true
49
+ t.keep_on_error = true
50
+ t.jasmine_config = ENV["JASMINE_HEADLESS_CONFIG"] || "config/jasmine.yml"
51
+ end
52
+ end