organizing code around Service and Repository classes (dependency injection). In progress

did committed Jan 30, 2015
commit 897d4d5db4733c4d6cb2e1504aa9e2db9188bc17
Showing 22 changed files with 740 additions and 261 deletions
Gemfile.lock +2 -0
@@ @@ -11,6 +11,7 @@ PATH
kaminari (~> 0.16.2)
kramdown (~> 1.5.0)
locomotivecms-solid (~> 4.0.0.alpha)
+ mimetype-fu (~> 0.1.2)
moneta (~> 0.8.0)
rack-cache (~> 1.2)
sprockets (~> 2.12.3)
@@ @@ -108,6 +109,7 @@ GEM
nokogiri (>= 1.5.9)
method_source (0.8.2)
mime-types (2.4.3)
+ mimetype-fu (0.1.2)
mini_portile (0.6.2)
minitest (5.5.1)
moneta (0.8.0)
locomotive/steam.rb b/lib/locomotive/steam.rb +16 -1
@@ @@ -7,10 +7,18 @@ require_relative 'steam/decorators'
require_relative 'steam/configuration'
require_relative 'steam/liquid'
+ require_relative 'steam/morphine'
+ # require_relative 'steam/default_repositories/theme_asset'
+ require_relative 'steam/repositories'
+ require_relative 'steam/services'
+
+ # TODO: move into a file named dependencies
require 'sprockets'
require 'sprockets-sass'
require 'haml'
require 'compass'
+ require 'mimetype_fu'
+ require 'mime-types'
require 'active_support'
require 'active_support/concern'
@@ @@ -23,7 +31,14 @@ require 'mime/types'
module Locomotive
module Steam
- TEMPLATE_EXTENSIONS = %w(liquid haml)
+ # Locomotive::Steam.repositories.get(:site)
+ # Locomotive::Steam.repositories.get(:theme_assets, site)
+
+ # a la fin de chaque requete => on clean les repositories
+
+ # Locomotive::Steam.repositories[:theme_assets](site)
+
+ # TEMPLATE_EXTENSIONS = %w(liquid haml)
class << self
attr_writer :configuration
locomotive/steam/configuration.rb b/lib/locomotive/steam/configuration.rb +4 -2
@@ @@ -2,10 +2,12 @@ module Locomotive
module Steam
class Configuration
- attr_accessor :mode
+
+ attr_accessor :mode, :theme_assets_checksum, :asset_host
def initialize
- self.mode = :production
+ self.mode = :production
+ self.theme_assets_checksum = false
end
end
locomotive/steam/liquid/asset_host.rb b/lib/locomotive/steam/liquid/asset_host.rb +0 -53
@@ @@ -1,53 +0,0 @@
- module Locomotive
- module Steam
- module Liquid
-
- class AssetHost
-
- IsHTTP = /^https?\/\//o
-
- attr_reader :request, :site, :host
-
- def initialize(request, site, host)
- @request, @site = request, site
-
- @host = build_host(host, request, site)
- end
-
- def compute(source, timestamp = nil)
- return source if source.nil?
-
- return add_timestamp_suffix(source, timestamp) if source =~ IsHTTP
-
- url = self.host ? URI.join(host, source).to_s : source
-
- add_timestamp_suffix(url, timestamp)
- end
-
- private
-
- def build_host(host, request, site)
- if host
- if host.respond_to?(:call)
- host.call(request, site)
- else
- host
- end
- else
- nil
- end
- end
-
- def add_timestamp_suffix(source, timestamp)
- if timestamp.nil? || timestamp == 0 || source.include?('?')
- source
- else
- "#{source}?#{timestamp}"
- end
- end
-
- end
-
- end
- end
- end
locomotive/steam/liquid/filters/base.rb b/lib/locomotive/steam/liquid/filters/base.rb +35 -47
@@ @@ -1,61 +1,49 @@
module Locomotive
- module Liquid
- module Filters
- module Base
-
- protected
-
- # Convert an array of properties ('key:value') into a hash
- # Ex: ['width:50', 'height:100'] => { width: '50', height: '100' }
- def args_to_options(*args)
- options = {}
- args.flatten.each do |a|
- if (a =~ /^(.*):(.*)$/)
- options[$1.to_sym] = $2
+ module Steam
+ module Liquid
+ module Filters
+ module Base
+
+ protected
+
+ # Convert an array of properties ('key:value') into a hash
+ # Ex: ['width:50', 'height:100'] => { width: '50', height: '100' }
+ def args_to_options(*args)
+ options = {}
+ args.flatten.each do |a|
+ if (a =~ /^(.*):(.*)$/)
+ options[$1.to_sym] = $2
+ end
end
+ options
end
- options
- end
-
- # Write options (Hash) into a string according to the following pattern:
- # <key1>="<value1>", <key2>="<value2", ...etc
- def inline_options(options = {})
- return '' if options.empty?
- (options.stringify_keys.sort.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
- end
- # Get the url to be used in html tags such as image_tag, flash_tag, ...etc
- # input: url (String) OR asset drop
- def get_url_from_asset(input)
- input.respond_to?(:url) ? input.url : input
- end
-
- def asset_url(path)
- # keep the query string safe
- path.gsub!(/(\?+.+)$/, '')
- query_string = $1
+ # Write options (Hash) into a string according to the following pattern:
+ # <key1>="<value1>", <key2>="<value2", ...etc
+ def inline_options(options = {})
+ return '' if options.empty?
+ (options.stringify_keys.sort.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
+ end
- # build the url of the theme asset based on the site and without loading
- # the whole theme asset from database
- _url = ThemeAssetUploader.url_for(@context.registers[:site], path)
+ # Get the url to be used in html tags such as image_tag, flash_tag, ...etc
+ # input: url (String) OR asset drop
+ def get_url_from_asset(input)
+ input.respond_to?(:url) ? input.url : input
+ end
- # get a timestamp only the source url does not include a query string
- timestamp = query_string.blank? ? @context.registers[:theme_assets_checksum][path] : nil
+ def asset_url(path)
+ @context.registers[:services].theme_asset_url.build(path)
+ end
- # prefix by a asset host if given
- url = @context.registers[:asset_host].compute(_url, timestamp)
+ def absolute_url(url)
+ url.starts_with?('/') ? url : "/#{url}"
+ end
- query_string ? "#{url}#{query_string}" : url
end
- def absolute_url(url)
- url.starts_with?('/') ? url : "/#{url}"
- end
+ ::Liquid::Template.register_filter(Base)
end
-
- ::Liquid::Template.register_filter(Base)
-
end
end
- end
\ No newline at end of file
+ end
locomotive/steam/liquid/filters/html.rb b/lib/locomotive/steam/liquid/filters/html.rb +91 -89
@@ @@ -1,117 +1,119 @@
module Locomotive
- module Liquid
- module Filters
- module Html
-
- # Return a link tag that browsers and news readers can use to auto-detect an RSS or ATOM feed.
- # input: url of the feed
- # example:
- # {{ '/foo/bar' | auto_discovery_link_tag: 'rel:alternate', 'type:application/atom+xml', 'title:A title' }}
- def auto_discovery_link_tag(input, *args)
- options = args_to_options(args)
-
- rel = options[:rel] || 'alternate'
- type = options[:type] || Mime::Type.lookup_by_extension('rss').to_s
- title = options[:title] || 'RSS'
-
- %{<link rel="#{rel}" type="#{type}" title="#{title}" href="#{input}">}
- end
+ module Steam
+ module Liquid
+ module Filters
+ module Html
+
+ # Return a link tag that browsers and news readers can use to auto-detect an RSS or ATOM feed.
+ # input: url of the feed
+ # example:
+ # {{ '/foo/bar' | auto_discovery_link_tag: 'rel:alternate', 'type:application/atom+xml', 'title:A title' }}
+ def auto_discovery_link_tag(input, *args)
+ options = args_to_options(args)
+
+ rel = options[:rel] || 'alternate'
+ type = options[:type] || 'application/rss+xml'
+ title = options[:title] || 'RSS'
+
+ %{<link rel="#{rel}" type="#{type}" title="#{title}" href="#{input}">}
+ end
+
+ # Write the url of a theme stylesheet
+ # input: name of the css file
+ def stylesheet_url(input)
+ return '' if input.nil?
- # Write the url of a theme stylesheet
- # input: name of the css file
- def stylesheet_url(input)
- return '' if input.nil?
+ if input =~ /^(\/|https?:)/
+ uri = URI(input)
+ else
+ uri = URI(asset_url("stylesheets/#{input}"))
+ end
- if input =~ /^(\/|https?:)/
- uri = URI(input)
- else
- uri = URI(asset_url("stylesheets/#{input}"))
+ uri.path = "#{uri.path}.css" unless uri.path.ends_with?('.css')
+ uri.to_s
end
- uri.path = "#{uri.path}.css" unless uri.path.ends_with?('.css')
- uri.to_s
- end
+ # Write the link tag of a theme stylesheet
+ # input: url of the css file
+ def stylesheet_tag(input, media = 'screen')
+ return '' if input.nil?
- # Write the link tag of a theme stylesheet
- # input: url of the css file
- def stylesheet_tag(input, media = 'screen')
- return '' if input.nil?
+ input = stylesheet_url(input)
- input = stylesheet_url(input)
+ %{<link href="#{input}" media="#{media}" rel="stylesheet" type="text/css">}
+ end
- %{<link href="#{input}" media="#{media}" rel="stylesheet" type="text/css">}
- end
+ # Write the url to javascript resource
+ # input: name of the javascript file
+ def javascript_url(input)
+ return '' if input.nil?
- # Write the url to javascript resource
- # input: name of the javascript file
- def javascript_url(input)
- return '' if input.nil?
+ if input =~ /^(\/|https?:)/
+ uri = URI(input)
+ else
+ uri = URI(asset_url("javascripts/#{input}"))
+ end
- if input =~ /^(\/|https?:)/
- uri = URI(input)
- else
- uri = URI(asset_url("javascripts/#{input}"))
+ uri.path = "#{uri.path}.js" unless uri.path.ends_with?('.js')
+ uri.to_s
end
- uri.path = "#{uri.path}.js" unless uri.path.ends_with?('.js')
- uri.to_s
- end
+ # Write the link to javascript resource
+ # input: url of the javascript file
+ def javascript_tag(input, *args)
+ return '' if input.nil?
+ javascript_options = inline_options(args_to_options(args))
+ input = javascript_url(input)
- # Write the link to javascript resource
- # input: url of the javascript file
- def javascript_tag(input, *args)
- return '' if input.nil?
- javascript_options = inline_options(args_to_options(args))
- input = javascript_url(input)
+ "<script src=\"#{input}\" type=\"text/javascript\" #{javascript_options}></script>"
+ end
- "<script src=\"#{input}\" type=\"text/javascript\" #{javascript_options}></script>"
- end
+ def theme_image_url(input)
+ return '' if input.nil?
- def theme_image_url(input)
- return '' if input.nil?
+ input = "images/#{input}" unless input.starts_with?('/')
- input = "images/#{input}" unless input.starts_with?('/')
+ asset_url(input)
+ end
- asset_url(input)
- end
+ # Write a theme image tag
+ # input: name of file including folder
+ # example: 'about/myphoto.jpg' | theme_image # <img src="images/about/myphoto.jpg">
+ def theme_image_tag(input, *args)
+ image_options = inline_options(args_to_options(args))
- # Write a theme image tag
- # input: name of file including folder
- # example: 'about/myphoto.jpg' | theme_image # <img src="images/about/myphoto.jpg">
- def theme_image_tag(input, *args)
- image_options = inline_options(args_to_options(args))
+ "<img src=\"#{theme_image_url(input)}\" #{image_options}>"
+ end
- "<img src=\"#{theme_image_url(input)}\" #{image_options}>"
- end
+ # Write an image tag
+ # input: url of the image OR asset drop
+ def image_tag(input, *args)
+ image_options = inline_options(args_to_options(args))
- # Write an image tag
- # input: url of the image OR asset drop
- def image_tag(input, *args)
- image_options = inline_options(args_to_options(args))
+ "<img src=\"#{get_url_from_asset(input)}\" #{image_options}>"
+ end
- "<img src=\"#{get_url_from_asset(input)}\" #{image_options}>"
- end
+ # Embed a flash movie into a page
+ # input: url of the flash movie OR asset drop
+ # width: width (in pixel or in %) of the embedded movie
+ # height: height (in pixel or in %) of the embedded movie
+ def flash_tag(input, *args)
+ path = get_url_from_asset(input)
+ embed_options = inline_options(args_to_options(args))
+ %{
+ <object #{embed_options}>
+ <param name="movie" value="#{path}">
+ <embed src="#{path}" #{embed_options}>
+ </embed>
+ </object>
+ }.gsub(/ >/, '>').strip
+ end
- # Embed a flash movie into a page
- # input: url of the flash movie OR asset drop
- # width: width (in pixel or in %) of the embedded movie
- # height: height (in pixel or in %) of the embedded movie
- def flash_tag(input, *args)
- path = get_url_from_asset(input)
- embed_options = inline_options(args_to_options(args))
- %{
- <object #{embed_options}>
- <param name="movie" value="#{path}">
- <embed src="#{path}" #{embed_options}>
- </embed>
- </object>
- }.gsub(/ >/, '>').strip
end
- end
-
- ::Liquid::Template.register_filter(Html)
+ ::Liquid::Template.register_filter(Html)
+ end
end
end
end
locomotive/steam/morphine.rb b/lib/locomotive/steam/morphine.rb +26 -0
@@ @@ -0,0 +1,26 @@
+ # Morphine is a lightweight dependency injection framework for Ruby. It uses a simple Ruby DSL to ease the pain of wiring your dependencies together.
+ # We do not use the offical gem but rather the single file from here:
+ # https://github.com/bkeepers/morphine
+ #
+
+ module Morphine
+ def self.included(base)
+ base.extend ClassMethods
+ end
+
+ def dependencies
+ @dependencies ||= {}
+ end
+
+ module ClassMethods
+ def register(name, &block)
+ define_method name do |*args|
+ dependencies[name] ||= instance_exec(*args,&block)
+ end
+
+ define_method "#{name}=" do |service|
+ dependencies[name] = service
+ end
+ end
+ end
+ end
locomotive/steam/repositories.rb b/lib/locomotive/steam/repositories.rb +28 -0
@@ @@ -0,0 +1,28 @@
+ Dir[File.join(File.dirname(__FILE__), 'repositories', '*.rb')].each { |lib| require lib }
+
+ module Locomotive
+ module Steam
+ module Repositories
+
+ def self.instance(site = nil)
+ Registered.new(site)
+ end
+
+ class Registered < Struct.new(:current_site)
+
+ include Morphine
+
+ # default repositories
+ register :site do
+ Repositories::Site.new
+ end
+
+ register :theme_asset do
+ Repositories::ThemeAsset.new(current_site)
+ end
+
+ end
+
+ end
+ end
+ end
locomotive/steam/repositories/content_types_repository.rb b/lib/locomotive/steam/repositories/content_types_repository.rb +14 -14
@@ @@ -1,14 +1,14 @@
- module Locomotive
- module Steam
- module Repositories
- class ContentTypesRepository
- include Repository
- def [](slug)
- query(:en) do
- where('slug.eq' => slug.to_s)
- end.first
- end
- end
- end
- end
- end
+ # module Locomotive
+ # module Steam
+ # module Repositories
+ # class ContentTypesRepository
+ # include Repository
+ # def [](slug)
+ # query(:en) do
+ # where('slug.eq' => slug.to_s)
+ # end.first
+ # end
+ # end
+ # end
+ # end
+ # end
locomotive/steam/repositories/pages_repository.rb b/lib/locomotive/steam/repositories/pages_repository.rb +21 -21
@@ @@ -1,23 +1,23 @@
- module Locomotive
- module Steam
- module Repositories
- class PagesRepository
- include Repository
- attr_accessor :current_locale
+ # module Locomotive
+ # module Steam
+ # module Repositories
+ # class PagesRepository
+ # include Repository
+ # attr_accessor :current_locale
- def [](path)
- query(current_locale) do
- where('fullpath.eq' => path)
- end.first
- end
+ # def [](path)
+ # query(current_locale) do
+ # where('fullpath.eq' => path)
+ # end.first
+ # end
- def matching_paths(paths)
- query(current_locale) do
- where('fullpath.in' => paths)
- order_by('position ASC')
- end
- end
- end
- end
- end
- end
+ # def matching_paths(paths)
+ # query(current_locale) do
+ # where('fullpath.in' => paths)
+ # order_by('position ASC')
+ # end
+ # end
+ # end
+ # end
+ # end
+ # end
locomotive/steam/repositories/site_repository.rb b/lib/locomotive/steam/repositories/site_repository.rb +19 -0
@@ @@ -0,0 +1,19 @@
+ module Locomotive
+ module Steam
+ module Repositories
+
+ class Site
+
+ def find_by_host(host)
+ raise 'TODO'
+ # TODO multilocales
+ # query(:en) do
+ # where('domains.in' => host)
+ # end.first
+ end
+
+ end
+
+ end
+ end
+ end
locomotive/steam/repositories/sites_repository.rb b/lib/locomotive/steam/repositories/sites_repository.rb +0 -16
@@ @@ -1,16 +0,0 @@
- module Locomotive
- module Steam
- module Repositories
- class SitesRepository
- include Repository
-
- def find_by_host(host)
- # TODO multilocales
- query(:en) do
- where('domains.in' => host)
- end.first
- end
- end
- end
- end
- end
locomotive/steam/repositories/theme_asset.rb b/lib/locomotive/steam/repositories/theme_asset.rb +19 -0
@@ @@ -0,0 +1,19 @@
+ module Locomotive
+ module Steam
+ module Repositories
+
+ class ThemeAsset < Struct.new(:site)
+
+ def url_for(path)
+ URI.join('sites', site._id, 'theme', path).to_s
+ end
+
+ def checksums
+ @site.theme_assets.checksums
+ end
+
+ end
+
+ end
+ end
+ end
locomotive/steam/server.rb b/lib/locomotive/steam/server.rb +7 -16
@@ @@ -23,36 +23,27 @@ module Locomotive::Steam
def _call(env)
set_request(env)
- set_path(env)
+ register_services(env)
fetch_site(env)
- set_services(env)
-
@app.call(env)
end
protected
- def set_path(env)
- env['steam.path'] = options.fetch(:path)
- end
def set_request(env)
- @request = Rack::Request.new(env)
- env['steam.request'] = @request
+ env['steam.request'] = Rack::Request.new(env)
end
def fetch_site(env)
- # one single mounting point per site
- env['steam.site'] = Locomotive::Models[:sites].find_by_host(@request.host)
+ site = env['steam.services'].site_finder.find
+ env['steam.site'] = env['steam.services'].repositories.current_site = site
+
end
- def set_services(env)
- env['steam.services'] = {
- dragonfly: Locomotive::Steam::Services::Dragonfly.new(options.fetch(:path)),
- markdown: Locomotive::Steam::Services::Markdown.new,
- external_api: Locomotive::Steam::Services::ExternalAPI.new
- }
+ def register_services(env)
+ env['steam.services'] = Locomotive::Steam::Services.instance(env['steam.request'], options)
end
end
locomotive/steam/services.rb b/lib/locomotive/steam/services.rb +43 -1
@@ @@ -1 +1,43 @@
- Dir[File.join(File.dirname(__FILE__), 'services', '*.rb')].each { |lib| require lib }
\ No newline at end of file
+ Dir[File.join(File.dirname(__FILE__), 'services', '*.rb')].each { |lib| require lib }
+
+ module Locomotive
+ module Steam
+ module Services
+
+ def self.instance(request, options = {})
+ Registered.new(request, options)
+ end
+
+ class Registered < Struct.new(:request, :options)
+
+ include Morphine
+
+ register :repositories do
+ Repositories.instance
+ end
+
+ register :site_finder do
+ Services::SiteFinder.new(request, repositories.site, options)
+ end
+
+ register :theme_asset_url do
+ Services::ThemeAssetUrl.new(current_site, asset_host, configuration.theme_assets_checksum)
+ end
+
+ register :asset_host do
+ Services::AssetHost.new(request, current_site, configuration.asset_host)
+ end
+
+ def current_site
+ repositories.current_site
+ end
+
+ def configuration
+ Locomotive::Steam.configuration
+ end
+
+ end
+
+ end
+ end
+ end
locomotive/steam/services/asset_host.rb b/lib/locomotive/steam/services/asset_host.rb +53 -0
@@ @@ -0,0 +1,53 @@
+ module Locomotive
+ module Steam
+ module Services
+
+ class AssetHost
+
+ IsHTTP = /^https?\/\//o
+
+ attr_reader :request, :site, :host
+
+ def initialize(request, site, host)
+ @request, @site = request, site
+
+ @host = build_host(host, request, site)
+ end
+
+ def compute(source, timestamp = nil)
+ return source if source.nil?
+
+ return add_timestamp_suffix(source, timestamp) if source =~ IsHTTP
+
+ url = self.host ? URI.join(host, source).to_s : source
+
+ add_timestamp_suffix(url, timestamp)
+ end
+
+ private
+
+ def build_host(host, request, site)
+ if host
+ if host.respond_to?(:call)
+ host.call(request, site)
+ else
+ host
+ end
+ else
+ nil
+ end
+ end
+
+ def add_timestamp_suffix(source, timestamp)
+ if timestamp.nil? || timestamp == 0 || source.include?('?')
+ source
+ else
+ "#{source}?#{timestamp}"
+ end
+ end
+
+ end
+
+ end
+ end
+ end
locomotive/steam/services/dragonfly.rb b/lib/locomotive/steam/services/dragonfly.rb +1 -1
@@ @@ -46,4 +46,4 @@ module Locomotive
end
end
end
- end
\ No newline at end of file
+ end
locomotive/steam/services/site_finder.rb b/lib/locomotive/steam/services/site_finder.rb +15 -0
@@ @@ -0,0 +1,15 @@
+ module Locomotive
+ module Steam
+ module Services
+
+ class SiteFinder < Struct.new(:repository, :request, :options)
+
+ def find
+ repository.find_by_host(request.host)
+ end
+
+ end
+
+ end
+ end
+ end
locomotive/steam/services/theme_asset_url.rb b/lib/locomotive/steam/services/theme_asset_url.rb +45 -0
@@ @@ -0,0 +1,45 @@
+ module Locomotive
+ module Steam
+ module Services
+
+ class ThemeAssetUrl < Struct.new(:repository, :asset_host, :checksum)
+
+ def buid(path)
+ # keep the query string safe
+ path.gsub!(/(\?+.+)$/, '')
+ query_string = $1
+
+ # build the url of the theme asset based on the persistence layer
+ _url = repository.url_for(path)
+
+ # get a timestamp only the source url does not include a query string
+ timestamp = query_string.blank? ? checksums[path] : nil
+
+ # prefix by a asset host if given
+ url = asset_host.compute(_url, timestamp)
+
+ query_string ? "#{url}#{query_string}" : url
+ end
+
+ def checksums
+ if checksum?
+ @checksums ||= fetch_checksums
+ else
+ {}
+ end
+ end
+
+ def checksum?
+ !!checksum
+ end
+
+ private
+
+ def fetch_checksums
+ repository.checksums
+ end
+
+ end
+ end
+ end
+ end
locomotivecms_steam.gemspec +1 -0
@@ @@ -38,6 +38,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'coffee-script', '~> 2.2.0'
spec.add_dependency 'haml', '~> 4.0.6'
spec.add_dependency 'compass', '~> 1.0.3'
+ spec.add_dependency 'mimetype-fu', '~> 0.1.2'
# spec.add_dependency 'locomotivecms_models', '~> 0.0.1.pre.alpha'
spec/unit/liquid/filters/html_spec.rb +256 -0
@@ @@ -0,0 +1,256 @@
+ require 'spec_helper'
+
+ describe Locomotive::Steam::Liquid::Filters::Html do
+
+ include Locomotive::Steam::Liquid::Filters::Base
+ include Locomotive::Steam::Liquid::Filters::Html
+
+ before(:each) do
+ @context = build_context
+ end
+
+ it 'writes the tag to display a rss/atom feed' do
+ expect(auto_discovery_link_tag('/foo/bar')).to eq %(
+ <link rel="alternate" type="application/rss+xml" title="RSS" href="/foo/bar">
+ ).strip
+
+ expect(auto_discovery_link_tag('/foo/bar', 'rel:alternate2', 'type:atom', 'title:Hello world')).to eq %(
+ <link rel="alternate2" type="atom" title="Hello world" href="/foo/bar">
+ ).strip
+ end
+
+ it 'returns an url for a stylesheet file' do
+ result = "/sites/000000000000000000000042/theme/stylesheets/main.css"
+ expect(stylesheet_url('main.css')).to eq(result)
+ expect(stylesheet_url('main')).to eq(result)
+ expect(stylesheet_url(nil)).to eq('')
+ end
+
+ it 'returnss an url with the checksum' do
+ @context.registers.merge!(theme_assets_checksum: { 'stylesheets/main.css' => 42 })
+ result = "/sites/000000000000000000000042/theme/stylesheets/main.css?42"
+ expect(stylesheet_url('main.css')).to eq(result)
+ end
+
+ it 'returns an url for a stylesheet file with folder' do
+ result = "/sites/000000000000000000000042/theme/stylesheets/trash/main.css"
+ expect(stylesheet_url('trash/main.css')).to eq(result)
+ end
+
+ it 'returns an url for a stylesheet file without touching the url that starts with "/"' do
+ result = "/trash/main.css"
+ expect(stylesheet_url('/trash/main.css')).to eq(result)
+ expect(stylesheet_url('/trash/main')).to eq(result)
+ end
+
+ it 'returns an url for a stylesheet file without touching the url that starts with "http:"' do
+ result = "http://cdn.example.com/trash/main.css"
+ expect(stylesheet_url('http://cdn.example.com/trash/main.css')).to eq(result)
+ expect(stylesheet_url('http://cdn.example.com/trash/main')).to eq(result)
+ end
+
+ it 'returns an url for a stylesheet file without touching the url that starts with "https:"' do
+ result = "https://cdn.example.com/trash/main.css"
+ expect(stylesheet_url('https://cdn.example.com/trash/main.css')).to eq(result)
+ expect(stylesheet_url('https://cdn.example.com/trash/main')).to eq(result)
+ end
+
+ it 'returns an url for a stylesheet file with respect to URL-parameters' do
+ result = "/sites/000000000000000000000042/theme/stylesheets/main.css?v=42"
+ expect(stylesheet_url('main.css?v=42')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet file' do
+ result = "<link href=\"/sites/000000000000000000000042/theme/stylesheets/main.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('main.css')).to eq(result)
+ expect(stylesheet_tag('main')).to eq(result)
+ expect(stylesheet_tag(nil)).to eq('')
+ end
+
+ it 'returns a link tag for a stylesheet file with folder' do
+ result = "<link href=\"/sites/000000000000000000000042/theme/stylesheets/trash/main.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('trash/main.css')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet file without touching the url that starts with "/"' do
+ result = "<link href=\"/trash/main.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('/trash/main.css')).to eq(result)
+ expect(stylesheet_tag('/trash/main')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet file without touching the url that starts with "http:"' do
+ result = "<link href=\"http://cdn.example.com/trash/main.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('http://cdn.example.com/trash/main.css')).to eq(result)
+ expect(stylesheet_tag('http://cdn.example.com/trash/main')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet file without touching the url that starts with "https:"' do
+ result = "<link href=\"https://cdn.example.com/trash/main.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('https://cdn.example.com/trash/main.css')).to eq(result)
+ expect(stylesheet_tag('https://cdn.example.com/trash/main')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet stored in Amazon S3' do
+ url = 'https://com.citrrus.locomotive.s3.amazonaws.com/sites/42/theme/stylesheets/bootstrap2.css'
+ stubs(:asset_url).returns(url)
+ result = "<link href=\"#{url}\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('bootstrap2.css')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet file and media attribute set to print' do
+ result = "<link href=\"/sites/000000000000000000000042/theme/stylesheets/main.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('main.css','print')).to eq(result)
+ expect(stylesheet_tag('main','print')).to eq(result)
+ expect(stylesheet_tag(nil)).to eq('')
+ end
+
+ it 'returns a link tag for a stylesheet file with folder and media attribute set to print' do
+ result = "<link href=\"/sites/000000000000000000000042/theme/stylesheets/trash/main.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('trash/main.css','print')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet file without touching the url that starts with "/" and media attribute set to print' do
+ result = "<link href=\"/trash/main.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('/trash/main.css','print')).to eq(result)
+ expect(stylesheet_tag('/trash/main','print')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet file without touching the url that starts with "http:" and media attribute set to print' do
+ result = "<link href=\"http://cdn.example.com/trash/main.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('http://cdn.example.com/trash/main.css','print')).to eq(result)
+ expect(stylesheet_tag('http://cdn.example.com/trash/main','print')).to eq(result)
+ end
+
+ it 'returns a link tag for a stylesheet file without touching the url that starts with "https:" and media attribute set to print' do
+ result = "<link href=\"https://cdn.example.com/trash/main.css\" media=\"print\" rel=\"stylesheet\" type=\"text/css\">"
+ expect(stylesheet_tag('https://cdn.example.com/trash/main.css','print')).to eq(result)
+ expect(stylesheet_tag('https://cdn.example.com/trash/main','print')).to eq(result)
+ end
+
+ it 'returns an url for a javascript file' do
+ result = "/sites/000000000000000000000042/theme/javascripts/main.js"
+ expect(javascript_url('main.js')).to eq(result)
+ expect(javascript_url('main')).to eq(result)
+ expect(javascript_url(nil)).to eq('')
+ end
+
+ it 'returns an url for a javascript file with folder' do
+ result = "/sites/000000000000000000000042/theme/javascripts/trash/main.js"
+ expect(javascript_url('trash/main.js')).to eq(result)
+ expect(javascript_url('trash/main')).to eq(result)
+ end
+
+ it 'returns an url for a javascript file without touching the url that starts with "/"' do
+ result = "/trash/main.js"
+ expect(javascript_url('/trash/main.js')).to eq(result)
+ expect(javascript_url('/trash/main')).to eq(result)
+ end
+
+ it 'returns an url for a javascript file without touching the url that starts with "http:"' do
+ result = "http://cdn.example.com/trash/main.js"
+ expect(javascript_url('http://cdn.example.com/trash/main.js')).to eq(result)
+ expect(javascript_url('http://cdn.example.com/trash/main')).to eq(result)
+ end
+
+ it 'returns an url for a javascript file without touching the url that starts with "https:"' do
+ result = "https://cdn.example.com/trash/main.js"
+ expect(javascript_url('https://cdn.example.com/trash/main.js')).to eq(result)
+ expect(javascript_url('https://cdn.example.com/trash/main')).to eq(result)
+ end
+
+ it 'returns an url for a javascript file with respect to URL-parameters' do
+ result = "/sites/000000000000000000000042/theme/javascripts/main.js?v=42"
+ expect(javascript_url('main.js?v=42')).to eq(result)
+ end
+
+ it 'returns a script tag for a javascript file' do
+ result = %{<script src="/sites/000000000000000000000042/theme/javascripts/main.js" type="text/javascript" ></script>}
+ expect(javascript_tag('main.js')).to eq(result)
+ expect(javascript_tag('main')).to eq(result)
+ expect(javascript_tag(nil)).to eq('')
+ end
+
+ it 'returns a script tag for a javascript file with folder' do
+ result = %{<script src="/sites/000000000000000000000042/theme/javascripts/trash/main.js" type="text/javascript" ></script>}
+ expect(javascript_tag('trash/main.js')).to eq(result)
+ expect(javascript_tag('trash/main')).to eq(result)
+ end
+
+ it 'returns a script tag for a javascript file without touching the url that starts with "/"' do
+ result = %{<script src="/trash/main.js" type="text/javascript" ></script>}
+ expect(javascript_tag('/trash/main.js')).to eq(result)
+ expect(javascript_tag('/trash/main')).to eq(result)
+ end
+
+ it 'returns a script tag for a javascript file without touching the url that starts with "http:"' do
+ result = %{<script src="http://cdn.example.com/trash/main.js" type="text/javascript" ></script>}
+ expect(javascript_tag('http://cdn.example.com/trash/main.js')).to eq(result)
+ expect(javascript_tag('http://cdn.example.com/trash/main')).to eq(result)
+ end
+
+ it 'returns a script tag for a javascript file without touching the url that starts with "https:"' do
+ result = %{<script src="https://cdn.example.com/trash/main.js" type="text/javascript" ></script>}
+ expect(javascript_tag('https://cdn.example.com/trash/main.js')).to eq(result)
+ expect(javascript_tag('https://cdn.example.com/trash/main')).to eq(result)
+ end
+
+ it 'returns a script tag for a javascript file with "defer" option' do
+ result = %{<script src="https://cdn.example.com/trash/main.js" type="text/javascript" defer="defer" ></script>}
+ expect(javascript_tag('https://cdn.example.com/trash/main.js', ['defer:defer'])).to eq(result)
+ end
+
+ it 'returns an image tag for a given theme file without parameters' do
+ expect(theme_image_tag('foo.jpg')).to eq("<img src=\"/sites/000000000000000000000042/theme/images/foo.jpg\" >")
+ end
+
+ it 'returns an image tag for a given theme file with size' do
+ expect(theme_image_tag('foo.jpg', 'width:100', 'height:100')).to eq("<img src=\"/sites/000000000000000000000042/theme/images/foo.jpg\" height=\"100\" width=\"100\" >")
+ end
+
+ it 'returns an image tag without parameters' do
+ expect(image_tag('foo.jpg')).to eq("<img src=\"foo.jpg\" >")
+ end
+
+ it 'returns an image tag with size' do
+ expect(image_tag('foo.jpg', 'width:100', 'height:50')).to eq("<img src=\"foo.jpg\" height=\"50\" width=\"100\" >")
+ end
+
+ it 'returns a flash tag without parameters' do
+ expect(flash_tag('foo.flv')).to eq(%{
+ <object>
+ <param name="movie" value="foo.flv">
+ <embed src="foo.flv">
+ </embed>
+ </object>
+ }.strip)
+ end
+
+ it 'returns a flash tag with size' do
+ expect(flash_tag('foo.flv', 'width:100', 'height:50')).to eq(%{
+ <object height=\"50\" width=\"100\">
+ <param name="movie" value="foo.flv">
+ <embed src="foo.flv" height=\"50\" width=\"100\">
+ </embed>
+ </object>
+ }.strip)
+ end
+
+ def build_context
+ klass = Class.new
+ klass.class_eval do
+ def registers
+ @registers ||= {
+ site: FactoryGirl.build(:site, id: fake_bson_id(42)),
+ theme_assets_checksum: {},
+ asset_host: TimestampAssetHost.new
+ }
+ end
+
+ def fake_bson_id(id)
+ BSON::ObjectId.from_string(id.to_s.rjust(24, '0'))
+ end
+ end
+ klass.new
+ end
+
+ end
spec/unit/repositories_spec.rb +44 -0
@@ @@ -0,0 +1,44 @@
+ require 'spec_helper'
+
+ describe Locomotive::Steam::Repositories do
+
+ let(:site) { instance_double('Site', name: 'PCH') }
+ let(:repositories) { Locomotive::Steam::Repositories.instance(site) }
+
+ describe '#theme_asset' do
+
+ subject { repositories.theme_asset }
+
+ context 'by default' do
+
+ it 'returns a class of ThemeAssetRepository' do
+ expect(subject.class).to eq Locomotive::Steam::Repositories::ThemeAsset
+ end
+
+ it 'gets access to the site' do
+ expect(subject.site.name).to eq 'PCH'
+ end
+
+ end
+
+ context 'a different repository' do
+
+ before do
+ repositories.theme_asset = MyThemeAssetRepository.new(site)
+ end
+
+ it 'returns a class of ThemeAssetRepository' do
+ expect(subject.class).to eq MyThemeAssetRepository
+ end
+
+ it 'gets access to the site' do
+ expect(subject.site.name).to eq 'PCH'
+ end
+
+ end
+
+ end
+
+ class MyThemeAssetRepository < Struct.new(:site); end
+
+ end