Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

guides preview + tests

  • Loading branch information...
commit 5a1cbe70ee8759f0c708150497762cfb6884a344 1 parent 6252db5
@wycats authored
View
1  Gemfile
@@ -3,3 +3,4 @@ source "http://rubygems.org"
gemspec
gem "rspec", "~> 2.0"
+gem "faraday", "~> 0.5.0"
View
1  guides.gemspec
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
s.add_dependency "rack", "~> 1.2.1"
s.add_dependency "RedCloth", "~> 4.1.1"
s.add_dependency "thor", "~> 0.14.6"
+ s.add_dependency "thin", "~> 1.2.7"
s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
View
4 lib/guides.rb
@@ -19,7 +19,9 @@ def root
File.expand_path(Dir.pwd)
end
- def meta
+ def meta(reload = false)
+ @meta = nil if reload
+
@meta ||= begin
if File.exist?("#{root}/guides.yml")
YAML.load_file("#{root}/guides.yml")
View
7 lib/guides/cli.rb
@@ -1,5 +1,6 @@
require "thor"
require "guides/new"
+require "guides/preview"
module Guides
class CLI < Thor
@@ -16,10 +17,10 @@ def new(name)
invoke "guides:new:copy", [name, options[:name] || name]
end
- desc "generate", "generate the guides output"
+ desc "build", "build the guides output"
method_option "only", :type => :array
method_option "clean", :type => :boolean
- def generate
+ def build
FileUtils.rm_rf("#{Guides.root}/output") if options[:clean]
require "guides/generator"
@@ -33,7 +34,7 @@ def generate
desc "preview", "preview the guides as you work"
def preview
-
+ Preview.start
end
desc "update", "when running from the pkg, updates the gem"
View
33 lib/guides/generator.rb
@@ -85,6 +85,33 @@ def generate
copy_assets
end
+ def generate_guide(guide, output_file)
+ return unless generate?(guide, output_file)
+
+ puts "Generating #{output_file}"
+ File.open(File.join(output_dir, output_file), 'w') do |f|
+ view = ActionView::Base.new(source_dir, :edge => edge)
+ view.extend(Helpers)
+
+ if guide =~ /\.html\.erb$/
+ # Generate the special pages like the home.
+ view.render("sections")
+ type = @edge ? "edge" : "normal"
+ result = view.render(:layout => 'layout', :file => guide, :locals => {:guide_type => type})
+ else
+ body = File.read(File.join(source_dir, guide))
+ body = set_header_section(body, view)
+ body = set_index(body, view)
+
+ result = view.render(:layout => 'layout', :text => textile(body))
+
+ warn_about_broken_links(result) if @warnings
+ end
+
+ f.write result
+ end
+ end
+
private
def generate_guides
guides_to_generate.each do |guide|
@@ -114,6 +141,12 @@ def copy_assets
def generate?(source_file, output_file)
fin = File.join(source_dir, source_file)
fout = File.join(output_dir, output_file)
+
+ if File.exists?(fout) && File.mtime(fout) < File.mtime(File.join(Guides.root, "guides.yml"))
+ Guides.meta(true)
+ return true
+ end
+
all || !File.exists?(fout) || File.mtime(fout) < File.mtime(fin)
end
View
50 lib/guides/preview.rb
@@ -0,0 +1,50 @@
+require "rack"
+
+module Guides
+ class App
+ LOCAL_ASSETS = File.expand_path("../templates/assets", __FILE__)
+ SOURCE_ASSETS = File.join(Guides.root, "assets")
+ SOURCE_TEMPLATES = File.join(Guides.root, "source")
+
+ def initialize
+ @local = Rack::File.new(LOCAL_ASSETS)
+ @source = Rack::File.new(SOURCE_ASSETS)
+ @output = Rack::File.new(File.join(Guides.root, "output"))
+ end
+
+ def call(env)
+ path = env["PATH_INFO"]
+
+ case path
+ when "/"
+ env["PATH_INFO"] = "/index.html"
+ return call(env)
+ when /(.*).html/
+ name = $1
+ generator = Guides::Generator.new({})
+ source_file = Dir["#{SOURCE_TEMPLATES}/#{name}.{html.erb,textile}"].first
+
+ unless source_file
+ return [404, {"Content-Type" => "text/html"}, ["#{name} not found"]]
+ end
+
+ generator.send(:generate_guide, File.basename(source_file), "#{name}.html")
+ return @output.call(env)
+ else
+ source = @source.call(env)
+ return source if source.first == 200
+ return @local.call(env)
+ end
+ end
+ end
+
+ class Preview < Rack::Server
+ def self.start(*)
+ super :host => '0.0.0.0', :Port => 9292, :server => "thin"
+ end
+
+ def app
+ @app ||= App.new
+ end
+ end
+end
View
19 spec/generate_spec.rb → spec/build_spec.rb
@@ -1,16 +1,11 @@
require "spec_helper"
-describe "guides generate" do
+describe "guides build" do
before(:all) do
- FileUtils.rm_rf(tmp.join("sample"))
- guides "new", "sample"
- wait
- Dir.chdir(tmp.join("sample"))
- guides "generate"
- end
-
- after(:all) do
- Dir.chdir(tmp)
+ reset_tmp
+ guides "new", "sample" and wait
+ Dir.chdir tmp.join("sample")
+ guides "build" and wait
end
it "generates the app" do
@@ -29,12 +24,12 @@
end
it "does nothing if run twice in a row" do
- guides "generate"
+ guides "build"
out.should be_blank
end
it "re-runs if run with --clean" do
- guides "generate", "--clean"
+ guides "build", "--clean"
out.should =~ /Generating contribute.html.*Generating credits.html.*Generating index.html/m
end
View
4 spec/new_spec.rb
@@ -1,6 +1,10 @@
require "spec_helper"
describe "guides new" do
+ before(:each) do
+ reset_tmp
+ end
+
it "prints an error if new is called with no name" do
guides "new", :track_stderr => true
err.should =~ /"new" was called incorrectly/
View
35 spec/preview_spec.rb
@@ -0,0 +1,35 @@
+require "spec_helper"
+
+describe "guides generate" do
+ before(:all) do
+ reset_tmp
+ guides "new", "sample" and wait
+ Dir.chdir tmp.join("sample")
+ guides "build" and wait
+ end
+
+ after(:all) do
+ Dir.chdir(tmp)
+ end
+
+ before(:each) do
+ host! :preview
+ launch_test_server
+ guides "preview"
+ end
+
+ it "downloads the index at /" do
+ get "/"
+ should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h3>Start Here<\/h3>/m
+ end
+
+ it "downloads the index at /index.html" do
+ get "/"
+ should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h3>Start Here<\/h3>/m
+ end
+
+ it "downloads contribute at /contribute.html" do
+ get "/contribute.html"
+ should_respond_with 200, /<!DOCTYPE html PUBLIC.*>.*<h2>Contribute<\/h2>/m
+ end
+end
View
7 spec/spec_helper.rb
@@ -1,6 +1,7 @@
require "fileutils"
require "pathname"
require "support/cli"
+require "support/rack"
RSpec.configure do |config|
include SpecHelpers
@@ -9,9 +10,13 @@ def tmp
@tmp ||= Pathname.new(File.expand_path("../../tmp", __FILE__))
end
- config.before(:suite) do
+ def reset_tmp
FileUtils.rm_rf(tmp)
FileUtils.mkdir_p(tmp)
Dir.chdir(tmp)
end
+
+ config.before(:suite) do
+ reset_tmp
+ end
end
View
112 spec/support/rack.rb
@@ -0,0 +1,112 @@
+require 'uri'
+require 'faraday'
+require 'rack'
+require 'webrick'
+require 'socket'
+
+Thread.abort_on_exception = true
+
+module SpecHelpers
+ RACK_ENV_KEYS = [ 'PATH_INFO', 'REQUEST_METHOD', 'QUERY_STRING', 'rack.input',
+ 'HTTP_X_ZOMG' ]
+
+ def self.launch_test_server
+ @test_server ||= begin
+ app = lambda do |env|
+ ret = env.slice(*RACK_ENV_KEYS)
+ ret['rack.input'] = ret['rack.input'].read if ret['rack.input']
+ [ 200, { 'Content-Type' => 'text/plain' }, ret.inspect ]
+ end
+
+ t = Thread.new do
+ logger = WEBrick::Log.new(nil, WEBrick::BasicLog::WARN)
+ Rack::Handler::WEBrick.run(app, :Host => '0.0.0.0', :Port => 9293,
+ :Logger => logger, :AccessLog => [])
+ end
+
+ begin
+ s = TCPSocket.new('0.0.0.0', 9293)
+ rescue Errno::ECONNREFUSED
+ sleep 0.2
+ retry
+ end
+
+ s.close
+ t
+ end
+ end
+
+ def launch_test_server
+ SpecHelpers.launch_test_server
+ end
+
+ %w( get post put delete head ).each do |method|
+ class_eval <<-RUBY
+ def #{method}(uri, *args)
+ request(:#{method}, uri, *args)
+ end
+ RUBY
+ end
+
+ attr_reader :response
+ attr_reader :host
+
+ def host!(host)
+ @host = host
+ end
+
+ def request(method, uri, *args)
+ uri = URI(uri)
+ host = uri.host || @host
+ scheme = uri.scheme || 'http'
+ headers = Hash === args.last ? args.pop : {}
+
+ if host == :preview
+ ip = host = 'http://localhost:9292'
+ else
+ ip = ENV['STROBEAPP_URL']
+ end
+
+ headers['Host'] = host
+ headers['Authorization'] = 'basic x:x' # hac to bypass varnish
+
+ conn = Faraday::Connection.new(:url => ip) do |c|
+ c.use Faraday::Adapter::NetHttp
+ c.headers.merge! headers
+ end
+
+ path = uri.path
+ path = "#{path}?#{uri.query}" if uri.query
+
+ @response = conn.run_request(method, path, args.first, {})
+ end
+
+ def should_respond_with(status, body = nil, hdrs = {})
+ @response.status.should == status
+
+ if body.is_a?(Regexp)
+ @response.body.should =~ body
+ elsif body
+ @response.body.should == body
+ end
+
+ hdrs.each do |hdr, val|
+ @response.headers[hdr].should == val
+ end
+ end
+
+ def should_have_env(env)
+ @response.status.should == 200
+ empty = RACK_ENV_KEYS - env.keys
+ actual = eval(@response.body)
+
+ env.each do |key, val|
+ actual[key].should == val
+ end
+
+ empty.each do |key|
+ actual[key].should be_blank
+ end
+ end
+end
+
Please sign in to comment.
Something went wrong with that request. Please try again.