Skip to content

Commit 7098a7e

Browse files
committedJul 31, 2015
Create a build environment for the Chrome Extension
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
1 parent 5e4bce6 commit 7098a7e

File tree

9 files changed

+201
-57
lines changed

9 files changed

+201
-57
lines changed
 

‎.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ test/dummy/tmp/
99
test/dummy/.sass-cache
1010
Gemfile.lock
1111
node_modules/
12+
dist/
13+
tmp/

‎Rakefile

+66-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ require 'socket'
88
require 'rake/testtask'
99
require 'tmpdir'
1010
require 'securerandom'
11+
require 'json'
12+
require 'web_console/testing/erb_precompiler'
1113

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

@@ -20,11 +22,11 @@ end
2022

2123
namespace :test do
2224
desc "Run tests for templates"
23-
task :templates => "templates:all"
25+
task templates: "templates:all"
2426

2527
namespace :templates do
26-
task :all => [:daemonize, :npm, :rackup, :mocha, :kill]
27-
task :serve => [:npm, :rackup]
28+
task all: [ :daemonize, :npm, :rackup, :mocha, :kill ]
29+
task serve: [ :npm, :rackup ]
2830

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

58+
namespace :ext do
59+
rootdir = Pathname('extensions')
60+
61+
desc 'Build Chrome Extension'
62+
task chrome: 'chrome:build'
63+
64+
namespace :chrome do
65+
dist = Pathname('dist/crx')
66+
extdir = rootdir.join(dist)
67+
manifest_json = rootdir.join('chrome/manifest.json')
68+
69+
directory extdir
70+
71+
task build: [ extdir, 'lib:templates' ] do
72+
cd rootdir do
73+
cp_r [ 'img/', 'tmp/lib/' ], dist
74+
`cd chrome && git ls-files`.split("\n").each do |src|
75+
dest = dist.join(src)
76+
mkdir_p dest.dirname
77+
cp Pathname('chrome').join(src), dest
78+
end
79+
end
80+
end
81+
82+
# Generate a .crx file.
83+
task crx: [ :build, :npm ] do
84+
out = "crx-web-console-#{JSON.parse(File.read(manifest_json))["version"]}.crx"
85+
cd(extdir) { sh "node \"$(npm bin)/crx\" pack ./ -p ../crx-web-console.pem -o ../#{out}" }
86+
end
87+
88+
# Generate a .zip file for Chrome Web Store.
89+
task zip: [ :build ] do
90+
version = JSON.parse(File.read(manifest_json))["version"]
91+
cd(extdir) { sh "zip -r ../crx-web-console-#{version}.zip ./" }
92+
end
93+
94+
desc 'Launch a browser with the chrome extension.'
95+
task run: [ :build ] do
96+
cd(rootdir) { sh "sh ./script/run_chrome.sh --load-extension=#{dist}" }
97+
end
98+
end
99+
100+
task :npm do
101+
cd(rootdir) { sh "npm install --silent" }
102+
end
103+
104+
namespace :lib do
105+
templates = Pathname('lib/web_console/templates')
106+
tmplib = rootdir.join('tmp/lib/')
107+
js_erb = FileList.new(templates.join('**/*.js.erb'))
108+
dirs = js_erb.pathmap("%{^#{templates},#{tmplib}}d")
109+
110+
task templates: dirs + js_erb.pathmap("%{^#{templates},#{tmplib}}X")
111+
112+
dirs.each { |d| directory d }
113+
rule '.js' => [ "%{^#{tmplib},#{templates}}X.js.erb" ] do |t|
114+
File.write(t.name, WebConsole::Testing::ERBPrecompiler.new(t.source).build)
115+
end
116+
end
117+
end
118+
56119
Bundler::GemHelper.install_tasks
57120

58121
task default: :test

‎extensions/README.markdown

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Web Console Browser Extensions
2+
3+
## Development
4+
5+
### Quickstart
6+
7+
```
8+
$ git clone https://github.com/rails/web-console.git
9+
$ cd web-console
10+
$ bundle install
11+
$ bundle exec rake ext:chrome:run
12+
```

‎extensions/package.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "dev",
3+
"version": "0.0.0",
4+
"devDependencies": {
5+
"crx": "^3.0.2"
6+
}
7+
}

‎extensions/script/run_chrome.sh

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/sh
2+
3+
is_command() {
4+
type $1 > /dev/null 2>&1
5+
}
6+
7+
find_chrome_binary() {
8+
for name in 'chromium' 'google-chrome' 'chromium-browser'; do
9+
if is_command $name; then
10+
echo $name
11+
return
12+
fi
13+
done
14+
}
15+
16+
CHROME_BINARY=${CHROME_BINARY:-`find_chrome_binary`}
17+
18+
if is_command $CHROME_BINARY; then
19+
$CHROME_BINARY $@
20+
else
21+
echo 'ERROR: Chrome is not found.'
22+
echo 'Please try "CHROME_BINARY=path/to/chrome".'
23+
exit 1
24+
fi
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
require 'web_console/testing/helper'
2+
require 'web_console/testing/fake_middleware'
3+
4+
module WebConsole
5+
module Testing
6+
# This class is to pre-compile 'templates/*.erb'.
7+
class ERBPrecompiler
8+
def initialize(path)
9+
@erb = ERB.new(File.read(path))
10+
@view = FakeMiddleware.new(
11+
view_path: Helper.gem_root.join('lib/web_console/templates'),
12+
).view
13+
end
14+
15+
def build
16+
@erb.result(binding)
17+
end
18+
19+
def method_missing(name, *args, &block)
20+
return super unless @view.respond_to?(name)
21+
@view.send(name, *args, &block)
22+
end
23+
end
24+
end
25+
end
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
require 'action_view'
2+
require 'action_dispatch'
3+
require 'json'
4+
require 'web_console/whitelist'
5+
require 'web_console/request'
6+
7+
module WebConsole
8+
module Testing
9+
class FakeMiddleware
10+
DEFAULT_HEADERS = { "Content-Type" => "application/javascript" }
11+
12+
def initialize(opts)
13+
@headers = opts.fetch(:headers, DEFAULT_HEADERS)
14+
@req_path_regex = opts[:req_path_regex]
15+
@view_path = opts[:view_path]
16+
end
17+
18+
def call(env)
19+
[ 200, @headers, [ render(req_path(env)) ] ]
20+
end
21+
22+
def view
23+
@view ||= create_view
24+
end
25+
26+
private
27+
28+
# extract target path from REQUEST_PATH
29+
def req_path(env)
30+
env["REQUEST_PATH"].match(@req_path_regex)[1]
31+
end
32+
33+
def render(template)
34+
view.render(template: template, layout: nil)
35+
end
36+
37+
def create_view
38+
lookup_context = ActionView::LookupContext.new(@view_path)
39+
lookup_context.cache = false
40+
FakeView.new(lookup_context)
41+
end
42+
43+
class FakeView < ActionView::Base
44+
def render_inlined_string(template)
45+
render(template: template, layout: "layouts/inlined_string")
46+
end
47+
end
48+
end
49+
end
50+
end

‎lib/web_console/testing/helper.rb

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module WebConsole
2+
module Testing
3+
module Helper
4+
def self.gem_root
5+
Pathname(File.expand_path('../../../../', __FILE__))
6+
end
7+
end
8+
end
9+
end

‎test/templates/config.ru

+6-54
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,7 @@
1-
require "action_view"
2-
require "pathname"
3-
require "action_dispatch"
4-
require "web_console"
1+
require "web_console/testing/fake_middleware"
52

63
TEST_ROOT = Pathname(__FILE__).dirname
74

8-
class FakeMiddleware
9-
DEFAULT_HEADERS = {"Content-Type" => "application/javascript"}
10-
11-
def initialize(opts)
12-
@headers = opts.fetch(:headers, DEFAULT_HEADERS)
13-
@req_path_regex = opts[:req_path_regex]
14-
@view_path = opts[:view_path]
15-
end
16-
17-
def call(env)
18-
[200, headers, [render(req_path(env))]]
19-
end
20-
21-
private
22-
23-
attr_reader :headers
24-
attr_reader :req_path_regex
25-
attr_reader :view_path
26-
27-
# extract target path from REQUEST_PATH
28-
def req_path(env)
29-
env["REQUEST_PATH"].match(req_path_regex)[1]
30-
end
31-
32-
def render(template)
33-
view.render(template: template, layout: nil)
34-
end
35-
36-
def view
37-
@view ||= create_view
38-
end
39-
40-
def create_view
41-
lookup_context = ActionView::LookupContext.new(view_path)
42-
lookup_context.cache = false
43-
FakeView.new(lookup_context)
44-
end
45-
46-
class FakeView < ActionView::Base
47-
def render_inlined_string(template)
48-
render(template: template, layout: "layouts/inlined_string")
49-
end
50-
end
51-
end
52-
535
# e.g. "/node_modules/mocha/mocha.js"
546
map "/node_modules" do
557
node_modules = TEST_ROOT.join("node_modules")
@@ -61,22 +13,22 @@ end
6113

6214
# test runners
6315
map "/html" do
64-
run FakeMiddleware.new(
16+
run WebConsole::Testing::FakeMiddleware.new(
6517
req_path_regex: %r{^/html/(.*)},
6618
headers: {"Content-Type" => "text/html"},
6719
view_path: TEST_ROOT.join("html"),
6820
)
6921
end
7022

7123
map "/spec" do
72-
run FakeMiddleware.new(
24+
run WebConsole::Testing::FakeMiddleware.new(
7325
req_path_regex: %r{^/spec/(.*)},
7426
view_path: TEST_ROOT.join("spec"),
7527
)
7628
end
7729

7830
map "/templates" do
79-
run FakeMiddleware.new(
31+
run WebConsole::Testing::FakeMiddleware.new(
8032
req_path_regex: %r{^/templates/(.*)},
8133
view_path: TEST_ROOT.join("../../lib/web_console/templates"),
8234
)
@@ -85,11 +37,11 @@ end
8537
map "/mock/repl/result" do
8638
headers = { 'Content-Type' => 'application/json' }
8739
body = [ { output: '=> "fake-result"\n' }.to_json ]
88-
run lambda { |env| [200, headers, body] }
40+
run lambda { |env| [ 200, headers, body ] }
8941
end
9042

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

0 commit comments

Comments
 (0)
Please sign in to comment.