Skip to content

Commit

Permalink
Create a build environment for the Chrome Extension
Browse files Browse the repository at this point in the history
For the development:

```
$ git clone https://github.com/rails/web-console.git
$ cd web-console
$ bundle install
$ bundle exec rake ext:chrome:run
=> Chrome will be launched with the extension.
```

And provide some rake tasks for the extension:

- "ext:chrome" is to build the extension
- "ext:chrome:run" is to launch a browser with the extension
- "ext:chrome:zip" is to generate .zip
- "ext:chrome:crx" is to generate .crx
  • Loading branch information
sh19910711 committed Jul 31, 2015
1 parent 5e4bce6 commit 7098a7e
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ test/dummy/tmp/
test/dummy/.sass-cache
Gemfile.lock
node_modules/
dist/
tmp/
69 changes: 66 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ require 'socket'
require 'rake/testtask'
require 'tmpdir'
require 'securerandom'
require 'json'
require 'web_console/testing/erb_precompiler'

EXPANDED_CWD = File.expand_path(File.dirname(__FILE__))

Expand All @@ -20,11 +22,11 @@ end

namespace :test do
desc "Run tests for templates"
task :templates => "templates:all"
task templates: "templates:all"

namespace :templates do
task :all => [:daemonize, :npm, :rackup, :mocha, :kill]
task :serve => [:npm, :rackup]
task all: [ :daemonize, :npm, :rackup, :mocha, :kill ]
task serve: [ :npm, :rackup ]

work_dir = Pathname(__FILE__).dirname.join("test/templates")
pid_file = Pathname(Dir.tmpdir).join("web_console.#{SecureRandom.uuid}.pid")
Expand Down Expand Up @@ -53,6 +55,67 @@ namespace :test do
end
end

namespace :ext do
rootdir = Pathname('extensions')

desc 'Build Chrome Extension'
task chrome: 'chrome:build'

namespace :chrome do
dist = Pathname('dist/crx')
extdir = rootdir.join(dist)
manifest_json = rootdir.join('chrome/manifest.json')

directory extdir

task build: [ extdir, 'lib:templates' ] do
cd rootdir do
cp_r [ 'img/', 'tmp/lib/' ], dist
`cd chrome && git ls-files`.split("\n").each do |src|
dest = dist.join(src)
mkdir_p dest.dirname
cp Pathname('chrome').join(src), dest
end
end
end

# Generate a .crx file.
task crx: [ :build, :npm ] do
out = "crx-web-console-#{JSON.parse(File.read(manifest_json))["version"]}.crx"
cd(extdir) { sh "node \"$(npm bin)/crx\" pack ./ -p ../crx-web-console.pem -o ../#{out}" }
end

# Generate a .zip file for Chrome Web Store.
task zip: [ :build ] do
version = JSON.parse(File.read(manifest_json))["version"]
cd(extdir) { sh "zip -r ../crx-web-console-#{version}.zip ./" }
end

desc 'Launch a browser with the chrome extension.'
task run: [ :build ] do
cd(rootdir) { sh "sh ./script/run_chrome.sh --load-extension=#{dist}" }
end
end

task :npm do
cd(rootdir) { sh "npm install --silent" }
end

namespace :lib do
templates = Pathname('lib/web_console/templates')
tmplib = rootdir.join('tmp/lib/')
js_erb = FileList.new(templates.join('**/*.js.erb'))
dirs = js_erb.pathmap("%{^#{templates},#{tmplib}}d")

task templates: dirs + js_erb.pathmap("%{^#{templates},#{tmplib}}X")

dirs.each { |d| directory d }
rule '.js' => [ "%{^#{tmplib},#{templates}}X.js.erb" ] do |t|
File.write(t.name, WebConsole::Testing::ERBPrecompiler.new(t.source).build)
end
end
end

Bundler::GemHelper.install_tasks

task default: :test
12 changes: 12 additions & 0 deletions extensions/README.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Web Console Browser Extensions

## Development

### Quickstart

```
$ git clone https://github.com/rails/web-console.git
$ cd web-console
$ bundle install
$ bundle exec rake ext:chrome:run
```
7 changes: 7 additions & 0 deletions extensions/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "dev",
"version": "0.0.0",
"devDependencies": {
"crx": "^3.0.2"
}
}
24 changes: 24 additions & 0 deletions extensions/script/run_chrome.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh

is_command() {
type $1 > /dev/null 2>&1
}

find_chrome_binary() {
for name in 'chromium' 'google-chrome' 'chromium-browser'; do
if is_command $name; then
echo $name
return
fi
done
}

CHROME_BINARY=${CHROME_BINARY:-`find_chrome_binary`}

if is_command $CHROME_BINARY; then
$CHROME_BINARY $@
else
echo 'ERROR: Chrome is not found.'
echo 'Please try "CHROME_BINARY=path/to/chrome".'
exit 1
fi
25 changes: 25 additions & 0 deletions lib/web_console/testing/erb_precompiler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'web_console/testing/helper'
require 'web_console/testing/fake_middleware'

module WebConsole
module Testing
# This class is to pre-compile 'templates/*.erb'.
class ERBPrecompiler
def initialize(path)
@erb = ERB.new(File.read(path))
@view = FakeMiddleware.new(
view_path: Helper.gem_root.join('lib/web_console/templates'),
).view
end

def build
@erb.result(binding)
end

def method_missing(name, *args, &block)
return super unless @view.respond_to?(name)
@view.send(name, *args, &block)
end
end
end
end
50 changes: 50 additions & 0 deletions lib/web_console/testing/fake_middleware.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'action_view'
require 'action_dispatch'
require 'json'
require 'web_console/whitelist'
require 'web_console/request'

module WebConsole
module Testing
class FakeMiddleware
DEFAULT_HEADERS = { "Content-Type" => "application/javascript" }

def initialize(opts)
@headers = opts.fetch(:headers, DEFAULT_HEADERS)
@req_path_regex = opts[:req_path_regex]
@view_path = opts[:view_path]
end

def call(env)
[ 200, @headers, [ render(req_path(env)) ] ]
end

def view
@view ||= create_view
end

private

# extract target path from REQUEST_PATH
def req_path(env)
env["REQUEST_PATH"].match(@req_path_regex)[1]
end

def render(template)
view.render(template: template, layout: nil)
end

def create_view
lookup_context = ActionView::LookupContext.new(@view_path)
lookup_context.cache = false
FakeView.new(lookup_context)
end

class FakeView < ActionView::Base
def render_inlined_string(template)
render(template: template, layout: "layouts/inlined_string")
end
end
end
end
end
9 changes: 9 additions & 0 deletions lib/web_console/testing/helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module WebConsole
module Testing
module Helper
def self.gem_root
Pathname(File.expand_path('../../../../', __FILE__))
end
end
end
end
60 changes: 6 additions & 54 deletions test/templates/config.ru
Original file line number Diff line number Diff line change
@@ -1,55 +1,7 @@
require "action_view"
require "pathname"
require "action_dispatch"
require "web_console"
require "web_console/testing/fake_middleware"

TEST_ROOT = Pathname(__FILE__).dirname

class FakeMiddleware
DEFAULT_HEADERS = {"Content-Type" => "application/javascript"}

def initialize(opts)
@headers = opts.fetch(:headers, DEFAULT_HEADERS)
@req_path_regex = opts[:req_path_regex]
@view_path = opts[:view_path]
end

def call(env)
[200, headers, [render(req_path(env))]]
end

private

attr_reader :headers
attr_reader :req_path_regex
attr_reader :view_path

# extract target path from REQUEST_PATH
def req_path(env)
env["REQUEST_PATH"].match(req_path_regex)[1]
end

def render(template)
view.render(template: template, layout: nil)
end

def view
@view ||= create_view
end

def create_view
lookup_context = ActionView::LookupContext.new(view_path)
lookup_context.cache = false
FakeView.new(lookup_context)
end

class FakeView < ActionView::Base
def render_inlined_string(template)
render(template: template, layout: "layouts/inlined_string")
end
end
end

# e.g. "/node_modules/mocha/mocha.js"
map "/node_modules" do
node_modules = TEST_ROOT.join("node_modules")
Expand All @@ -61,22 +13,22 @@ end

# test runners
map "/html" do
run FakeMiddleware.new(
run WebConsole::Testing::FakeMiddleware.new(
req_path_regex: %r{^/html/(.*)},
headers: {"Content-Type" => "text/html"},
view_path: TEST_ROOT.join("html"),
)
end

map "/spec" do
run FakeMiddleware.new(
run WebConsole::Testing::FakeMiddleware.new(
req_path_regex: %r{^/spec/(.*)},
view_path: TEST_ROOT.join("spec"),
)
end

map "/templates" do
run FakeMiddleware.new(
run WebConsole::Testing::FakeMiddleware.new(
req_path_regex: %r{^/templates/(.*)},
view_path: TEST_ROOT.join("../../lib/web_console/templates"),
)
Expand All @@ -85,11 +37,11 @@ end
map "/mock/repl/result" do
headers = { 'Content-Type' => 'application/json' }
body = [ { output: '=> "fake-result"\n' }.to_json ]
run lambda { |env| [200, headers, body] }
run lambda { |env| [ 200, headers, body ] }
end

map "/mock/repl/error" do
headers = { 'Content-Type' => 'application/json' }
body = [ { output: 'fake-error-message' }.to_json ]
run lambda { |env| [400, headers, body] }
run lambda { |env| [ 400, headers, body ] }
end

0 comments on commit 7098a7e

Please sign in to comment.