ballonizer 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/examples/ballonizer_app/config.ru +59 -0
- data/examples/ballonizer_app/index.html +159 -0
- data/examples/ballonizer_js_module/index.html +196 -0
- data/lib/assets/javascripts/ballonizer.js +482 -0
- data/lib/assets/stylesheets/ballonizer.css +78 -0
- data/lib/ballonizer.rb +201 -36
- data/spec/ballonizer_spec.rb +153 -2
- data/spec/javascripts/ballonizer_spec.js +568 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-with-anchor-in-image.html +163 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-with-ballons.html +163 -0
- data/spec/javascripts/fixtures/ballonized-xkcd-without-ballons.html +163 -0
- data/spec/javascripts/fixtures/xkcd.css +191 -0
- data/spec/javascripts/helpers/jasmine-jquery.js +660 -0
- data/spec/javascripts/helpers/jquery.simulate-ext.js +32 -0
- data/spec/javascripts/helpers/jquery.simulate.drag-n-drop.js +583 -0
- data/spec/javascripts/helpers/jquery.simulate.js +328 -0
- data/spec/javascripts/support/jasmine.yml +99 -0
- data/vendor/assets/javascripts/jquery-2.0.1.js +8837 -0
- data/vendor/assets/javascripts/jquery-ui-1.10.3.custom.min.js +6 -0
- data/vendor/assets/javascripts/jquery.json-2.4.min.js +24 -0
- data/vendor/assets/stylesheets/ui-lightness/images/animated-overlay.gif +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/stylesheets/ui-lightness/jquery-ui-1.10.3.custom.min.css +5 -0
- metadata +51 -3
data/lib/ballonizer.rb
CHANGED
@@ -4,6 +4,7 @@ require 'sequel'
|
|
4
4
|
require 'json'
|
5
5
|
require 'htmlentities'
|
6
6
|
require 'rack'
|
7
|
+
require 'sprockets'
|
7
8
|
|
8
9
|
# This gem provides mechanisms to allow ballons (or speech bubbles) to be
|
9
10
|
# added/removed/edited over images of a HTML or XHTML document and to be
|
@@ -16,7 +17,7 @@ require 'rack'
|
|
16
17
|
#
|
17
18
|
# This class lacks a lot of features like: access to an abstraction of the
|
18
19
|
# ballons, images and their relationship; control over users who edit the
|
19
|
-
# ballons; access to the old versions of the ballon set of a image (
|
20
|
+
# ballons; access to the old versions of the ballon set of a image (that
|
20
21
|
# are stored in the database, but only can be accessed directly by the
|
21
22
|
# Sequel::Database object). It's a work in progress, be warned to use
|
22
23
|
# carefully and motivated to contribute.
|
@@ -40,12 +41,10 @@ require 'rack'
|
|
40
41
|
# To use this class with your (rack isn't?) app you need to: create the
|
41
42
|
# necessary tables in a Sequel::Database object with Ballonizer.create_tables;
|
42
43
|
# create a ballonizer instance with the url where you gonna handle the ballon
|
43
|
-
# change requests. Handle the ballon changes request
|
44
|
-
# process_submit. Call instance.ballonize_page over the html
|
45
|
-
# have the images to be ballonized.
|
46
|
-
#
|
47
|
-
# the ui-lightness and ballonizer css in the page (provided by the gem).
|
48
|
-
# Check if the image match the css selector :img_to_ballonize_css_selector.
|
44
|
+
# change requests and where provide the assets. Handle the ballon changes request
|
45
|
+
# in that url with process_submit. Call instance.ballonize_page over the html
|
46
|
+
# documents that can have the images to be ballonized. Check if the image match
|
47
|
+
# the css selector :img_to_ballonize_css_selector.
|
49
48
|
#
|
50
49
|
# What's explained above is basically the example you can access with
|
51
50
|
# 'rake example' and is in the examples/ballonizer_app/config.ru file.
|
@@ -64,23 +63,93 @@ class Ballonizer
|
|
64
63
|
|
65
64
|
attr_accessor :db, :settings
|
66
65
|
|
66
|
+
# @api private Don't use the methods of this module. They are for internal use only.
|
67
|
+
module Workaround
|
68
|
+
def self.join_uris(base, relative)
|
69
|
+
base = base.end_with?('/') ? base : base + '/'
|
70
|
+
Addressable::URI.parse(base).join(relative).to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.deep_freeze(e)
|
74
|
+
e.each { | v | deep_freeze(v) } if e.is_a?(Enumerable)
|
75
|
+
e.freeze
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.parse_html_or_xhtml(doc)
|
79
|
+
# If you parse XHTML as HTML with Nokogiri and use to_s after the markup can be messed up
|
80
|
+
#
|
81
|
+
# Example: <meta name="description" content="not important" />
|
82
|
+
# becomes <meta name="description" content="not important" >
|
83
|
+
# To avoid this we parse a document that is XML valid as XML, and, otherwise as HTML
|
84
|
+
parsed_doc = nil
|
85
|
+
begin
|
86
|
+
# this also isn't a great way to do this
|
87
|
+
# the Nokogiri don't have exception classes, this way any StandardError will be silenced
|
88
|
+
options = Nokogiri::XML::ParseOptions::DEFAULT_XML &
|
89
|
+
Nokogiri::XML::ParseOptions::STRICT &
|
90
|
+
Nokogiri::XML::ParseOptions::NONET
|
91
|
+
parsed_doc = Nokogiri::XML::Document.parse(doc, nil, nil, options)
|
92
|
+
rescue
|
93
|
+
parsed_doc = Nokogiri::HTML(doc)
|
94
|
+
end
|
95
|
+
|
96
|
+
parsed_doc
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private_constant :Workaround
|
101
|
+
|
102
|
+
# The load paths of assets inside the gem and the files inside each path,
|
103
|
+
# in the order they need to be included (the files of the first path need
|
104
|
+
# to be included before the files in the second path, and the files in the
|
105
|
+
# same path need to be included in the specified order).
|
106
|
+
# Give preference to the asset(s)_* and *_html_links methods over this constant.
|
107
|
+
ASSETS = Workaround.deep_freeze([
|
108
|
+
['vendor/assets/javascripts', [
|
109
|
+
'jquery-2.0.1.js',
|
110
|
+
'jquery.json-2.4.min.js',
|
111
|
+
'jquery-ui-1.10.3.custom.min.js']],
|
112
|
+
['lib/assets/javascripts', [
|
113
|
+
'ballonizer.js']],
|
114
|
+
['vendor/assets/stylesheets', [
|
115
|
+
'ui-lightness/jquery-ui-1.10.3.custom.min.css']],
|
116
|
+
['lib/assets/stylesheets', [
|
117
|
+
'ballonizer.css']]
|
118
|
+
])
|
119
|
+
|
67
120
|
# The default #settings
|
68
121
|
DEFAULT_SETTINGS = {
|
69
122
|
# The css selector used to define the elements to ballonize.
|
70
123
|
img_to_ballonize_css_selector: 'img.to_ballonize',
|
71
124
|
# A url to be used in the client-side action attribute of the form for
|
72
|
-
# ballon submition. The value will be used in the javascript snippet
|
125
|
+
# ballon submition. The value will be used in the javascript snippet that
|
73
126
|
# initialize the ballonizer client javascript allowing ballon edition
|
74
127
|
# (and consequently creating the form).
|
75
128
|
form_handler_url: '#',
|
76
|
-
# Define if the javascript code
|
129
|
+
# Define if the javascript code that allow edition will be added to the page.
|
77
130
|
# (this don't refer to the jquery-* libs and the ballonizer.js only the
|
78
131
|
# snippet to execute when the page is ready)
|
79
|
-
add_js_for_edition: true
|
132
|
+
add_js_for_edition: true,
|
133
|
+
# A path string to prefix each href of the css stylesheet links generated
|
134
|
+
# by the js_libs_html_links, and, possibly, added by the ballonize_page
|
135
|
+
# object. Example: if you use Ballonizer.assets_app mapped to '/assets'
|
136
|
+
# then use '/assets' here. This is used with the :add_required_css setting.
|
137
|
+
css_asset_path_for_link: nil,
|
138
|
+
# If the ballonize_page method will add or not the html generated by
|
139
|
+
# #css_html_links (require the :css_asset_path_for_link to be defined).
|
140
|
+
add_required_css: false,
|
141
|
+
# A path string to prefix each js source src generated by the
|
142
|
+
# object. Example: if you use Ballonizer.assets_app mapped to '/assets'
|
143
|
+
# then use '/assets' here. This is used with the
|
144
|
+
# :add_required_js_libs_for_edition setting.
|
145
|
+
js_asset_path_for_link: nil,
|
146
|
+
# If the ballonize_page method will add or not the html generated by
|
147
|
+
# #js_libs_html_links (require the :js_asset_path_for_link to be defined).
|
148
|
+
add_required_js_libs_for_edition: false
|
80
149
|
}.freeze.each { | _, v| v.freeze }
|
81
150
|
|
82
151
|
# Create a new Ballonizer object from a Sequel Database (with the expected
|
83
|
-
# tables,
|
152
|
+
# tables, that can be created with Ballonizer.create_tables) and a optional
|
84
153
|
# hash of settings.
|
85
154
|
# @param db [Sequel::Database] A Sequel::Database with tables as described
|
86
155
|
# @param settings [Hash{Symbol => String}] A optional hash of settings. The
|
@@ -256,7 +325,9 @@ class Ballonizer
|
|
256
325
|
end
|
257
326
|
|
258
327
|
# Wrap each image to ballonize with a container, add its ballons to the
|
259
|
-
# container and add the js snippet for the
|
328
|
+
# container and, possibly, add the css and js libs and snippet for the
|
329
|
+
# edition initialization. Don't make any change if the page has no images
|
330
|
+
# to ballonize.
|
260
331
|
# @param page [String] The (X)HTML page.
|
261
332
|
# @param page_url [String] The url of the page to be ballonized, necessary
|
262
333
|
# to make absolute the src attribute of img (if it's relative).
|
@@ -284,9 +355,15 @@ class Ballonizer
|
|
284
355
|
end
|
285
356
|
end
|
286
357
|
|
358
|
+
head = parsed_page.at_css('head')
|
359
|
+
if settings[:add_required_css]
|
360
|
+
head.children.last.add_next_sibling(self.css_html_links)
|
361
|
+
end
|
362
|
+
if settings[:add_required_js_libs_for_edition]
|
363
|
+
head.children.last.add_next_sibling(self.js_libs_html_links)
|
364
|
+
end
|
287
365
|
if settings[:add_js_for_edition]
|
288
|
-
|
289
|
-
.add_next_sibling(self.js_load_snippet)
|
366
|
+
head.children.last.add_next_sibling(self.js_load_snippet)
|
290
367
|
end
|
291
368
|
end
|
292
369
|
|
@@ -310,7 +387,7 @@ class Ballonizer
|
|
310
387
|
# Don't use this method. It is for internal use only.
|
311
388
|
# @note This method don't make distinction between a image in the database
|
312
389
|
# without any ballons (removed in the last version, by example) or a image
|
313
|
-
#
|
390
|
+
# that isn't in the database (both return a empty array).
|
314
391
|
def last_ballon_set_of_image(img_src)
|
315
392
|
db_image = self.db[:images].first({img_src: img_src})
|
316
393
|
if db_image
|
@@ -372,30 +449,118 @@ class Ballonizer
|
|
372
449
|
end
|
373
450
|
end
|
374
451
|
|
375
|
-
#
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
Nokogiri::XML::ParseOptions::STRICT &
|
389
|
-
Nokogiri::XML::ParseOptions::NONET
|
390
|
-
parsed_doc = Nokogiri::XML::Document.parse(doc, nil, nil, options)
|
391
|
-
rescue
|
392
|
-
parsed_doc = Nokogiri::HTML(doc)
|
393
|
-
end
|
452
|
+
# The (X)HTML fragment with the link tags that are added to the page by
|
453
|
+
# ballonize_page if the :add_required_css setting is true (the default
|
454
|
+
# is false). If the :css_asset_path_for_link isn't set (what is the
|
455
|
+
# default) this method return nil.
|
456
|
+
# @return [String,NilClass] A frozen string.
|
457
|
+
def css_html_links
|
458
|
+
return nil unless settings[:css_asset_path_for_link]
|
459
|
+
return @css_html_links if @css_html_links
|
460
|
+
|
461
|
+
link_template = '<link rel="stylesheet" type="text/css" href="PATH" />'
|
462
|
+
css_paths = self.class.asset_logical_paths.select do | p |
|
463
|
+
/^.+\.css$/.match(p)
|
464
|
+
end
|
394
465
|
|
395
|
-
|
466
|
+
links = css_paths.map do | p |
|
467
|
+
p = Workaround.join_uris(settings[:css_asset_path_for_link], p)
|
468
|
+
link_template.sub('PATH', p)
|
396
469
|
end
|
470
|
+
|
471
|
+
@css_html_links = links.join('').freeze
|
397
472
|
end
|
398
473
|
|
399
|
-
|
474
|
+
# The (X)HTML fragment with the script tags that are added to the page by
|
475
|
+
# ballonize_page if the :add_required_js_libs_for_edition setting is true
|
476
|
+
# (the default is false). If the :js_asset_path_for_link isn't set (what
|
477
|
+
# is the default) this method return nil.
|
478
|
+
# @return [String,NilClass] A frozen string.
|
479
|
+
def js_libs_html_links
|
480
|
+
return nil unless settings[:js_asset_path_for_link]
|
481
|
+
return @js_libs_html_links if @js_libs_html_links
|
482
|
+
|
483
|
+
link_template = '<script type="text/javascript" src="PATH" />'
|
484
|
+
js_libs_paths = self.class.asset_logical_paths.select do | p |
|
485
|
+
/^.+\.js$/.match(p)
|
486
|
+
end
|
487
|
+
|
488
|
+
links = js_libs_paths.map do | p |
|
489
|
+
p = Workaround.join_uris(settings[:js_asset_path_for_link], p)
|
490
|
+
link_template.sub('PATH', p)
|
491
|
+
end
|
492
|
+
|
493
|
+
@js_libs_html_links = links.join('').freeze
|
494
|
+
end
|
495
|
+
|
496
|
+
# List of paths (relative to the gem root directory) to the directories with
|
497
|
+
# the css and js provided by the gem.
|
498
|
+
# @return [Array<String>] A frozen array of frozen strings.
|
499
|
+
def self.asset_load_paths
|
500
|
+
return @asset_load_paths if @asset_load_paths
|
501
|
+
|
502
|
+
absolute_lib_dir = File.dirname(File.realpath(__FILE__))
|
503
|
+
ballonizer_gem_root_dir = File.expand_path('../', absolute_lib_dir)
|
504
|
+
|
505
|
+
@asset_load_paths = ASSETS.map do | load_path_and_files |
|
506
|
+
load_path = load_path_and_files.first
|
507
|
+
File.expand_path(load_path, ballonizer_gem_root_dir)
|
508
|
+
end
|
509
|
+
|
510
|
+
@asset_load_paths.flatten!
|
511
|
+
@asset_load_paths.freeze
|
512
|
+
end
|
513
|
+
|
514
|
+
# List of logical paths to the css and js assets. The assets_app respond to
|
515
|
+
# any requisition to one of these paths.
|
516
|
+
# @return [Array<String>] A frozen array of frozen strings.
|
517
|
+
def self.asset_logical_paths
|
518
|
+
return @asset_logical_paths if @asset_logical_paths
|
519
|
+
|
520
|
+
@asset_logical_paths = ASSETS.map do | load_path_and_files |
|
521
|
+
load_path_and_files.last
|
522
|
+
end
|
523
|
+
|
524
|
+
@asset_logical_paths.flatten!
|
525
|
+
@asset_logical_paths.freeze
|
526
|
+
end
|
527
|
+
|
528
|
+
# List of absolute filepaths to the css and js files needed by the client
|
529
|
+
# counterpart and provided by the gem. To all who not want to use assets_app.
|
530
|
+
# @return [Array<String>] A frozen array of frozen strings.
|
531
|
+
# @see Ballonizer.assets_app
|
532
|
+
def self.asset_absolute_paths
|
533
|
+
return @asset_absolute_paths if @asset_absolute_paths
|
534
|
+
|
535
|
+
absolute_lib_dir = File.dirname(File.realpath(__FILE__))
|
536
|
+
ballonizer_gem_root_dir = File.expand_path('../', absolute_lib_dir)
|
537
|
+
|
538
|
+
@asset_absolute_paths = ASSETS.map do | load_path_and_files |
|
539
|
+
relative_load_path, filepaths = *load_path_and_files
|
540
|
+
absolute_load_path = File.expand_path(relative_load_path, ballonizer_gem_root_dir)
|
541
|
+
|
542
|
+
filepaths.map do | filepath |
|
543
|
+
File.expand_path(filepath, absolute_load_path)
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
@asset_absolute_paths.flatten!
|
548
|
+
@asset_absolute_paths.freeze
|
549
|
+
end
|
550
|
+
|
551
|
+
# A Rack app that provide the gem css and js. Each call to this method return
|
552
|
+
# a new object (clone). The Sprockets::Environment isn't frozen because it
|
553
|
+
# can't be used with 'run' in a rack app if frozen.
|
554
|
+
# @return [Sprockets::Environment]
|
555
|
+
# @see Ballonizer.assets_app
|
556
|
+
def self.assets_app
|
557
|
+
# dont freeze because run don't work in a frozen sprockets env
|
558
|
+
return @assets_app.clone if @assets_app
|
559
|
+
@assets_app = Sprockets::Environment.new
|
560
|
+
asset_load_paths.each do | load_path |
|
561
|
+
@assets_app.prepend_path load_path
|
562
|
+
end
|
563
|
+
@assets_app.clone
|
564
|
+
end
|
400
565
|
end
|
401
566
|
|
data/spec/ballonizer_spec.rb
CHANGED
@@ -3,6 +3,7 @@ require 'rspec-html-matchers'
|
|
3
3
|
# Avoid to use equivalent-xml, the specs break with cosmetic changes this way
|
4
4
|
require 'equivalent-xml'
|
5
5
|
require 'stringio'
|
6
|
+
require 'rexml/document'
|
6
7
|
|
7
8
|
# make the changes in the BD restricted to the example
|
8
9
|
RSpec.configure do |c|
|
@@ -11,6 +12,26 @@ RSpec.configure do |c|
|
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
15
|
+
RSpec::Matchers.define :exist_in_filesystem do
|
16
|
+
match do | actual |
|
17
|
+
if actual.respond_to? :all?
|
18
|
+
actual.all? { | filename | File.exist?(filename) }
|
19
|
+
else
|
20
|
+
File.exist? actual
|
21
|
+
end
|
22
|
+
end
|
23
|
+
failure_message_for_should do | actual |
|
24
|
+
if actual.respond_to? :all?
|
25
|
+
"expected #{actual} to be a list of absolute filepaths for existing files or directories"
|
26
|
+
else
|
27
|
+
"expected #{actual} to be a absolute filepath for an existing file or directory"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
description do
|
31
|
+
"be a list of absolute paths for existing files or directories"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
14
35
|
describe Ballonizer do
|
15
36
|
|
16
37
|
DB = Sequel.sqlite
|
@@ -63,8 +84,11 @@ describe Ballonizer do
|
|
63
84
|
# Definitions ending with '_example' are to be cloned and defined in a
|
64
85
|
# context without the sufix. Definitions without the sufix are used in the
|
65
86
|
# specs and may require the definition of some without '_example' counterparts.
|
87
|
+
let (:ballonizer_settings_example) do
|
88
|
+
{}
|
89
|
+
end
|
66
90
|
let (:ballonizer_new_args_example) do
|
67
|
-
[DB,
|
91
|
+
[DB, ballonizer_settings]
|
68
92
|
end
|
69
93
|
# TODO: This isn't a valid Rack env, to turn it in a valid env will be
|
70
94
|
# necessary to add all obrigatory 'rack.' variables described in:
|
@@ -123,6 +147,7 @@ describe Ballonizer do
|
|
123
147
|
|
124
148
|
# definitions to be overriden in specific contexts (by doing a clone of the
|
125
149
|
# '_example' counterpart and changing what is needed)
|
150
|
+
let (:ballonizer_settings) { ballonizer_settings_example }
|
126
151
|
let (:ballonizer_new_args) { ballonizer_new_args_example }
|
127
152
|
let (:env) { env_example }
|
128
153
|
let (:original_page) { original_page_example.to_s }
|
@@ -173,6 +198,35 @@ describe Ballonizer do
|
|
173
198
|
end)
|
174
199
|
end
|
175
200
|
end
|
201
|
+
# TODO: create this specs
|
202
|
+
context 'and the settings define to insert css' do
|
203
|
+
let (:ballonizer_settings) do
|
204
|
+
ballonizer_settings_example.merge({
|
205
|
+
add_required_css: true,
|
206
|
+
css_asset_path_for_link: 'assets/css'
|
207
|
+
})
|
208
|
+
end
|
209
|
+
|
210
|
+
it do
|
211
|
+
# the example html don't have any link tag, so if there one
|
212
|
+
# it was added by the method
|
213
|
+
should have_tag('link', :with => { type: 'text/css' })
|
214
|
+
end
|
215
|
+
end
|
216
|
+
context 'and the settings define to insert js' do
|
217
|
+
let (:ballonizer_settings) do
|
218
|
+
ballonizer_settings_example.merge({
|
219
|
+
# this option is added to avoid a false positive in the test
|
220
|
+
add_js_for_edition: false,
|
221
|
+
add_required_js_libs_for_edition: true,
|
222
|
+
js_asset_path_for_link: 'assets/js'
|
223
|
+
})
|
224
|
+
end
|
225
|
+
|
226
|
+
it do
|
227
|
+
should have_tag('script', :with => { type: 'text/javascript' })
|
228
|
+
end
|
229
|
+
end
|
176
230
|
end
|
177
231
|
context 'and more than one of them is to be ballonized' do
|
178
232
|
let (:original_page) do
|
@@ -488,7 +542,6 @@ describe Ballonizer do
|
|
488
542
|
end
|
489
543
|
|
490
544
|
describe '#process_submit' do
|
491
|
-
|
492
545
|
# As process_submit use the #valid_submit_json? and #process_submit_hash
|
493
546
|
# we only make the tests here for example and its not the ideia cover the
|
494
547
|
# cases already covered in the specs of the two methods
|
@@ -535,5 +588,103 @@ describe Ballonizer do
|
|
535
588
|
end
|
536
589
|
end
|
537
590
|
end
|
591
|
+
|
592
|
+
describe '#css_html_links' do
|
593
|
+
context "when the path for the css isn't configured" do
|
594
|
+
it 'returns nil' do
|
595
|
+
expect(instance.css_html_links).to eq nil
|
596
|
+
end
|
597
|
+
end
|
598
|
+
context 'when the path for the css is configured' do
|
599
|
+
let (:ballonizer_settings) do
|
600
|
+
ballonizer_settings_example.merge({
|
601
|
+
css_asset_path_for_link: 'assets/css'
|
602
|
+
})
|
603
|
+
end
|
604
|
+
|
605
|
+
it 'return a HTML string with links prefixed by the path' do
|
606
|
+
REXML::Document.new("<root>#{instance.css_html_links}</root>")
|
607
|
+
.root.children.each do | e |
|
608
|
+
expect(e.attributes['href']).to match(/^assets\/css/)
|
609
|
+
end
|
610
|
+
end
|
611
|
+
end
|
612
|
+
end
|
613
|
+
|
614
|
+
describe '#js_libs_html_links' do
|
615
|
+
context "when the path for the js libs isn't configured" do
|
616
|
+
it 'returns nil' do
|
617
|
+
expect(instance.js_libs_html_links).to eq nil
|
618
|
+
end
|
619
|
+
end
|
620
|
+
context 'when the path for the js libs is configured' do
|
621
|
+
let (:ballonizer_settings) do
|
622
|
+
ballonizer_settings_example.merge({
|
623
|
+
js_asset_path_for_link: 'assets/js'
|
624
|
+
})
|
625
|
+
end
|
626
|
+
|
627
|
+
it 'return a HTML string with links prefixed by the path' do
|
628
|
+
REXML::Document.new("<root>#{instance.js_libs_html_links}</root>")
|
629
|
+
.root.children.each do | e |
|
630
|
+
expect(e.attributes['src']).to match(/^assets\/js/)
|
631
|
+
end
|
632
|
+
end
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
describe '.asset_load_paths' do
|
637
|
+
it 'return an array of paths who exist in the gem root dir' do
|
638
|
+
# TODO: change to __dir__ when the 2.0 become widely adopted
|
639
|
+
spec_dir = File.dirname(File.realpath(__FILE__))
|
640
|
+
gem_root_dir = File.expand_path('../', spec_dir)
|
641
|
+
|
642
|
+
absolute_load_paths = described_class.asset_load_paths.map do | path |
|
643
|
+
File.expand_path(path, gem_root_dir)
|
644
|
+
end
|
645
|
+
|
646
|
+
expect(absolute_load_paths).to exist_in_filesystem
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
describe '.asset_absolute_paths' do
|
651
|
+
it 'return an array of absolute filepaths who exist' do
|
652
|
+
expect(described_class.asset_absolute_paths).to exist_in_filesystem
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
describe '.asset_logical_paths' do
|
657
|
+
it 'return the last part of the asset_absolute_paths' do
|
658
|
+
logical_paths = described_class.asset_logical_paths
|
659
|
+
absolute_paths = described_class.asset_absolute_paths
|
660
|
+
|
661
|
+
are_last_part_of_absolute = logical_paths.all? do | lp |
|
662
|
+
absolute_paths.any? { | ap | ap.end_with? lp }
|
663
|
+
end
|
664
|
+
|
665
|
+
expect(are_last_part_of_absolute).to be_true
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
describe '.assets_app' do
|
670
|
+
let (:envs) do
|
671
|
+
described_class.asset_logical_paths.map do | asset_logical_path |
|
672
|
+
env_example.merge({
|
673
|
+
'HTTP_HOST' => 'example.net',
|
674
|
+
'SERVER_NAME' => 'example.net',
|
675
|
+
'PATH_INFO' => asset_logical_path,
|
676
|
+
'REQUEST_METHOD' => 'GET',
|
677
|
+
'rack.input' => nil,
|
678
|
+
'CONTENT_TYPE' => nil,
|
679
|
+
'CONTENT_LENGTH' => nil
|
680
|
+
})
|
681
|
+
end
|
682
|
+
end
|
683
|
+
it 'provide the css and js libs required by the gem' do
|
684
|
+
envs.each do | env |
|
685
|
+
expect(described_class.assets_app.call(env)[0]).to eq 200
|
686
|
+
end
|
687
|
+
end
|
688
|
+
end
|
538
689
|
end
|
539
690
|
|