parcels 0.0.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 (158) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec-local +4 -0
  4. data/.travis.yml +54 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +6 -0
  9. data/lib/parcels/dependency_parcel_list.rb +50 -0
  10. data/lib/parcels/environment.rb +60 -0
  11. data/lib/parcels/fortitude/alongside_engine.rb +37 -0
  12. data/lib/parcels/fortitude/assets.rb +212 -0
  13. data/lib/parcels/fortitude/enabling.rb +72 -0
  14. data/lib/parcels/fortitude/fortitude_engine.rb +35 -0
  15. data/lib/parcels/fortitude/fortitude_loader.rb +27 -0
  16. data/lib/parcels/fortitude/widget_engine.rb +31 -0
  17. data/lib/parcels/fortitude_alongside_parcel.rb +38 -0
  18. data/lib/parcels/fortitude_inline_parcel.rb +31 -0
  19. data/lib/parcels/fortitude_parcel.rb +102 -0
  20. data/lib/parcels/fragments/css_fragment.rb +107 -0
  21. data/lib/parcels/index.rb +16 -0
  22. data/lib/parcels/rails/rails_loader.rb +23 -0
  23. data/lib/parcels/rails/railtie.rb +16 -0
  24. data/lib/parcels/sprockets.rb +153 -0
  25. data/lib/parcels/utils/path_utils.rb +32 -0
  26. data/lib/parcels/version.rb +3 -0
  27. data/lib/parcels/widget_tree.rb +158 -0
  28. data/lib/parcels.rb +21 -0
  29. data/parcels.gemspec +48 -0
  30. data/spec/helpers/content_in_helpers.rb +21 -0
  31. data/spec/helpers/file_structure_helpers.rb +79 -0
  32. data/spec/helpers/global_helper.rb +34 -0
  33. data/spec/helpers/new_asset_helpers.rb +31 -0
  34. data/spec/helpers/new_rails_helpers.rb +31 -0
  35. data/spec/helpers/parcels_rails_helpers.rb +20 -0
  36. data/spec/helpers/per_example_helpers.rb +15 -0
  37. data/spec/helpers/sprockets_helpers.rb +23 -0
  38. data/spec/lib/spec/expected/base_expected_asset.rb +35 -0
  39. data/spec/lib/spec/expected/expected_asset.rb +135 -0
  40. data/spec/lib/spec/expected/expected_asset_set.rb +45 -0
  41. data/spec/lib/spec/expected/must_not_be_present_asset.rb +17 -0
  42. data/spec/lib/spec/fixtures/file_set.rb +80 -0
  43. data/spec/lib/spec/fixtures/widget_base.rb +13 -0
  44. data/spec/lib/spec/fixtures/widget_file.rb +108 -0
  45. data/spec/lib/spec/parsing/compiled_asset.rb +94 -0
  46. data/spec/lib/spec/parsing/compiled_asset_fragment.rb +38 -0
  47. data/spec/lib/spec/parsing/parsed_css_asset.rb +34 -0
  48. data/spec/lib/spec/parsing/precompiled_rails_asset.rb +52 -0
  49. data/spec/lib/spec/parsing/rails_asset.rb +30 -0
  50. data/spec/lib/spec/parsing/sprockets_asset.rb +40 -0
  51. data/spec/rails/basic_rails_spec.rb +102 -0
  52. data/spec/rails/compression_rails_spec.rb +11 -0
  53. data/spec/rails/development_mode_rails_spec.rb +321 -0
  54. data/spec/rails/sass_rails_spec.rb +125 -0
  55. data/spec/rails/sets_rails_spec.rb +85 -0
  56. data/spec/rails/templates/base/app/assets/stylesheets/application.css +16 -0
  57. data/spec/rails/templates/base/app/views/widgets/base.rb +4 -0
  58. data/spec/rails/templates/base/config/environments/production.rb +92 -0
  59. data/spec/rails/templates/base/lib/null_compressor.rb +5 -0
  60. data/spec/rails/templates/basic_rails_spec/app/controllers/basic_rails_spec_controller.rb +21 -0
  61. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_and_inline.pcss +1 -0
  62. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_and_inline.rb +9 -0
  63. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_and_inline_html.html.pcss +1 -0
  64. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_and_inline_html.html.rb +9 -0
  65. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_erb.pcss +1 -0
  66. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_erb.rb +7 -0
  67. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/inline_erb.rb +9 -0
  68. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/multiple_engines.pcss +1 -0
  69. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/multiple_engines.rb +9 -0
  70. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/no_corresponding_widget.pcss +1 -0
  71. data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/simple_css.rb +9 -0
  72. data/spec/rails/templates/compression_rails_spec/app/controllers/compression_rails_spec_controller.rb +5 -0
  73. data/spec/rails/templates/compression_rails_spec/app/views/compression_rails_spec/inline_and_alongside_css.pcss +1 -0
  74. data/spec/rails/templates/compression_rails_spec/app/views/compression_rails_spec/inline_and_alongside_css.rb +9 -0
  75. data/spec/rails/templates/compression_rails_spec/config/environments/production.rb +91 -0
  76. data/spec/rails/templates/development_mode_rails_spec/app/assets/stylesheets/changingone.scss +1 -0
  77. data/spec/rails/templates/development_mode_rails_spec/app/assets/stylesheets/changingtwo.scss +1 -0
  78. data/spec/rails/templates/development_mode_rails_spec/app/assets/stylesheets/import_dir/import_dir_ss_1.scss +1 -0
  79. data/spec/rails/templates/development_mode_rails_spec/app/controllers/development_mode_rails_spec_controller.rb +45 -0
  80. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/adding_alongside_css.rb +5 -0
  81. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/adding_inline_css.rb +7 -0
  82. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/adding_widget.rb +5 -0
  83. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/basic_widget_with_inline_and_alongside_parcels.pcss +3 -0
  84. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/basic_widget_with_inline_and_alongside_parcels.rb +9 -0
  85. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/changing_alongside_css.pcss +1 -0
  86. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/changing_alongside_css.rb +5 -0
  87. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/changing_import_file.pcss +2 -0
  88. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/changing_import_file.rb +10 -0
  89. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/changing_inline_css.rb +9 -0
  90. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/changing_prefix_imported_file.pcss +1 -0
  91. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/changing_prefix_imported_file.rb +7 -0
  92. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/removing_alongside_css.pcss +1 -0
  93. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/removing_alongside_css.rb +5 -0
  94. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/removing_inline_css.rb +7 -0
  95. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/removing_widget.pcss +1 -0
  96. data/spec/rails/templates/development_mode_rails_spec/app/views/development_mode_rails_spec/removing_widget.rb +9 -0
  97. data/spec/rails/templates/development_mode_rails_spec/app/views/import_base.rb +5 -0
  98. data/spec/rails/templates/development_mode_rails_spec/config/environments/development.rb +37 -0
  99. data/spec/rails/templates/development_mode_rails_spec/vendor/assets/stylesheets/one.scss +1 -0
  100. data/spec/rails/templates/development_mode_rails_spec/vendor/assets/stylesheets/two.scss +1 -0
  101. data/spec/rails/templates/sass_rails_spec/app/assets/foobar/the_import_dir_2/id2ss1.scss +1 -0
  102. data/spec/rails/templates/sass_rails_spec/app/assets/foobar/the_import_dir_2/id2ss2.scss +1 -0
  103. data/spec/rails/templates/sass_rails_spec/app/assets/foobar/twelve.scss +1 -0
  104. data/spec/rails/templates/sass_rails_spec/app/assets/foobar/two.scss +1 -0
  105. data/spec/rails/templates/sass_rails_spec/app/assets/images/quux/foo.png +0 -0
  106. data/spec/rails/templates/sass_rails_spec/app/assets/stylesheets/eleven.scss +1 -0
  107. data/spec/rails/templates/sass_rails_spec/app/assets/stylesheets/one.scss +1 -0
  108. data/spec/rails/templates/sass_rails_spec/app/assets/stylesheets/shared_import_dir/sid1ss1.scss +1 -0
  109. data/spec/rails/templates/sass_rails_spec/app/assets/stylesheets/shared_import_dir/sid1ss2.scss +1 -0
  110. data/spec/rails/templates/sass_rails_spec/app/assets/stylesheets/the_import_dir_1/id1ss1.scss +1 -0
  111. data/spec/rails/templates/sass_rails_spec/app/assets/stylesheets/the_import_dir_1/id1ss2.scss +1 -0
  112. data/spec/rails/templates/sass_rails_spec/app/controllers/sass_rails_spec_controller.rb +29 -0
  113. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/added_asset_path.pcss +2 -0
  114. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/added_asset_path.rb +10 -0
  115. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/asset_url.pcss +2 -0
  116. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/asset_url.rb +17 -0
  117. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/default_sass_import.pcss +6 -0
  118. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/default_sass_import.rb +14 -0
  119. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/import_directory.pcss +3 -0
  120. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/import_directory.rb +11 -0
  121. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/import_view_relative_directory.pcss +3 -0
  122. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/import_view_relative_directory.rb +11 -0
  123. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/other_features.pcss +1 -0
  124. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/other_features.rb +9 -0
  125. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/shared_imports.rb +10 -0
  126. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/vr_import_dir_1/vr1ss1.scss +1 -0
  127. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/vr_import_dir_1/vr1ss2.scss +1 -0
  128. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/vr_import_dir_2/vr2ss1.scss +1 -0
  129. data/spec/rails/templates/sass_rails_spec/app/views/sass_rails_spec/vr_import_dir_2/vr2ss2.scss +1 -0
  130. data/spec/rails/templates/sass_rails_spec/app/views/widgets/import_base.rb +5 -0
  131. data/spec/rails/templates/sass_rails_spec/config/application.rb +25 -0
  132. data/spec/rails/templates/sass_rails_spec/lib/more_assets/twenty.scss +1 -0
  133. data/spec/rails/templates/sass_rails_spec/vendor/assets/stylesheets/thirteen.scss +1 -0
  134. data/spec/rails/templates/sass_rails_spec/vendor/assets/stylesheets/three.scss +1 -0
  135. data/spec/rails/templates/sets_rails_spec/app/assets/stylesheets/admin.css.scss +1 -0
  136. data/spec/rails/templates/sets_rails_spec/app/assets/stylesheets/all.css.scss +1 -0
  137. data/spec/rails/templates/sets_rails_spec/app/assets/stylesheets/normal.css.scss +1 -0
  138. data/spec/rails/templates/sets_rails_spec/app/controllers/sets_rails_spec_controller.rb +3 -0
  139. data/spec/rails/templates/sets_rails_spec/app/views/admin/admin_one.pcss +1 -0
  140. data/spec/rails/templates/sets_rails_spec/app/views/admin/admin_one.rb +3 -0
  141. data/spec/rails/templates/sets_rails_spec/app/views/admin/admin_two.pcss +1 -0
  142. data/spec/rails/templates/sets_rails_spec/app/views/admin/admin_two.rb +3 -0
  143. data/spec/rails/templates/sets_rails_spec/app/views/admin/base.rb +3 -0
  144. data/spec/rails/templates/sets_rails_spec/app/views/root.rb +9 -0
  145. data/spec/rails/templates/sets_rails_spec/app/views/sets_base.rb +3 -0
  146. data/spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_one.pcss +1 -0
  147. data/spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_one.rb +3 -0
  148. data/spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_two.pcss +1 -0
  149. data/spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_two.rb +3 -0
  150. data/spec/system/alongside_file_spec.rb +193 -0
  151. data/spec/system/autogenerated_class_application_spec.rb +240 -0
  152. data/spec/system/basic_system_spec.rb +75 -0
  153. data/spec/system/dependency_sorting_spec.rb +48 -0
  154. data/spec/system/engines_spec.rb +245 -0
  155. data/spec/system/prefix_spec.rb +108 -0
  156. data/spec/system/sass_features_spec.rb +109 -0
  157. data/spec/system/sets_spec.rb +405 -0
  158. metadata +477 -0
data/lib/parcels.rb ADDED
@@ -0,0 +1,21 @@
1
+ require "sprockets"
2
+
3
+ module Parcels
4
+ def self.fortitude_available?
5
+ @fortitude_available || false
6
+ end
7
+
8
+ def self.fortitude_available!
9
+ @fortitude_available = true
10
+ end
11
+
12
+ def self.is_fortitude_logical_path?(logical_path)
13
+ ::Parcels::FortitudeParcel.is_fortitude_logical_path?(logical_path)
14
+ end
15
+ end
16
+
17
+ require "parcels/version"
18
+ require "parcels/rails/rails_loader"
19
+ require "parcels/fortitude/fortitude_loader"
20
+ require "parcels/sprockets"
21
+ require "parcels/environment"
data/parcels.gemspec ADDED
@@ -0,0 +1,48 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'parcels/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "parcels"
8
+ spec.version = Parcels::VERSION
9
+ spec.authors = ["Andrew Geweke"]
10
+ spec.email = ["andrew@geweke.org"]
11
+ spec.summary = %q{Views are HTML...and CSS, and Javascript. Together at last!}
12
+ spec.description = %q{Allows you to package the CSS and Javascript for your view together with that view, creating self-contained parcels of view code that seamlessly work together. When used with Fortitude, automatically scopes your CSS, too. No more dueling CSS rules!}
13
+ spec.homepage = "https://github.com/ageweke/parcels"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ if RUBY_VERSION =~ /^1\.8\./
22
+ spec.add_dependency "activesupport", "< 4.0.0"
23
+ else
24
+ spec.add_dependency "activesupport"
25
+ end
26
+
27
+ if (ENV['PARCELS_SPECS_SPROCKETS_VERSION'] || '').strip.length > 0
28
+ spec.add_dependency "sprockets", "= #{ENV['PARCELS_SPECS_SPROCKETS_VERSION']}"
29
+ else
30
+ spec.add_dependency "sprockets"
31
+ end
32
+
33
+ spec.add_dependency "sass"
34
+
35
+ spec.add_development_dependency "bundler", "~> 1.6"
36
+ spec.add_development_dependency "rake"
37
+ spec.add_development_dependency "rspec", "~> 3.0"
38
+
39
+ if RUBY_VERSION =~ /^1\.8\./
40
+ spec.add_development_dependency "nokogiri", "< 1.6.0"
41
+ else
42
+ spec.add_development_dependency "nokogiri"
43
+ end
44
+
45
+ spec.add_development_dependency "oop_rails_server", "~> 0", ">= 0.0.5"
46
+ spec.add_development_dependency "css_parser"
47
+ spec.add_development_dependency "fortitude", ">= 0.9.1"
48
+ end
@@ -0,0 +1,21 @@
1
+ require 'nokogiri'
2
+
3
+ module ContentInHelpers
4
+ def classes_from(node, xpath)
5
+ elements = node.xpath(xpath)
6
+
7
+ if elements.length == 0
8
+ raise "No elements matched #{xpath.inspect} from here: #{node}"
9
+ elsif elements.length == 1
10
+ element = elements[0]
11
+ class_string = element['class']
12
+ if class_string
13
+ class_string.split(/\s+/)
14
+ else
15
+ [ ]
16
+ end
17
+ else
18
+ raise "Multiple elements matched #{xpath.inspect} from here: #{node}; they are: #{elements.inspect}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,79 @@
1
+ require 'fortitude'
2
+
3
+ require 'active_support/concern'
4
+
5
+ require 'spec/fixtures/file_set'
6
+
7
+ module Views; end
8
+
9
+ module FileStructureHelpers
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ after :each do
14
+ unload_all_classes!
15
+ end
16
+ end
17
+
18
+ def this_example_root
19
+ per_example_data[:this_example_root] ||= clean_directory(this_spec_root, this_example_name)
20
+ end
21
+
22
+ def files(&block)
23
+ per_example_data[:file_set_fixture] ||= ::Spec::Fixtures::FileSet.new(this_example_root)
24
+ per_example_data[:file_set_fixture].instance_eval(&block)
25
+ per_example_data[:file_set_fixture].create!
26
+ end
27
+
28
+ def files_root(file_set_fixture = nil)
29
+ file_set_fixture ||= per_example_data[:file_set_fixture]
30
+ file_set_fixture.root_dir
31
+ end
32
+
33
+ private
34
+ def unload_all_classes!
35
+ fd = per_example_data[:file_set_fixture]
36
+ fd.unload_all_classes! if fd
37
+ end
38
+
39
+ def this_example_name
40
+ per_example_data[:this_example_name] ||= this_example.metadata[:full_description].strip.downcase.gsub(/[^A-Za-z0-9_]+/, '_')
41
+ end
42
+
43
+ def this_spec_root
44
+ per_example_data[:this_spec_root] ||= extant_directory(tempdir_root, this_spec_name)
45
+ end
46
+
47
+ def this_spec_name
48
+ per_example_data[:this_spec_name] ||= begin
49
+ name = self.class.name
50
+ name = $1 if name =~ /::([^:]+)$/i
51
+ name.strip.downcase.gsub(/[^A-Za-z0-9_]+/, '_')
52
+ end
53
+ end
54
+
55
+ def gem_root
56
+ per_example_data[:gem_root] ||= extant_directory(File.dirname(File.dirname(File.dirname(__FILE__))))
57
+ end
58
+
59
+ def tempdir_root
60
+ per_example_data[:tempdir_root] ||= extant_directory(gem_root, 'tmp', 'spec')
61
+ end
62
+
63
+ def extant_directory(*path_components)
64
+ out = path(*path_components)
65
+ FileUtils.mkdir_p(out)
66
+ out
67
+ end
68
+
69
+ def clean_directory(*path_components)
70
+ p = path(*path_components)
71
+ FileUtils.rm_rf(p)
72
+ FileUtils.mkdir_p(p)
73
+ p
74
+ end
75
+
76
+ def path(*path_components)
77
+ File.expand_path(File.join(*path_components))
78
+ end
79
+ end
@@ -0,0 +1,34 @@
1
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'parcels'
4
+
5
+ require 'spec/parsing/sprockets_asset'
6
+ require 'spec/parsing/compiled_asset'
7
+ require 'spec/expected/expected_asset'
8
+
9
+ require 'helpers/file_structure_helpers'
10
+ require 'helpers/content_in_helpers'
11
+ require 'helpers/sprockets_helpers'
12
+ require 'helpers/per_example_helpers'
13
+ require 'helpers/parcels_rails_helpers'
14
+ require 'helpers/new_asset_helpers'
15
+ require 'helpers/new_rails_helpers'
16
+
17
+ require 'oop_rails_server'
18
+
19
+ RSpec.configure do |c|
20
+ c.include ContentInHelpers
21
+ c.include PerExampleHelpers
22
+ c.include FileStructureHelpers
23
+ c.include NewAssetHelpers, :type => :system
24
+ c.include NewRailsHelpers, :type => :rails
25
+
26
+ c.include SprocketsHelpers, :type => :system
27
+
28
+ c.include ::OopRailsServer::Helpers, :type => :rails
29
+ c.include ParcelsRailsHelpers, :type => :rails
30
+
31
+ c.before(:each) do |example|
32
+ set_up_per_example_data!(example)
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec/expected/expected_asset_set'
2
+
3
+ module NewAssetHelpers
4
+ def sprockets_asset(name, the_sprockets_env = nil)
5
+ the_sprockets_env ||= sprockets_env
6
+ ::Spec::Parsing::SprocketsAsset.new(the_sprockets_env, name)
7
+ end
8
+
9
+ def compiled_sprockets_asset(name, the_sprockets_env = nil)
10
+ ::Spec::Parsing::CompiledAsset.new(sprockets_asset(name, the_sprockets_env))
11
+ end
12
+
13
+ def expected_file_asset(subpath, &block)
14
+ ::Spec::Expected::ExpectedAsset.new(files_root, subpath, &block)
15
+ end
16
+
17
+ def file_assets(&block)
18
+ ::Spec::Expected::ExpectedAssetSet.new(files_root, &block)
19
+ end
20
+
21
+ def render_file_asset(subpath, args = { }, options = { })
22
+ subpath = $1 if subpath =~ %r{^(.*?)\.rb$}i
23
+ full_path = File.join(files_root, subpath)
24
+ full_path += ".rb" unless full_path =~ /\.rb\s*$/i
25
+ widget_class = Fortitude::Widget.widget_class_from_file(full_path, :root_dirs => files_root)
26
+ html = widget_class.new(args).to_html
27
+ out = Nokogiri::HTML(html)
28
+ out = out.xpath('/html/body') if options.fetch(:extract_body_contents, true)
29
+ out
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec/parsing/compiled_asset'
2
+ require 'spec/parsing/rails_asset'
3
+ require 'spec/parsing/precompiled_rails_asset'
4
+ require 'spec/expected/expected_asset'
5
+ require 'spec/expected/expected_asset_set'
6
+
7
+ module NewRailsHelpers
8
+ def rails_asset(name, the_rails_server = nil)
9
+ the_rails_server ||= rails_server
10
+ ::Spec::Parsing::RailsAsset.new(the_rails_server, name)
11
+ end
12
+
13
+ def compiled_rails_asset(name, the_rails_server = nil)
14
+ ::Spec::Parsing::CompiledAsset.new(rails_asset(name, the_rails_server))
15
+ end
16
+
17
+ def precompiled_rails_asset(name, the_rails_server = nil)
18
+ the_rails_server ||= rails_server
19
+ ::Spec::Parsing::CompiledAsset.new(::Spec::Parsing::PrecompiledRailsAsset.new(the_rails_server, name))
20
+ end
21
+
22
+ def expected_rails_asset(subpath, the_rails_server = nil, &block)
23
+ the_rails_server ||= rails_server
24
+ ::Spec::Expected::ExpectedAsset.new("#{the_rails_server.rails_root}/app", subpath, &block)
25
+ end
26
+
27
+ def rails_assets(the_rails_server = nil, &block)
28
+ the_rails_server ||= rails_server
29
+ ::Spec::Expected::ExpectedAssetSet.new("#{the_rails_server.rails_root}/app", &block)
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ module ParcelsRailsHelpers
2
+ def rails_server_project_root
3
+ @rails_server_project_root ||= File.expand_path(File.join(File.dirname(__FILE__), '../..'))
4
+ end
5
+
6
+ def rails_server_additional_gemfile_lines
7
+ [
8
+ "gem 'fortitude', \">= 0.9.0\"",
9
+ "gem 'parcels', :path => '#{rails_server_project_root}'"
10
+ ]
11
+ end
12
+
13
+ def rails_server_implicit_template_paths
14
+ [ :base ]
15
+ end
16
+
17
+ def rails_server_default_version
18
+ ENV['PARCELS_SPECS_RAILS_VERSION']
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ module PerExampleHelpers
2
+ def set_up_per_example_data!(example)
3
+ @per_example_data = {
4
+ :example => example
5
+ }
6
+ end
7
+
8
+ def per_example_data
9
+ (@per_example_data || raise("#set_up_per_example_data! was not called!"))
10
+ end
11
+
12
+ def this_example
13
+ per_example_data[:example]
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ module SprocketsHelpers
2
+ def new_sprockets_env(*args)
3
+ ::Sprockets::Environment.new(*args)
4
+ end
5
+
6
+ def sprockets_env(*args, &block)
7
+ out = if args.length > 0 || block
8
+ raise "Duplicate creation of sprockets_env? #{args.inspect}" if @sprockets_env
9
+ args = [ this_example_root ] if args.length == 0
10
+ per_example_data[:sprockets_env] = new_sprockets_env(*args)
11
+ block.call(per_example_data[:sprockets_env]) if block
12
+ else
13
+ per_example_data[:sprockets_env] ||= begin
14
+ out = new_sprockets_env(this_example_root)
15
+ out.append_path 'assets'
16
+ out
17
+ end
18
+ end
19
+
20
+ out.parcels.add_widget_tree!(File.join(this_example_root, 'views'))
21
+ out
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ module Spec
2
+ module Expected
3
+ class BaseExpectedAsset
4
+ def initialize(root_directory, expected_subpath)
5
+ @root_directory = root_directory
6
+ @expected_subpath = expected_subpath
7
+ end
8
+
9
+ def to_s
10
+ "<#{self.class.name} at #{expected_subpath.inspect}>"
11
+ end
12
+
13
+ private
14
+ attr_reader :root_directory, :expected_subpath
15
+
16
+ def filename
17
+ @filename ||= begin
18
+ if expected_subpath.kind_of?(Symbol)
19
+ expected_subpath
20
+ else
21
+ File.join(root_directory, expected_subpath)
22
+ end
23
+ end
24
+ end
25
+
26
+ def applies_to_asset?(asset)
27
+ asset.filename == filename
28
+ end
29
+
30
+ def applicable_assets_from(remaining_assets)
31
+ remaining_assets.select { |a| applies_to_asset?(a) }
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,135 @@
1
+ require 'spec/parsing/parsed_css_asset'
2
+
3
+ require 'spec/expected/base_expected_asset'
4
+
5
+ module Spec
6
+ module Expected
7
+ class ExpectedAsset < BaseExpectedAsset
8
+ def initialize(root_directory, expected_subpath, &block)
9
+ super(root_directory, expected_subpath)
10
+
11
+ @expected_rules = { }
12
+ @allow_extra_rules = false
13
+
14
+ instance_eval(&block) if block
15
+ end
16
+
17
+ def source
18
+ out = ""
19
+ expected_rules.each do |selector, rules|
20
+ out << "#{selector} {\n"
21
+ rules.each do |rule|
22
+ out << " #{rule}\n"
23
+ end
24
+ out << "}\n\n"
25
+ end
26
+ out.strip
27
+ end
28
+
29
+ def expect_rules(selector, *rules)
30
+ selector = selector.to_s
31
+ expected_rules[selector] ||= [ ]
32
+ expected_rules[selector] += rules
33
+ end
34
+ alias_method :expect_rule, :expect_rules
35
+
36
+ def expect_wrapped_rules(selector, *rules)
37
+ wrapped_selector = wrap_selector(selector)
38
+ expect_rules(wrapped_selector, *rules)
39
+ end
40
+ alias_method :expect_wrapped_rule, :expect_wrapped_rules
41
+
42
+ def allow_extra_rules!
43
+ @allow_extra_rules = true
44
+ end
45
+
46
+ def should_match(remaining_assets)
47
+ matching_remaining_assets = applicable_assets_from(remaining_assets)
48
+
49
+ if matching_remaining_assets.length == 0
50
+ message = "Expected match not found:\n #{self}\nnot found in these assets:"
51
+ remaining_assets.each do |remaining_asset|
52
+ message << "\n\n #{remaining_asset}:\n #{remaining_asset.source}\n"
53
+ end
54
+ raise message
55
+ elsif matching_remaining_assets.length == 1
56
+ matching_remaining_asset = matching_remaining_assets.first
57
+
58
+ unless asset_matches?(matching_remaining_asset)
59
+ raise "Asset mismatch for #{matching_remaining_asset.where_from}: expected\n #{source}\ndoes not match actual\n #{matching_remaining_asset.source}"
60
+ end
61
+
62
+ [ matching_remaining_asset ]
63
+ elsif matching_remaining_assets.length > 1
64
+ message = "Multiple assets match:\n #{self}\nin:"
65
+ matching_remaining_assets.each do |matching_remaining_asset|
66
+ message << "\n\n #{matching_remaining_asset}:\n #{matching_remaining_asset.source}\n"
67
+ end
68
+ raise message
69
+ end
70
+ end
71
+
72
+ def parcels_wrapping_class
73
+ @parcels_wrapping_class ||= begin
74
+ out = expected_subpath.dup
75
+ out = $1 if out =~ /^(.*?)\.([^\/]+)$/i
76
+ out = out.gsub('/', '__').gsub(/[^A-Za-z0-9_]/, '_')
77
+ "parcels_class__#{out}"
78
+ end
79
+ end
80
+
81
+ private
82
+ attr_reader :expected_rules
83
+
84
+ def extra_rules_allowed?
85
+ !! @allow_extra_rules
86
+ end
87
+
88
+ def wrap_selector(selector)
89
+ if selector
90
+ ".#{parcels_wrapping_class} #{selector}"
91
+ else
92
+ ".#{parcels_wrapping_class}"
93
+ end
94
+ end
95
+
96
+ def asset_matches?(asset)
97
+ parsed_asset = ::Spec::Parsing::ParsedCssAsset.new(asset)
98
+
99
+ actual_rules = parsed_asset.style_rules.dup
100
+
101
+ expected_rules.each do |expected_selector, expected_rules_for_this_selector|
102
+ actual_rules_for_this_selector = actual_rules[expected_selector]
103
+ return false unless actual_rules_for_this_selector
104
+
105
+ matches = (actual_rules_for_this_selector.length == expected_rules_for_this_selector.length)
106
+ if matches
107
+ actual_rules_for_this_selector.each_with_index do |actual_rule, index|
108
+ expected_rule = expected_rules_for_this_selector[index]
109
+
110
+ this_matches = if expected_rule.kind_of?(String)
111
+ actual_rule == expected_rule
112
+ elsif expected_rule.kind_of?(Regexp)
113
+ actual_rule =~ expected_rule
114
+ else
115
+ false
116
+ end
117
+
118
+ matches &&= this_matches
119
+ end
120
+
121
+ actual_rules.delete(expected_selector)
122
+ end
123
+
124
+ return false unless matches
125
+ end
126
+
127
+ if actual_rules.length > 0 && (! extra_rules_allowed?)
128
+ return false
129
+ end
130
+
131
+ true
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec/expected/expected_asset'
2
+ require 'spec/expected/must_not_be_present_asset'
3
+
4
+ module Spec
5
+ module Expected
6
+ class ExpectedAssetSet
7
+ def initialize(root_directory, &block)
8
+ @root_directory = root_directory
9
+ @expected_assets = [ ]
10
+ @allows_additional = false
11
+
12
+ instance_eval(&block) if block
13
+ end
14
+
15
+ def asset(subpath, &block)
16
+ expected_asset = Spec::Expected::ExpectedAsset.new(root_directory, subpath, &block)
17
+ @expected_assets << expected_asset
18
+ end
19
+
20
+ def asset_must_not_be_present(subpath)
21
+ expected_asset = Spec::Expected::MustNotBePresentAsset.new(root_directory, subpath)
22
+ @expected_assets << expected_asset
23
+ end
24
+
25
+ def expected_assets
26
+ @expected_assets
27
+ end
28
+
29
+ def allow_additional_assets!
30
+ @allows_additional = true
31
+ end
32
+
33
+ def allows_additional?
34
+ !! @allows_additional
35
+ end
36
+
37
+ def to_s
38
+ "<ExpectedAssetSet: #{@expected_assets.length} assets:\n #{@expected_assets.join("\n ")}>"
39
+ end
40
+
41
+ private
42
+ attr_reader :root_directory
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec/expected/base_expected_asset'
2
+
3
+ module Spec
4
+ module Expected
5
+ class MustNotBePresentAsset < BaseExpectedAsset
6
+ def should_match(remaining_assets)
7
+ matching = applicable_assets_from(remaining_assets)
8
+
9
+ if matching.length > 0
10
+ raise "Assets found that must not be present:\n #{matching.join("\n ")}"
11
+ end
12
+
13
+ [ ]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec/fixtures/widget_base'
2
+ require 'spec/fixtures/widget_file'
3
+
4
+ module Spec
5
+ module Fixtures
6
+ class FileSet
7
+ attr_reader :root_dir
8
+
9
+ def initialize(root_dir)
10
+ @root_dir = root_dir
11
+ @files = { }
12
+ @widgets = { }
13
+ end
14
+
15
+ def file(subpath, contents = nil)
16
+ contents = $2 if contents =~ /\A(\s*\n)*(.*?)(\s\n)*\Z/mi
17
+ files[subpath] = contents
18
+ end
19
+
20
+ def widget(subpath, options = { }, &block)
21
+ class_name = options[:class_name]
22
+ class_name ||= begin
23
+ out = subpath
24
+ out = $1 if out =~ /^(.*)(\.[A-Z0-9_]+)+$/i
25
+ out = out.camelize
26
+ out
27
+ end
28
+ superclass = options[:superclass] || ::Spec::Fixtures::WidgetBase
29
+ superclass = superclass.name if superclass.kind_of?(Class)
30
+ subpath += ".rb" unless subpath =~ /\.rb$/i
31
+
32
+ widget_definition = ::Spec::Fixtures::WidgetFile.new(class_name, superclass, root_dir)
33
+ widget_definition.instance_eval(&block) if block
34
+
35
+ @widgets[subpath] = widget_definition
36
+ end
37
+
38
+ def create!
39
+ files.each do |subpath, contents|
40
+ full_path = File.join(root_dir, subpath)
41
+ FileUtils.mkdir_p(File.dirname(full_path))
42
+ File.open(full_path, 'w') { |f| f << contents }
43
+ end
44
+
45
+ widgets.each do |subpath, definition|
46
+ full_path = File.join(root_dir, subpath)
47
+ FileUtils.mkdir_p(File.dirname(full_path))
48
+ File.open(full_path, 'w') { |f| f << definition.source_text }
49
+ end
50
+ end
51
+
52
+ def unload_all_classes!
53
+ subpaths = files.keys | widgets.keys
54
+
55
+ subpaths.each do |subpath|
56
+ next unless subpath =~ /\.rb$/i
57
+ full_path = File.join(root_dir, subpath)
58
+ widget_class = ::Fortitude::Widget.widget_class_from_file(full_path, :root_dirs => root_dir) rescue nil
59
+
60
+ if widget_class
61
+ parent = constant_name = nil
62
+
63
+ if widget_class.name =~ /^(.*)::([^:]+)$/i
64
+ parent = $1.constantize
65
+ constant_name = $2.to_sym
66
+ else
67
+ parent = ::Object
68
+ constant_name = widget_class.name.to_sym
69
+ end
70
+
71
+ parent.send(:remove_const, constant_name)
72
+ end
73
+ end
74
+ end
75
+
76
+ private
77
+ attr_reader :files, :widgets
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,13 @@
1
+ module Spec
2
+ module Fixtures
3
+ class WidgetBase < ::Fortitude::Widget
4
+ doctype :html5
5
+
6
+ enable_parcels!
7
+
8
+ def content
9
+ p "spec_widget #{self.class.name} contents!"
10
+ end
11
+ end
12
+ end
13
+ end