eris 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.md +2 -0
- data/Rakefile +2 -0
- data/bin/eris +5 -0
- data/eris.gemspec +36 -0
- data/js_helpers/ErisHelpers.js +84 -0
- data/lib/eris.rb +22 -0
- data/lib/eris/eris.ru +3 -0
- data/lib/eris/lib/eris_config.rb +17 -0
- data/lib/eris/lib/jasmine_config_overrides.rb +43 -0
- data/lib/eris/lib/jasmine_rspec_runner.rb +34 -0
- data/lib/eris/lib/luna_request.rb +51 -0
- data/lib/eris/lib/proxied_request.rb +18 -0
- data/lib/eris/lib/server.rb +75 -0
- data/lib/eris/tasks/generate.rb +19 -0
- data/lib/eris/tasks/server.rb +14 -0
- data/lib/eris/templates/Gemfile +5 -0
- data/lib/eris/templates/Rakefile +32 -0
- data/lib/eris/templates/ci_build.sh +16 -0
- data/lib/eris/templates/eris_config.json +3 -0
- data/lib/eris/templates/jasmine.yml +77 -0
- data/lib/eris/templates/sampleSpec.js +13 -0
- data/lib/eris/templates/specHelper.js +3 -0
- data/lib/eris/version.rb +3 -0
- data/spec/fixtures/enyo/0.10/framework/enyo.js +1 -0
- data/spec/fixtures/sample_app/app/models/foo.js +1 -0
- data/spec/fixtures/sample_app/appinfo.json +10 -0
- data/spec/fixtures/sample_app/eris_config.json +3 -0
- data/spec/fixtures/sample_app/index.html.erb +20 -0
- data/spec/fixtures/sample_app/spec/acceptance/helpers/AppHelper.js +0 -0
- data/spec/fixtures/vcr_cassettes/failure.yml +34 -0
- data/spec/fixtures/vcr_cassettes/success.yml +62 -0
- data/spec/lib/eris/lib/eris_config_spec.rb +25 -0
- data/spec/lib/eris/lib/eris_spec.rb +7 -0
- data/spec/lib/eris/lib/luna_request_spec.rb +27 -0
- data/spec/lib/eris/lib/proxied_request_spec.rb +19 -0
- data/spec/lib/eris/lib/server_spec.rb +175 -0
- data/spec/lib/eris/tasks/generator_integration_spec.rb +38 -0
- data/spec/lib/eris/tasks/generator_spec.rb +90 -0
- data/spec/lib/eris/tasks/server_spec.rb +44 -0
- data/spec/spec_helper.rb +41 -0
- metadata +309 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Eris
|
4
|
+
class Tasks < Thor
|
5
|
+
desc "server", "Launch the Eris server for your Enyo app"
|
6
|
+
method_option :port, :default => "9999", :aliases => "-p", :desc => "server port"
|
7
|
+
|
8
|
+
def server
|
9
|
+
port = options[:port]
|
10
|
+
puts "Starting Eris on port #{port}"
|
11
|
+
exec("rackup -p #{port} #{@@source_root}/lib/eris/eris.ru")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'jasmine'
|
2
|
+
|
3
|
+
namespace :jasmine do
|
4
|
+
task :server do
|
5
|
+
require 'jasmine'
|
6
|
+
require 'eris/lib/jasmine_config_overrides'
|
7
|
+
|
8
|
+
puts "your tests are here:"
|
9
|
+
puts " http://localhost:8888/"
|
10
|
+
|
11
|
+
Jasmine::Config.new.start_server
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Run continuous integration tests"
|
15
|
+
task :ci do
|
16
|
+
require 'jasmine'
|
17
|
+
require "rspec"
|
18
|
+
require "rspec/core/rake_task"
|
19
|
+
require 'eris'
|
20
|
+
ENV['JASMINE_BROWSER'] = 'chrome'
|
21
|
+
|
22
|
+
RSpec::Core::RakeTask.new(:jasmine_continuous_integration_runner) do |t|
|
23
|
+
t.rspec_opts = ["--color", "--format", "progress"]
|
24
|
+
t.verbose = true
|
25
|
+
t.pattern = ["#{Eris::FILE_PATH}/eris/lib/jasmine_rspec_runner.rb"]
|
26
|
+
end
|
27
|
+
Rake::Task["jasmine_continuous_integration_runner"].invoke
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Run specs with local config"
|
32
|
+
task :jasmine => ['jasmine:server']
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/bash -e
|
2
|
+
|
3
|
+
cd trunk
|
4
|
+
|
5
|
+
source $HOME/.rvm/scripts/rvm && source .rvmrc
|
6
|
+
|
7
|
+
# install bundler if necessary
|
8
|
+
gem list --local bundler | grep bundler || gem install bundler || exit 1
|
9
|
+
|
10
|
+
# debugging info
|
11
|
+
echo USER=$USER && ruby --version && which ruby && which bundle
|
12
|
+
|
13
|
+
# conditionally install project gems from Gemfile
|
14
|
+
bundle check || bundle install --deployment || exit 1
|
15
|
+
|
16
|
+
bundle exec rake jasmine:ci
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# src_files
|
2
|
+
#
|
3
|
+
# Return an array of filepaths relative to src_dir to include before jasmine specs.
|
4
|
+
# Default: []
|
5
|
+
#
|
6
|
+
# EXAMPLE:
|
7
|
+
#
|
8
|
+
# src_files:
|
9
|
+
# - lib/source1.js
|
10
|
+
# - lib/source2.js
|
11
|
+
# - dist/**/*.js
|
12
|
+
#
|
13
|
+
src_files:
|
14
|
+
- ../../enyo/1.0/framework/enyo.js
|
15
|
+
# For attempts at partially loading Enyo for specs
|
16
|
+
# - enyo/enyo-loader.js
|
17
|
+
# - spec/jasmine-depends.js
|
18
|
+
# - depends.js
|
19
|
+
|
20
|
+
# stylesheets
|
21
|
+
#
|
22
|
+
# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
|
23
|
+
# Default: []
|
24
|
+
#
|
25
|
+
# EXAMPLE:
|
26
|
+
#
|
27
|
+
# stylesheets:
|
28
|
+
# - css/style.css
|
29
|
+
# - stylesheets/*.css
|
30
|
+
#
|
31
|
+
stylesheets:
|
32
|
+
|
33
|
+
# helpers
|
34
|
+
#
|
35
|
+
# Return an array of filepaths relative to spec_dir to include before jasmine specs.
|
36
|
+
# Default: ["helpers/**/*.js"]
|
37
|
+
#
|
38
|
+
# EXAMPLE:
|
39
|
+
#
|
40
|
+
# helpers:
|
41
|
+
# - helpers/**/*.js
|
42
|
+
#
|
43
|
+
helpers:
|
44
|
+
- specHelper.js
|
45
|
+
# spec_files
|
46
|
+
#
|
47
|
+
# Return an array of filepaths relative to spec_dir to include.
|
48
|
+
# Default: ["**/*[sS]pec.js"]
|
49
|
+
#
|
50
|
+
# EXAMPLE:
|
51
|
+
#
|
52
|
+
# spec_files:
|
53
|
+
# - **/*[sS]pec.js
|
54
|
+
#
|
55
|
+
spec_files:
|
56
|
+
- app/shared/**/*.js
|
57
|
+
- '**/*[sS]pec.js'
|
58
|
+
# src_dir
|
59
|
+
#
|
60
|
+
# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
|
61
|
+
# Default: project root
|
62
|
+
#
|
63
|
+
# EXAMPLE:
|
64
|
+
#
|
65
|
+
# src_dir: public
|
66
|
+
#
|
67
|
+
src_dir: .
|
68
|
+
# spec_dir
|
69
|
+
#
|
70
|
+
# Spec directory path. Your spec_files must be returned relative to this path.
|
71
|
+
# Default: spec/javascripts
|
72
|
+
#
|
73
|
+
# EXAMPLE:
|
74
|
+
#
|
75
|
+
# spec_dir: spec/javascripts
|
76
|
+
#
|
77
|
+
spec_dir: spec/unit
|
@@ -0,0 +1,13 @@
|
|
1
|
+
describe("Javascript", function () {
|
2
|
+
it("should know that one equals one", function() {
|
3
|
+
expect(1).toEqual(1);
|
4
|
+
});
|
5
|
+
});
|
6
|
+
|
7
|
+
|
8
|
+
describe("Enyo", function () {
|
9
|
+
it("should be present", function() {
|
10
|
+
var component = new enyo.Component({ name: "testComponent" });
|
11
|
+
expect(component.name).toEqual("testComponent");
|
12
|
+
});
|
13
|
+
});
|
data/lib/eris/version.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
This is the enyo.js fixture
|
@@ -0,0 +1 @@
|
|
1
|
+
var noop = function() {};
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title><%= app_title %></title>
|
5
|
+
<script src="<%= "/usr/palm/frameworks/enyo/0.10/framework/enyo.js" -%>" type="text/javascript" enyo="true"></script>
|
6
|
+
<%= eris_helper_tags %>
|
7
|
+
<%= app_helper_tag %>
|
8
|
+
<% if launch_params %>
|
9
|
+
<script type="text/javascript" launch-params="true">
|
10
|
+
relaunchWithParams('<%= launch_params %>');
|
11
|
+
</script>
|
12
|
+
<% end %>
|
13
|
+
</head>
|
14
|
+
<body>
|
15
|
+
<div id="app-container" class="enyo-fit"></div>
|
16
|
+
<script type="text/javascript">
|
17
|
+
app.go();
|
18
|
+
</script>
|
19
|
+
</body>
|
20
|
+
</html>
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: http://dev.virtualearth.net:80/REST/v1/Routes/Driving?c=en-US&dateTime=14:46:48&distanceUnit=mi&key=Ah2oavKf-raTJYVgMxnxJg9E2E2_53Wb3jz2lD4N415EFSKwFlhlMe9U2dJpMZyJ&output=json&routePathOutput=Points&timeType=Departure&wp.0=731%20Market%20St,%20San%20Francisco,%20ca&wp.1=jkhgkjhgkjhg
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
response: !ruby/struct:VCR::Response
|
9
|
+
status: !ruby/struct:VCR::ResponseStatus
|
10
|
+
code: 404
|
11
|
+
message: Not Found
|
12
|
+
headers:
|
13
|
+
x-powered-by:
|
14
|
+
- ASP.NET
|
15
|
+
x-aspnet-version:
|
16
|
+
- 2.0.50727
|
17
|
+
content-type:
|
18
|
+
- application/json
|
19
|
+
x-bm-srv:
|
20
|
+
- BL2M001310, BL2MSNVM001815, BL2MSNVM001291, BL2MSNVM001266, BL2MSNVM001260, BL2MSNVM001265, BL2MSNVM001279, BL2MSNVM001292, BL2MSNVM001817, BL2MSNVM001297
|
21
|
+
x-ms-bm-ws-info:
|
22
|
+
- "0"
|
23
|
+
server:
|
24
|
+
- Microsoft-IIS/7.5
|
25
|
+
date:
|
26
|
+
- Fri, 24 Jun 2011 22:05:25 GMT
|
27
|
+
cache-control:
|
28
|
+
- no-cache
|
29
|
+
transfer-encoding:
|
30
|
+
- chunked
|
31
|
+
x-bm-traceid:
|
32
|
+
- 6144d092df924727a5f0935528c5cbb2
|
33
|
+
body: "{\"authenticationResultCode\":\"ValidCredentials\",\"brandLogoUri\":\"http:\\/\\/dev.virtualearth.net\\/Branding\\/logo_powered_by.png\",\"copyright\":\"Copyright \xC2\xA9 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.\",\"errorDetails\":[\"One or more locations specified in the waypoint parameter are invalid or require more information.\",\"jkhgkjhgkjhg\"],\"resourceSets\":[],\"statusCode\":404,\"statusDescription\":\"Not Found\",\"traceId\":\"6144d092df924727a5f0935528c5cbb2|BL2M001310|02.00.126.1500|BL2MSNVM001815, BL2MSNVM001291, BL2MSNVM001266, BL2MSNVM001260, BL2MSNVM001265, BL2MSNVM001279, BL2MSNVM001292, BL2MSNVM001817, BL2MSNVM001297\"}"
|
34
|
+
http_version: "1.1"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
---
|
2
|
+
- !ruby/struct:VCR::HTTPInteraction
|
3
|
+
request: !ruby/struct:VCR::Request
|
4
|
+
method: :get
|
5
|
+
uri: http://www.google.com:80/?foo=bar
|
6
|
+
body:
|
7
|
+
headers:
|
8
|
+
response: !ruby/struct:VCR::Response
|
9
|
+
status: !ruby/struct:VCR::ResponseStatus
|
10
|
+
code: 200
|
11
|
+
message: OK
|
12
|
+
headers:
|
13
|
+
expires:
|
14
|
+
- "-1"
|
15
|
+
content-type:
|
16
|
+
- text/html; charset=ISO-8859-1
|
17
|
+
server:
|
18
|
+
- gws
|
19
|
+
x-xss-protection:
|
20
|
+
- 1; mode=block
|
21
|
+
date:
|
22
|
+
- Fri, 24 Jun 2011 22:05:24 GMT
|
23
|
+
set-cookie:
|
24
|
+
- NID=48=QB_x_TK2rdQnD2WpNNp9Vii3PoE5MzWHcuNL6YDU6WoLXAqYGADHE_-m8jDq4kuRRiAWGvj2a3-VHRDzvYD6ZJ-RAtpbyC81QjRbZYsZGPkmFLINBuveh_znlQaQJ-hU; expires=Sat, 24-Dec-2011 22:05:24 GMT; path=/; domain=.google.com; HttpOnly
|
25
|
+
- PREF=ID=f1758e3be9ba3350:FF=0:TM=1308953124:LM=1308953124:S=7QULP01SChxTU6yy; expires=Sun, 23-Jun-2013 22:05:24 GMT; path=/; domain=.google.com
|
26
|
+
cache-control:
|
27
|
+
- private, max-age=0
|
28
|
+
transfer-encoding:
|
29
|
+
- chunked
|
30
|
+
body: |-
|
31
|
+
<!doctype html><html><head><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"><meta name="description" content="Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for."><meta name="robots" content="noodp"><title>Google</title><script>window.google={kEI:"JAoFTomrPMndiALAoLGsDQ",kEXPI:"28504,28936,29822,30316,30348,30760,31091,31111,31127,31193,31267",kCSI:{e:"28504,28936,29822,30316,30348,30760,31091,31111,31127,31193,31267",ei:"JAoFTomrPMndiALAoLGsDQ",expi:"28504,28936,29822,30316,30348,30760,31091,31111,31127,31193,31267"},authuser:0,ml:function(){},kHL:"en",time:function(){return(new Date).getTime()},
|
32
|
+
log:function(c,d,b){var a=new Image,e=google,g=e.lc,f=e.li;a.onerror=(a.onload=(a.onabort=function(){delete g[f]}));g[f]=a;b=b||"/gen_204?atyp=i&ct="+c+"&cad="+d+"&zx="+google.time();a.src=b;e.li=f+1},lc:[],li:0,Toolbelt:{}};
|
33
|
+
window.google.sn="webhp";var i=window.google.timers={};window.google.startTick=function(a,b){i[a]={t:{start:(new Date).getTime()},bfr:!(!b)}};window.google.tick=function(a,b,c){if(!i[a])google.startTick(a);i[a].t[b]=c||(new Date).getTime()};google.startTick("load",true);try{}catch(v){}
|
34
|
+
var _gjwl=location;function _gjuc(){var e=_gjwl.href.indexOf("#");if(e>=0){var a=_gjwl.href.substring(e);if(a.indexOf("&q=")>0||a.indexOf("#q=")>=0){a=a.substring(1);if(a.indexOf("#")==-1){for(var c=0;c<a.length;){var d=c;if(a.charAt(d)=="&")++d;var b=a.indexOf("&",d);if(b==-1)b=a.length;var f=a.substring(d,b);if(f.indexOf("fp=")==0){a=a.substring(0,c)+a.substring(b,a.length);b=c}else if(f=="cad=h")return 0;c=b}_gjwl.href="/search?"+a+"&cad=h";return 1}}}return 0}function _gjp(){!(window._gjwl.hash&&
|
35
|
+
window._gjuc())&&setTimeout(_gjp,500)};
|
36
|
+
window._gjp && _gjp()</script><style id=gstyle>body{margin:0;overflow-y:scroll}#gog{padding:3px 8px 0}td{line-height:.8em}.gac_m td{line-height:17px}form{margin-bottom:20px}body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}em{font-weight:bold;font-style:normal}.lst{height:25px;width:496px}.ds{border-bottom:solid 1px #e7e7e7;border-right:solid 1px #e7e7e7;display:-moz-inline-box;display:inline-block;margin:3px 0 4px;margin-left:4px}input{font-family:inherit}a.gb1,a.gb2,a.gb3,a.gb4{color:#11c !important}#gb{font:13px/27px Arial,sans-serif;height:30px}#gbz,#gbg{position:absolute;white-space:nowrap;top:0;height:30px;z-index:1000}#gbz{left:0;padding-left:4px}#gbg{right:0;padding-right:5px}#gbs{background:#fff;left:0;position:absolute;visibility:hidden;z-index:998}#gbx3,#gbx4{background-color:#fff;background-image:url(//ssl.gstatic.com/gb/images/b_8d5afc09.png);_background-image:url(//ssl.gstatic.com/gb/images/b8_c99e669a.png);background-position:0 -138px;background-repeat:repeat-x;border-bottom:1px solid #f5f5f5;font-size:24px;height:29px;_height:30px;opacity:1;filter:alpha(opacity=100);position:absolute;top:0;width:100%;z-index:990}#gbx3{left:0}#gbx4{right:0}.gbtcb{position:absolute;visibility:hidden}#gbz .gbtcb{right:0}#gbg .gbtcb{left:0}.gbxx{display:none !important}.gbm{position:absolute;z-index:999;top:-999px;visibility:hidden;text-align:left;border:1px solid #bebebe;background:#fff;-moz-box-shadow:-1px 1px 1px #ccc;-webkit-box-shadow:0 1px 5px #ccc;box-shadow:0 1px 5px #ccc}.gbrtl .gbm{-moz-box-shadow:1px 1px 1px #ccc}.gbto .gbm{visibility:visible;top:29px !important}#gbs{top:29px !important}#gbz .gbm{left:0}#gbg .gbm{right:0}.gbmc{background:#fff;position:relative;z-index:2;zoom:1}.gbxms{background-color:#ccc;display:block;position:absolute;z-index:1;top:-1px;left:-2px;right:-2px;bottom:-2px;opacity:.4;-moz-border-radius:3px;filter:progid:DXImageTransform.Microsoft.Blur(pixelradius=5);*opacity:1;*top:-2px;*left:-5px;*right:5px;*bottom:4px;-ms-filter:"progid:DXImageTransform.Microsoft.Blur(pixelradius=5)";opacity:1\0/;top:-4px\0/;left:-6px\0/;right:5px\0/;bottom:4px\0/}.gbma{position:relative;top:-1px;border-style:solid dashed dashed;border-color:transparent;border-top-color:#c0c0c0;display:-moz-inline-box;display:inline-block;font-size:0;height:0;line-height:0;width:0;border-width:3px 3px 0;padding-top:1px;left:4px}#gbztms1,#gbi4m1,#gbi4s,#gbi4t{zoom:1}.gbtc,.gbmc,.gbmcc{display:block;list-style:none;margin:0;padding:0}.gbt{position:relative;display:-moz-inline-box;display:inline-block;line-height:27px;padding:0;vertical-align:top}.gbt{*display:inline}.gbto{box-shadow:0 1px 5px #ccc;-moz-box-shadow:0 1px 5px #ccc;-webkit-box-shadow:0 1px 5px #ccc}.gbzt,.gbgt{cursor:pointer;display:block;text-decoration:none !important}.gbts{border-left:1px solid transparent;border-right:1px solid transparent;display:block;*display:inline-block;padding:0 5px;position:relative;z-index:1000}.gbts{*display:inline}.gbto .gbts{background:#fff;border-color:#bebebe;color:#36c;padding-bottom:1px;padding-top:2px}.gbz0l .gbts{color:#363636;font-weight:bold}.gbtsa{padding-right:9px}#gbz .gbzt,#gbz .gbgt,#gbg .gbgt{color:#36c!important}.gbtb2{display:block;border-top:2px solid transparent}.gbto .gbzt .gbtb2,.gbto .gbgt .gbtb2{border-top-width:0}.gbtb .gbts{background:url(//ssl.gstatic.com/gb/images/b_8d5afc09.png);_background:url(//ssl.gstatic.com/gb/images/b8_c99e669a.png);background-position:0 -22px;border:0;font-size:0;padding:29px 0 0;*padding:27px 0 0;width:1px}.gbzt-hvr,.gbzt:focus,.gbgt-hvr,.gbgt:focus{background-color:transparent;background-image:url(//ssl.gstatic.com/gb/images/b_8d5afc09.png);_background-image:url(//ssl.gstatic.com/gb/images/b8_c99e669a.png);background-position:0 -102px;background-repeat:repeat-x;outline:none;text-decoration:none !important}.gbpdjs .gbto .gbm{min-width:99%}.gbz0l .gbtb2{border-top-color:#1a54e1!important}#gbi4s,#gbi4s1{font-weight:bold}#gbi4i,#gbi4id{left:6px;border:0;height:24px;position:absolute;top:1px;width:24px}.gbi4p{display:inline-block;width:30px}.gbi4p{*display:inline}.gbto #gbi4i,.gbto #gbi4id{visibility:hidden}#gbi4id,#gbmpid{background:url(//ssl.gstatic.com/gb/images/b_8d5afc09.png);_background:url(//ssl.gstatic.com/gb/images/b8_c99e669a.png)}#gbi4id{background-position:-29px -54px}#gbmpid{background-position:-58px 0px}#gbmpi,#gbmpid{border:none;display:inline-block;margin:10px;height:48px;width:48px}#gbmpi,#gbmpid{*display:inline}#gbg5{font-size:0}#gbgs5{padding:5px !important}.gbto #gbgs5{padding:7px 5px 6px !important}#gbi5{background:url(//ssl.gstatic.com/gb/images/b_8d5afc09.png);_background:url(//ssl.gstatic.com/gb/images/b8_c99e669a.png);background-position:-6px -22px;display:block;font-size:0;height:17px;width:16px}.gbto #gbi5{background-position:-6px -22px}#gbgf .gbmt,.gbn .gbmt,.gbn .gbmt:visited{color:#dd8e27 !important}.gbf .gbmt,.gbf .gbmt:visited{color:#900 !important}.gbmt,.gbml1,.gbmt:visited,.gbml1:visited{color:#36c !important;display:block;text-decoration:none}.gbml1{display:inline-block}.gbml1{*display:inline}.gbml1-hvr{text-decoration:underline !important}.gbmt{padding-left:6px;padding-right:12px}.gbmt-hvr,.gbmt:focus{background:#eff3fb;cursor:pointer;outline:0 solid black;text-decoration:none !important}.gbm0l,.gbm0l:visited{color:#000 !important;font-weight:bold}.gbmh{border-top:1px solid #e5e5e5;font-size:0}.gbmtc{padding:0;margin:0;line-height:27px}.GBMCC:last-child:after,#GBMPAL:last-child:after{content:'\0A\0A';white-space:pre;position:absolute}#gbd4 .gbpc,#gbd4 .gbmtc{line-height:17px}#gbd4 .gbmt{border-top:1px solid #e5e5e5;padding:10px}#gbd4 .gbpgs .gbmtc{line-height:27px}#gbd4 .gbpgs .gbmt{padding:0 10px}#gbmple .gbmt,#gbmpas .gbmt{font-size:15px}#gbd4 .gbpc{display:inline-block;margin:10px;vertical-align:top}#gbd4 .gbpc{*display:inline}.gbpc .gbmtc{margin-top:10px}.gbpc .gbps{color:#000;font-weight:bold}.gbpc .gbps2{font-size:13px}.gbpc .gbpd{color:#000}.gbpd .gbmt,.gbmpmtd .gbmt{color:#666 !important}.gbmpme,.gbps2{color:#666;display:block;font-size:11px}.gbp0 .gbps2,.gbmpmta .gbmpme{font-weight:bold}#gbmpp{display:none}.gbpmc{background:#edfeea}#gbpm{*border-collapse:collapse;border-spacing:0;margin:0;white-space:normal}#gbpm .gbmt{border-top:none;color:#666 !important;font:11px Arial,sans-serif}.gbpms2{font-weight:bold;white-space:nowrap}#gbmpal{*border-collapse:collapse;border-spacing:0;margin:0;white-space:nowrap}.gbmpala,.gbmpalb{font:13px Arial,sans-serif;padding:5px 10px}.gbmpala{text-align:left}.gbmpalb{text-align:right}#gbmpsb{margin:0 10px}.gbp0 .gbps,.gbmpmta .gbmpmn{color:#000;display:inline-block;font-weight:bold;padding-right:34px;position:relative}.gbp0 .gbps,.gbmpmta .gbmpmn{*display:inline}.gbmpmtc,.gbp0i{background:url(//ssl.gstatic.com/gb/images/b_8d5afc09.png);_background:url(//ssl.gstatic.com/gb/images/b8_c99e669a.png);background-position:0 -54px;position:absolute;height:21px;width:24px;right:0;top:-3px}body{background:#fff;color:black}input{-moz-box-sizing:content-box}a{color:#11c;text-decoration:none}a:hover,a:active{text-decoration:underline}.fl a{color:#36c}a:visited{color:#551a8b}a.gb1,a.gb4{text-decoration:underline}a.gb3:hover{text-decoration:none}#ghead a.gb2:hover{color:#fff!important}.sblc{padding-top:5px}.sblc a{display:block;margin:2px 0;margin-left:13px;font-size:11px;}.lsbb{background:#eee;border:solid 1px;border-color:#ccc #999 #999 #ccc;height:30px;display:block}.ftl,#fll a{display:inline-block;margin:0 12px}.lsb{background:url(/images/srpr/nav_logo73.png) bottom;border:none;color:#000;cursor:pointer;height:30px;margin:0;outline:0;font:15px arial,sans-serif;vertical-align:top}.lsb:active{background:#ccc}.lst:focus{outline:none}#addlang a{padding:0 3px}.gac_v div{display:none}.gac_v .gac_v2,.gac_bt{display:block!important}</style><script>google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};(function(){try{var e=true,k=false;var m=window.gbar=window.gbar||{};function _tvn(a,b){var c=parseInt(a,10);return isNaN(c)?b:c}function _tvf(a,b){var c=parseFloat(a);return isNaN(c)?b:c}function _tvb(a,b){return a=="true"?e:a=="false"?k:b}function _tvv(a){return!!a}function n(a,b,c){(c||m)[a]=b}m.bv={n:_tvn("2",0),r:"r_gc.r_pw.",m:_tvn("1",1)};var aa=function(){return m.bv.m==1};n("sb",aa);
|
37
|
+
var o={},ba={},p=[],ea=function(a,b){p.push([a,b])},fa=function(a,b){o[a]=b},ga=function(a){return a in o},q={},r=function(a,b){q[a]||(q[a]=[]);q[a].push(b)},s=function(a){r("m",a)},u=function(a){var b=document.createElement("script");b.src=a;(document.getElementById("xjsc")||document.body).appendChild(b)},w=function(a){for(var b=0,c;c=p[b];++b)if(c[0]==a)break;if(c&&!c[1].l&&!c[1].s){c[1].s=e;v(2,a);u(c[1].url)}},x=function(a){r("gc",a)},y=null,ha=function(a){y=a},v=function(a,b,c){if(y){a={t:a,
|
38
|
+
b:b};if(c)for(var d in c)a[d]=c[d];try{y(a)}catch(f){}}};n("mdc",o);n("mdi",ba);n("bnc",p);n("qGC",x);n("qd",q);n("lb",w);n("mcf",fa);n("bcf",ea);n("aq",r);n("mdd","");n("has",ga);n("trh",ha);n("tev",v);var z=function(){},A=function(){},D=function(a){var b=new Image,c=B;b.onerror=b.onload=b.onabort=function(){try{delete C[c]}catch(d){}};C[c]=b;b.src=a;B=c+1},C=[],B=0;n("logger",{il:A,ml:z});var E=window.gbar.logger,F=_tvf("0.001",1.0E-4),G=0;
|
39
|
+
function _mlToken(a,b){try{if(G<1){G++;var c,d=a,f=b||{},g=encodeURIComponent,h=["//www.google.com/gen_204?atyp=i&zx=",(new Date).getTime(),"&jexpid=",g("30316"),"&srcpg=",g("prop=1"),"&jsr=",Math.round(1/F),"&ogv=",g("1308875615.1308938441")];if(f._sn)f._sn="og."+f._sn;for(var l in f){h.push("&");h.push(g(l));h.push("=");h.push(g(f[l]))}h.push("&emsg=");h.push(g(d.name+":"+d.message));var i=h.join("");if(H(i))i=i.substr(0,2E3);c=i;var j=window.gbar.logger._aem(a,
|
40
|
+
c);D(j)}}catch(t){}}var H=function(a){return a.length>=2E3},ia=function(a,b){return b};function I(a){z=a;n("_itl",H,E);n("_aem",ia,E);n("ml",z,E);a={};o.er=a}if(_tvv(""))I(function(a){throw a;});else _tvv("1")&&Math.random()<F&&I(_mlToken);var ja=["gb_71","gb_155"];function ka(a){try{var b=(document.forms[0].q||"").value;if(b)a.href=a.href.replace(/([?&])q=[^&]*|$/,function(d,f){return(f||"&")+"q="+encodeURIComponent(b)})}catch(c){z(c)}}
|
41
|
+
var L=function(){for(var a=[],b=0,c;c=ja[b];++b)(c=document.getElementById(c))&&a.push(c);return a},la=function(){var a=L();return a.length>0?a[0]:null},ma=function(){return document.getElementById("gb_70")},M={},N={},O={},P=undefined,qa=function(a,b){try{var c=document.getElementById("gb");Q(c,"gbpdjs");R();S(document.body)&&Q(c,"gbrtl");if(b&&b.getAttribute){var d=b.getAttribute("aria-owns");if(d.length){var f=document.getElementById(d);if(f){var g=b.parentNode;if(P==d){P=undefined;T(g,"gbto")}else{if(P){var h=
|
42
|
+
document.getElementById(P);if(h&&h.getAttribute){var l=h.getAttribute("aria-owner");if(l.length){var i=document.getElementById(l);i&&i.parentNode&&T(i.parentNode,"gbto")}}}na(f)&&oa(f);P=d;Q(g,"gbto")}}}}s(function(){m.tg(a,b,e)});pa(a)}catch(j){z(j)}},ra=function(a){s(function(){m.close(a)})},Q=function(a,b){var c=a.className;U(a,b)||(a.className+=(c!=""?" ":"")+b)},T=function(a,b){var c=a.className,d=RegExp("\\s?\\b"+b+"\\b");if(c&&c.match(d))a.className=c.replace(d,"")},U=function(a,b){var c=RegExp("\\b"+
|
43
|
+
b+"\\b"),d=a.className;return!!(d&&d.match(c))},S=function(a){var b,c="direction",d=document.defaultView;if(d&&d.getComputedStyle){if(a=d.getComputedStyle(a,""))b=a[c]}else b=a.currentStyle?a.currentStyle[c]:a.style[c];return b=="rtl"},sa=function(a,b,c){if(a)try{var d=document.getElementById("gbd5").firstChild,f=d.firstChild,g=document.createElement("li");g.className=b+" gbmtc";g.id=c;a.className="gbmt";g.appendChild(a);if(f.hasChildNodes()){c=[["gbkc"],["gbf","gbe","gbn"],["gbkp"]];d=0;for(var h=
|
44
|
+
f.childNodes.length,l=k,i=-1,j=0,t;t=c[j];j++){for(var ca=0,J;J=t[ca];ca++){for(;d<h&&U(f.childNodes[d],J);)d++;if(J==b){f.insertBefore(g,f.childNodes[d]);l=e;break}}if(l){if(d+1<f.childNodes.length&&U(f.childNodes[d+1],"gbkp"))i=d+1;break}if(d>0&&d+1<h)d++;else if(d>0&&d==h-1)i=d}if(i>=0){var K=document.createElement("li"),da=document.createElement("div");K.className="gbmtc";da.className="gbmt gbmh";K.appendChild(da);f.insertBefore(K,f.childNodes[i])}m.addHover&&m.addHover(a)}else f.appendChild(g)}catch(ya){z(ya)}},
|
45
|
+
ta=function(a,b,c){sa(a,b,c)},ua=function(a,b){sa(a,"gbe",b)},va=function(){s(function(){m.pcm&&m.pcm()})},wa=function(a,b,c,d,f,g,h,l){s(function(){m.paa&&m.paa(a,b,c,d,f,g,h,l)})},xa=function(a,b){M[a]||(M[a]=[]);M[a].push(b)},za=function(a,b){N[a]||(N[a]=[]);N[a].push(b)},Aa=function(a,b){O[a]||(O[a]=[]);O[a].push(b)},pa=function(a){a.preventDefault&&a.preventDefault();a.returnValue=k;a.cancelBubble=e},V=null,oa=function(a,b){R();if(a){W(a,"Opening…");X(a,e);var c=typeof b!=
|
46
|
+
"undefined"?b:1E4;V=window.setTimeout(Ba,c)}},Ca=function(a){R();if(a){X(a,k);W(a,"")}},Ba=function(a){R();if(a=a||document.getElementById(P)){W(a,"This service is currently unavailable.%1$1Please try again later.","%1$1");X(a,e)}},W=function(a,b,c){if(a&&b){var d=na(a);if(d){if(c){d.innerHTML="";b=b.split(c);c=0;for(var f;f=b[c];c++){var g=document.createElement("div");g.innerHTML=f;d.appendChild(g)}}else d.innerHTML=b;X(a,e)}}},X=function(a,b){var c=b!==undefined?b:e;c?Q(a,"gbmsgo"):T(a,"gbmsgo")},na=function(a){for(var b=0,c;c=a.childNodes[b];b++)if(U(c,
|
47
|
+
"gbmsg"))return c},R=function(){V&&window.clearTimeout(V)};n("so",la);n("sos",L);n("si",ma);n("tg",qa);n("close",ra);n("addLink",ta);n("addExtraLink",ua);n("pcm",va);n("paa",wa);n("ddld",oa);n("ddrd",Ca);n("dderr",Ba);n("ca",Q);n("cr",T);n("cc",U);n("rtl",S);n("bh",M);n("abh",xa);n("dh",N);n("adh",za);n("ch",O);n("ach",Aa);n("qs",ka);var Da={};o.base=Da;p.push(["m",{url:"//ssl.gstatic.com/gb/js/sem_d9a018401fc6c1b310c6c3d97866e254.js"}]);
|
48
|
+
var Y=_tvn("1",0),Ea=function(a){var b,c;if((b=a.id)&&(c=/^gb_(\d+)/.exec(b)))if(c[1]==Y)return;m.qs(a)},Fa=/\bgbmt\b/,Ga=function(a){if(Fa.test(a.className))return"gbm0l";return"gbz0l"},Ha=function(a){try{var b=document.getElementById("gb_"+Y),c=document.getElementById("gb_"+a);b&&T(b,Ga(b));c&&Q(c,Ga(c))}catch(d){z(d)}Y=a};n("qsj",Ea);n("slp",Ha);
|
49
|
+
if(_tvv("1")){var Ia=_tvb("false",k);p.push(["gc",{auto:Ia,url:"https://ssl.gstatic.com/gb/js/gcm_db5d28cdf8a6967cf1a8c2a26ccf7542.js"}]);var Ja={version:"gcm_db5d28cdf8a6967cf1a8c2a26ccf7542.js",index:"",lang:"en"};o.gc=Ja;var Z=function(a){if(window.googleapis)a&&a();else{a&&x(a);w("gc")}};n("lGC",Z);_tvv("1")&&n("lPWF",Z)}window.__PVT="";var Ka=_tvf("0.001",1.0E-4),La=_tvf("0.01",1);
|
50
|
+
function Ma(a,b){var c=Ka,d;d=a<=14?a==7||a==8||a==12?k:e:k;if(d)c=La;if(_tvv("1")&&Math.random()<=c){d=encodeURIComponent;c=["//www.google.com/gen_204?atyp=i&zx=",(new Date).getTime(),"&oge=",a,"&ogex=",d("30316"),"&ogp=",d("1"),"&ogsr=",Math.round(1/c),"&ogv=",d("1308875615.1308938441")];if(b){if("ogw"in b){c.push("&ogw="+b.ogw);delete b.ogw}var f,g=b,h=[];for(f in g){h.length!=0&&h.push(",");h.push(f);h.push(".");h.push(g[f])}f=h.join("");
|
51
|
+
if(f!=""){c.push("&ogad=");c.push(d(f))}}D(c.join(""))}}A=Ma;n("il",A,E);var Na={};o.il=Na;var Oa=function(){m.prm&&m.prm()};xa("gbd4",Oa);if(_tvb("false",e)){var Pa={g:_tvv(""),d:_tvv(""),e:"",m:"",p:"//ssl.gstatic.com/gb/images/avatar_b96.png",xp:_tvv("1"),mg:"%1$s (delegated)",md:"%1$s (default)"};o.prf=Pa}
|
52
|
+
if(_tvv("1")&&_tvv("1")){var $=function(a){Z(function(){r("pw",a);w("pw")})};n("lPW",$);p.push(["pw",{url:"//ssl.gstatic.com/gb/js/pwm_377e54339fe6909b01c5d023b5297ebb.js"}]);var Qa=[],Ra=function(a){Qa[0]=a},Sa={signed:Qa,elog:z,base:"https://profiles.google.com/u/",loadTime:(new Date).getTime()};o.pw=Sa;var Ta=function(a,b){for(var c=b.split("."),d=function(){var l=arguments;a(function(){for(var i=m,j=0,t=c.length-1;j<t;++j)i=i[c[j]];i[c[j]].apply(i,l)})},f=m,g=0,h=c.length-1;g<h;++g)f=f[c[g]]=f[c[g]]||
|
53
|
+
{};return f[c[g]]=d};Ta($,"pw.clk");Ta($,"pw.hvr");n("su",Ra,m.pw)}
|
54
|
+
function Ua(){function a(){for(var j;j=g[h++];)if(j[0]=="m"||j[1].auto)break;if(j){v(2,j[0]);u(j[1].url)}h<g.length&&setTimeout(a,0)}function b(){f-- >0?setTimeout(b,0):a()}var c=_tvb("true",e),d=_tvb("false",k),f=3,g=p,h=0,l=window.gbarOnReady;if(l)try{l()}catch(i){z(i)}if(d)n("ldb",a);else if(c)window.addEventListener?window.addEventListener("load",b,k):window.attachEvent("onload",b);else b()}n("rdl",Ua);}catch(e){window.gbar&&gbar.logger&&gbar.logger.ml(e);}})();
|
55
|
+
(function(){try{window.gbar.rdl();}catch(e){window.gbar&&gbar.logger&&gbar.logger.ml(e);}})();
|
56
|
+
</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload="document.f.q.focus();if(document.images)new Image().src='/images/srpr/nav_logo73.png'" ><textarea id=csi style=display:none></textarea><div id=mngb><div id=gb><div id=gbw><div id=gbz><span class=gbtcb></span><ol class=gbtc><li class=gbt><a class="gbzt gbz0l gbp1" id=gb_1 onclick="gbar.qsj(this);gbar.logger.il(1,{t:1})" href="http://www.google.com/webhp?hl=en&tab=ww"><span class=gbtb2></span><span class=gbts>Web</span></a></li><li class=gbt><a class=gbzt id=gb_2 onclick="gbar.qsj(this);gbar.logger.il(1,{t:2})" href="http://www.google.com/imghp?hl=en&tab=wi"><span class=gbtb2></span><span class=gbts>Images</span></a></li><li class=gbt><a class=gbzt id=gb_12 onclick="gbar.qsj(this);gbar.logger.il(1,{t:12})" href="http://video.google.com/?hl=en&tab=wv"><span class=gbtb2></span><span class=gbts>Videos</span></a></li><li class=gbt><a class=gbzt id=gb_8 onclick="gbar.qsj(this);gbar.logger.il(1,{t:8})" href="http://maps.google.com/maps?hl=en&tab=wl"><span class=gbtb2></span><span class=gbts>Maps</span></a></li><li class=gbt><a class=gbzt id=gb_5 onclick="gbar.qsj(this);gbar.logger.il(1,{t:5})" href="http://news.google.com/nwshp?hl=en&tab=wn"><span class=gbtb2></span><span class=gbts>News</span></a></li><li class=gbt><a class=gbzt id=gb_6 onclick="gbar.qsj(this);gbar.logger.il(1,{t:6})" href="http://www.google.com/prdhp?hl=en&tab=wf"><span class=gbtb2></span><span class=gbts>Shopping</span></a></li><li class=gbt><a class=gbzt onclick="gbar.logger.il(1,{t:23})" href="http://mail.google.com/mail/?hl=en&tab=wm"><span class=gbtb2></span><span class=gbts>Gmail</span></a></li><li class=gbt><a id=gbztm class=gbgt href="http://www.google.com/intl/en/options/" onclick="gbar.tg(event,this)" aria-haspopup=true aria-owns=gbd><span class=gbtb2></span><span id=gbztms class="gbts gbtsa"><span id=gbztms1>more</span><span class=gbma></span></span></a><div class=gbm id=gbd aria-owner=gbztm><div class=gbmc><ol class=gbmcc><li class=gbmtc><a class=gbmt id=gb_51 onclick="gbar.qsj(this);gbar.logger.il(1,{t:51})" href="http://translate.google.com/?hl=en&tab=wT">Translate</a></li><li class=gbmtc><a class=gbmt id=gb_10 onclick="gbar.qsj(this);gbar.logger.il(1,{t:10})" href="http://books.google.com/bkshp?hl=en&tab=wp">Books</a></li><li class=gbmtc><a class=gbmt id=gb_27 onclick="gbar.qsj(this);gbar.logger.il(1,{t:27})" href="http://www.google.com/finance?hl=en&tab=we">Finance</a></li><li class=gbmtc><a class=gbmt id=gb_9 onclick="gbar.qsj(this);gbar.logger.il(1,{t:9})" href="http://scholar.google.com/schhp?hl=en&tab=ws">Scholar</a></li><li class=gbmtc><a class=gbmt id=gb_13 onclick="gbar.qsj(this);gbar.logger.il(1,{t:13})" href="http://blogsearch.google.com/?hl=en&tab=wb">Blogs</a></li><li class=gbmtc><a class=gbmt id=gb_92 onclick="gbar.qsj(this);gbar.logger.il(1,{t:92})" href="http://www.google.com/realtime?hl=en&tab=wY">Realtime</a></li><li class=gbmtc><div class="gbmt gbmh"></div></li><li class=gbmtc><a class=gbmt id=gb_36 onclick="gbar.qsj(this);gbar.logger.il(1,{t:36})" href="http://www.youtube.com/?hl=en&tab=w1">YouTube</a></li><li class=gbmtc><a class=gbmt id=gb_24 onclick="gbar.qsj(this);gbar.logger.il(1,{t:24})" href="http://www.google.com/calendar?hl=en&tab=wc">Calendar</a></li><li class=gbmtc><a class=gbmt id=gb_31 onclick="gbar.qsj(this);gbar.logger.il(1,{t:31})" href="http://picasaweb.google.com/home?hl=en&tab=wq">Photos</a></li><li class=gbmtc><a class=gbmt onclick="gbar.logger.il(1,{t:25})" href="http://docs.google.com/?hl=en&tab=wo">Documents</a></li><li class=gbmtc><a class=gbmt onclick="gbar.logger.il(1,{t:32})" href="http://www.google.com/reader/?hl=en&tab=wy">Reader</a></li><li class=gbmtc><a class=gbmt onclick="gbar.logger.il(1,{t:38})" href="http://sites.google.com/?hl=en&tab=w3">Sites</a></li><li class=gbmtc><a class=gbmt id=gb_3 onclick="gbar.qsj(this);gbar.logger.il(1,{t:3})" href="http://groups.google.com/grphp?hl=en&tab=wg">Groups</a></li><li class=gbmtc><div class="gbmt gbmh"></div></li><li class=gbmtc><a class=gbmt onclick="gbar.logger.il(1,{t:66})" href="http://www.google.com/intl/en/options/">even more »</a></li></ol></div></div></li></ol></div><div id=gbg><h2 class=gbxx>Account Options</h2><span class=gbtcb></span><ol class=gbtc><li class=gbt><a class=gbgt id=gb_70 href="https://www.google.com/accounts/ServiceLogin?hl=en&continue=http://www.google.com/%3Ffoo%3Dbar" onclick="gbar.logger.il(9,{l:'i'})"><span class=gbtb2></span><span id=gbgs4 class=gbts><span id=gbi4s1>Sign in</span></span></a></li><li class="gbt gbtb"><span class=gbts></span></li><li class=gbt><a class=gbgt id=gbg5 href="http://www.google.com/preferences?hl=en" title="Options" onclick="gbar.tg(event,this)" aria-haspopup=true aria-owns=gbd5><span class=gbtb2></span><span id=gbgs5 class=gbts><span id=gbi5></span></span></a><div class=gbm id=gbd5 aria-owner=gbg5><div class=gbmc><ol class=gbmcc><li class="gbkc gbmtc"><a class=gbmt href="/preferences?hl=en">Search settings</a></li><li class=gbmtc><div class="gbmt gbmh"></div></li><li class="gbe gbmtc"><a class=gbmt onclick="gbar.logger.il(11,{t:78,ty:'e'})" href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Ffoo%3Dbar%26hl%3Den%26source%3Diglk&usg=AFQjCNHivu3-vhKsRbuEF6CC6-ystRNaxg">iGoogle</a></li><li class=gbmtc><div class="gbmt gbmh"></div></li></ol></div></div></li></ol></div></div><div id=gbx3></div><div id=gbx4></div></div></div><iframe name=wgjf style=display:none></iframe><center><br clear=all id=lgpd><div id=lga><img alt="Google" height=95 src="/intl/en_ALL/images/srpr/logo1w.png" width=275 id=hplogo style="padding:28px 0 14px" onload="window.lol&&lol()"><br><br></div><form action="/search" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%> </td><td align=center nowrap><input name=hl type=hidden value=en><input name=source type=hidden value=hp><input type=hidden name=ie value="ISO-8859-1"><div class=ds style="height:32px;margin:4px 0"><input autocomplete=off maxlength=2048 name=q class="lst" title="Google Search" value="" size=57 style="background:#fff;border:1px solid #ccc;border-bottom-color:#999;border-right-color:#999;color:#000;font:18px arial,sans-serif bold;margin:0;padding:5px 8px 0 6px;vertical-align:top"></div><br style="line-height:0"><span class=ds ><span class=lsbb><input name=btnG type=submit value="Google Search" class=lsb></span></span><span class=ds><span class=lsbb><input name=btnI type=submit class=lsb value="I'm Feeling Lucky"></span></span></td><td nowrap width=25% align=left class="fl sblc"><a href="/advanced_search?hl=en">Advanced search</a><a href="/language_tools?hl=en">Language tools</a></td></tr></table></form><div style="font-size:83%;min-height:3.5em"><br></div><div id=res></div><span id=footer><center id=fctr><div style="font-size:10pt"><div id=fll style="margin:19px auto 19px auto;text-align:center"><a href="/intl/en/ads/">Advertising Programs</a><a href="/services/">Business Solutions</a><a href="/intl/en/about.html">About Google</a></div></div><p style="color:#767676;font-size:8pt">© 2011 - <a href="/intl/en/privacy.html">Privacy</a></p></center></span> <div id=xjsd></div><div id=xjsi><script>if(google.y)google.y.first=[];google.dlj=function(b){window.setTimeout(function(){var a=document.createElement("script");a.src=b;document.getElementById("xjsd").appendChild(a)},0)};
|
57
|
+
if(google.y)google.y.first=[];if(!google.xjs){google.dstr=[];google.rein=[];if(google.timers&&google.timers.load.t){google.timers.load.t.xjsls=new Date().getTime();}google.dlj('/extern_js/f/CgJlbhICdXMgACswRTgALCswWjgALCswDjgALCswFzgALCswPDgALCswUTgALCswCjgBQC8sKzAWOAAsKzAZOAAsKzAlOAAsKzA1OAAsKzBAOAAsKzBBOAAsKzBNOAAsKzBOOAAsKzBUOAAsKzBjOAAsKzBpOAAsKzAYOAAsKzAmOAAsgAJJkAJC/aNnFs6TAbKw.js');google.xjs=1}google.neegg=1;google.mc=[];google.mc=google.mc.concat([[69,{}],[14,{}],[60,{}],[81,{}],[78,{}],[25,{"m":{"bks":true,"blg":true,"dsc":true,"evn":true,"frm":true,"isch":true,"klg":true,"mbl":true,"nws":true,"plcs":true,"ppl":true,"prc":true,"pts":true,"rcp":true,"shop":true,"vid":true},"t":null}],[64,{"hr":"1 hour ago","hrs":"1 hours ago","jsecs":"seconds ago","min":"1 minute ago","mins":"1 minutes ago","secs":"1 seconds ago"}],[105,{}],[22,{"m_errors":{"32":"Sorry, no more results to show.","default":"\u003Cfont color=red\u003EError:\u003C/font\u003E The server could not complete your request. Try again in 30 seconds."},"m_tip":"Click for more information"}],[77,{}],[84,{}],[99,{}],[24,{}],[38,{}]]);google.y.first.push(function(){try{var form=document.f||document.f||document.gs;google.ac.i(form,form.q,'','','',{l:1,o:1,sw:1});}catch(e){google.ml(e,false,{'cause':'defer'});}if(google.med){google.med('init');google.initHistory();google.med('history');}google.History&&google.History.initialize('/?foo\x3dbar')});if(google.j&&google.j.en&&google.j.xi){window.setTimeout(google.j.xi,0);}</script></div><script>(function(){var a,b=window.location.href.match(/\/webhp\?[^#]*tune=[^#]*/);if(a=b&&b.length>0?"http://www.google.com/logos/2011/lespaul.html#"+b[0].substr(7):null)google.nav&&google.nav.go?google.nav.go(a):window.location.href=a;})();</script><script>(function(){
|
58
|
+
var b,d,e,f;function g(a,c){if(a.removeEventListener){a.removeEventListener("load",c,false);a.removeEventListener("error",c,false)}else{a.detachEvent("onload",c);a.detachEvent("onerror",c)}}function h(a){f=(new Date).getTime();++d;a=a||window.event;var c=a.target||a.srcElement;g(c,h)}var i=document.getElementsByTagName("img");b=i.length;d=0;for(var j=0,k;j<b;++j){k=i[j];if(k.complete||typeof k.src!="string"||!k.src)++d;else if(k.addEventListener){k.addEventListener("load",h,false);k.addEventListener("error",
|
59
|
+
h,false)}else{k.attachEvent("onload",h);k.attachEvent("onerror",h)}}e=b-d;function l(){if(!google.timers.load.t)return;google.timers.load.t.ol=(new Date).getTime();google.timers.load.t.iml=f;google.kCSI.imc=d;google.kCSI.imn=b;google.kCSI.imp=e;google.timers.load.t.xjs&&google.report&&google.report(google.timers.load,google.kCSI)}if(window.addEventListener)window.addEventListener("load",l,false);else if(window.attachEvent)window.attachEvent("onload",l);google.timers.load.t.prt=(f=(new Date).getTime());
|
60
|
+
})();
|
61
|
+
</script>
|
62
|
+
http_version: "1.1"
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Eris Config" do
|
4
|
+
before do
|
5
|
+
@app_root= File.join(File.dirname(__FILE__), '..', '..', '..', 'fixtures', 'sample_app')
|
6
|
+
@config_path = File.join(@app_root, 'eris_config.json')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should be able to read a config' do
|
10
|
+
config = ErisConfig.new(:config_path => @config_path, :app_root => @app_root)
|
11
|
+
config.enyo_root.should == File.join(@app_root, '../')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not append the app_root path if an absolute path is given" do
|
15
|
+
File.stub!(:read).and_return('{"enyoRoot": "/foo/bar" }')
|
16
|
+
config = ErisConfig.new(:config_path => @config_path, :app_root => @app_root)
|
17
|
+
config.enyo_root.should == '/foo/bar'
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not append the app_root path if the path is absolute and contains .." do
|
21
|
+
File.stub!(:read).and_return('{"enyoRoot": "/foo/bar/../baz" }')
|
22
|
+
config = ErisConfig.new(:config_path => @config_path, :app_root => @app_root)
|
23
|
+
config.enyo_root.should == '/foo/bar/../baz'
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Eris::LunaRequest do
|
4
|
+
it "should populate the service correctly" do
|
5
|
+
request = Eris::LunaRequest.new({ "url" => "com.palm.db", "body" => ["foo"]})
|
6
|
+
|
7
|
+
request.url.should match(/-i com\.palm\.db/)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "param escaping" do
|
11
|
+
it "should escape spaces properly" do
|
12
|
+
request = Eris::LunaRequest.new({ "url" => "com.palm.db", "body" => ["foo bar"]})
|
13
|
+
request.params.should == "[\"foo\\ bar\"]"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should escape single quotes properlyish?" do
|
17
|
+
request = Eris::LunaRequest.new({ "url" => "com.palm.db", "body" => ["foo'bar"]})
|
18
|
+
JSON.parse(`echo '#{request.params}'`).should == ["foo'bar"]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should escape new lines" do
|
22
|
+
request = Eris::LunaRequest.new({ "url" => "com.palm.db", "body" => ['f\noo']})
|
23
|
+
JSON.parse(`echo '#{request.params}'`).should == ['f\noo']
|
24
|
+
# request.params.should == %{["foo\\nbar"]}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Eris::ProxiedRequest do
|
4
|
+
|
5
|
+
let(:request) do
|
6
|
+
Eris::ProxiedRequest.new({ "url" => "http://api.example.com", "body" => { "foo" => "bar", "baz" => "quux corge"}})
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
it "should use the correct URL" do
|
11
|
+
request.url.should match /http:\/\/api\.example\.com/
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should turn the params into query params, including escaping" do
|
15
|
+
request.url.should match /foo=bar/
|
16
|
+
request.url.should match /baz=quux%20corge/
|
17
|
+
request.url.should match /\?.*=.*&.*=.*/
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
=begin
|
4
|
+
x * serve all files in a directory
|
5
|
+
x * map / to /index.html
|
6
|
+
* inject JavaScript and/or script tags into index.html ONLY
|
7
|
+
* map /luna to novacom
|
8
|
+
* map /xhr to curl
|
9
|
+
=end
|
10
|
+
|
11
|
+
|
12
|
+
describe "Eris Server" do
|
13
|
+
include Rack::Test::Methods
|
14
|
+
|
15
|
+
let(:app_dir) do
|
16
|
+
File.join(File.dirname(__FILE__), '..', '..', '..', 'fixtures', 'sample_app')
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:app) do
|
20
|
+
@our_app = Eris::Server.new(app_dir)
|
21
|
+
@our_app
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can return any static filepath" do
|
25
|
+
get '/app/models/foo.js'
|
26
|
+
last_response.should be_ok
|
27
|
+
last_response.body.should match(/function/)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "can serve index.html when asking for '/'" do
|
31
|
+
get '/'
|
32
|
+
last_response.should be_ok
|
33
|
+
last_response.body.should match(/^<html>/)
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when serving an Enyo app" do
|
37
|
+
|
38
|
+
before :each do
|
39
|
+
get '/'
|
40
|
+
@body = Nokogiri(last_response.body)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should have an app title" do
|
44
|
+
@body.css('title').first.content.should == "Sample Eris App"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should load the shared version of the enyo framework" do
|
48
|
+
enyo_tags = @body.css('script[@enyo]')
|
49
|
+
|
50
|
+
enyo_tags.length.should == 1
|
51
|
+
enyo_tags.first["src"].should == "/usr/palm/frameworks/enyo/0.10/framework/enyo.js"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should load the common helper files" do
|
55
|
+
eris_helper_tags = @body.css('script[@eris-helpers]')
|
56
|
+
|
57
|
+
eris_helper_tags.length.should == 1
|
58
|
+
eris_helper_tags.first["src"].should == "eris-helpers/ErisHelpers.js"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should load the app's specific helper files" do
|
62
|
+
app_helper_tags = @body.css('script[@app-helper]')
|
63
|
+
|
64
|
+
app_helper_tags.length.should == 1
|
65
|
+
app_helper_tags.first["src"].should == "spec/acceptance/helpers/AppHelper.js"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "when injecting launch params" do
|
70
|
+
it "does nothing if launch_params is nil" do
|
71
|
+
get '/'
|
72
|
+
@body = Nokogiri(last_response.body)
|
73
|
+
@body.css('script[@launch-params]').length.should == 0
|
74
|
+
end
|
75
|
+
|
76
|
+
it "injects the launch params script if launchParams is present" do
|
77
|
+
get '/?launchParams=foo'
|
78
|
+
@body = Nokogiri(last_response.body)
|
79
|
+
@body.css('script[@launch-params]').length.should == 1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when serving eris-helpers" do
|
84
|
+
before :each do
|
85
|
+
get '/eris-helpers/ErisHelpers.js'
|
86
|
+
@body = last_response.body
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should include the fake app relaunch" do
|
90
|
+
@body.should match(/relaunchWithParams =/)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should include the XHR proxy for Luna calls" do
|
94
|
+
@body.should match(/var NovacomRequest = enyo.kind\(\{/)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should include the XHR proxy for arbitrary AJAX calls" do
|
98
|
+
@body.should match(/var ProxiedRequest = enyo.kind\(\{/)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "when serving enyo" do
|
103
|
+
before :each do
|
104
|
+
get '/usr/palm/frameworks/enyo/0.10/framework/enyo.js'
|
105
|
+
@body = last_response.body
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should return enyo" do
|
109
|
+
@body.should == "This is the enyo.js fixture"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "when making a palm/luna XHR" do
|
114
|
+
let :luna_request do
|
115
|
+
luna_request = double('LunaRequest')
|
116
|
+
luna_request.stub!(:execute)
|
117
|
+
end
|
118
|
+
|
119
|
+
before :each do
|
120
|
+
Eris::LunaRequest.stub!(:new).and_return(luna_request)
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "to other services" do
|
124
|
+
it "should shell out to luna" do
|
125
|
+
luna_request.should_receive(:execute)
|
126
|
+
req_string = '{"body": {"foo" : "bar" }, "url": "http://www.example.com/"}'
|
127
|
+
|
128
|
+
get "/luna?req=#{URI.encode(req_string)}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "to the location service" do
|
133
|
+
it "does not shell out" do
|
134
|
+
Eris::LunaRequest.stub!(:new).and_return(luna_request)
|
135
|
+
luna_request.should_not_receive(:execute)
|
136
|
+
|
137
|
+
req_string = '{"body": {}, "url": "palm://com.palm.location/getCurrentPosition"}'
|
138
|
+
|
139
|
+
get "/luna?req=#{URI.encode(req_string)}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "when making an external API XHR" do
|
145
|
+
it "should give a 200 if it's sucessful" do
|
146
|
+
VCR.use_cassette('success') do
|
147
|
+
req_string = '{"body": {"foo" : "bar" }, "url": "http://www.google.com/"}'
|
148
|
+
|
149
|
+
get "/xhrproxy?req=#{URI.encode(req_string)}"
|
150
|
+
last_response.should be_ok
|
151
|
+
last_response.body.should match(/google/)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should give a 200 if it's sucessful" do
|
156
|
+
VCR.use_cassette('failure') do
|
157
|
+
req_string = '{"url":"http://dev.virtualearth.net/REST/v1/Routes/Driving","body":{"output":"json","c":"en-US","key":"Ah2oavKf-raTJYVgMxnxJg9E2E2_53Wb3jz2lD4N415EFSKwFlhlMe9U2dJpMZyJ","routePathOutput":"Points","timeType":"Departure","dateTime":"14:46:48","distanceUnit":"mi","wp.0":"731 Market St, San Francisco, ca","wp.1":"jkhgkjhgkjhg"}}'
|
158
|
+
|
159
|
+
get "/xhrproxy?req=#{URI.encode(req_string)}"
|
160
|
+
last_response.should_not be_ok
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should shell out to curl" do
|
165
|
+
proxied_request = double('ProxiedRequest')
|
166
|
+
proxied_request.stub!(:execute)
|
167
|
+
Eris::ProxiedRequest.stub!(:new).and_return(proxied_request)
|
168
|
+
proxied_request.should_receive(:execute)
|
169
|
+
|
170
|
+
req_string = '{"body": {"foo" : "bar" }, "url": "http://www.example.com/"}'
|
171
|
+
|
172
|
+
get "/xhrproxy?req=#{URI.encode(req_string)}"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|