eris 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +4 -0
  5. data/README.md +2 -0
  6. data/Rakefile +2 -0
  7. data/bin/eris +5 -0
  8. data/eris.gemspec +36 -0
  9. data/js_helpers/ErisHelpers.js +84 -0
  10. data/lib/eris.rb +22 -0
  11. data/lib/eris/eris.ru +3 -0
  12. data/lib/eris/lib/eris_config.rb +17 -0
  13. data/lib/eris/lib/jasmine_config_overrides.rb +43 -0
  14. data/lib/eris/lib/jasmine_rspec_runner.rb +34 -0
  15. data/lib/eris/lib/luna_request.rb +51 -0
  16. data/lib/eris/lib/proxied_request.rb +18 -0
  17. data/lib/eris/lib/server.rb +75 -0
  18. data/lib/eris/tasks/generate.rb +19 -0
  19. data/lib/eris/tasks/server.rb +14 -0
  20. data/lib/eris/templates/Gemfile +5 -0
  21. data/lib/eris/templates/Rakefile +32 -0
  22. data/lib/eris/templates/ci_build.sh +16 -0
  23. data/lib/eris/templates/eris_config.json +3 -0
  24. data/lib/eris/templates/jasmine.yml +77 -0
  25. data/lib/eris/templates/sampleSpec.js +13 -0
  26. data/lib/eris/templates/specHelper.js +3 -0
  27. data/lib/eris/version.rb +3 -0
  28. data/spec/fixtures/enyo/0.10/framework/enyo.js +1 -0
  29. data/spec/fixtures/sample_app/app/models/foo.js +1 -0
  30. data/spec/fixtures/sample_app/appinfo.json +10 -0
  31. data/spec/fixtures/sample_app/eris_config.json +3 -0
  32. data/spec/fixtures/sample_app/index.html.erb +20 -0
  33. data/spec/fixtures/sample_app/spec/acceptance/helpers/AppHelper.js +0 -0
  34. data/spec/fixtures/vcr_cassettes/failure.yml +34 -0
  35. data/spec/fixtures/vcr_cassettes/success.yml +62 -0
  36. data/spec/lib/eris/lib/eris_config_spec.rb +25 -0
  37. data/spec/lib/eris/lib/eris_spec.rb +7 -0
  38. data/spec/lib/eris/lib/luna_request_spec.rb +27 -0
  39. data/spec/lib/eris/lib/proxied_request_spec.rb +19 -0
  40. data/spec/lib/eris/lib/server_spec.rb +175 -0
  41. data/spec/lib/eris/tasks/generator_integration_spec.rb +38 -0
  42. data/spec/lib/eris/tasks/generator_spec.rb +90 -0
  43. data/spec/lib/eris/tasks/server_spec.rb +44 -0
  44. data/spec/spec_helper.rb +41 -0
  45. 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,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "eris"
4
+ gem "jasmine"
5
+ gem "rake"
@@ -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,3 @@
1
+ {
2
+ "enyoRoot": "/Users/pivotal/workspace/"
3
+ }
@@ -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
+ });
@@ -0,0 +1,3 @@
1
+ function getJson(filename) {
2
+ return enyo.g11n.Utils.getJsonFile({path: 'spec/unit/source/mock', locale: filename});
3
+ }
@@ -0,0 +1,3 @@
1
+ module Eris
2
+ Eris::VERSION = "0.0.1"
3
+ end
@@ -0,0 +1 @@
1
+ This is the enyo.js fixture
@@ -0,0 +1 @@
1
+ var noop = function() {};
@@ -0,0 +1,10 @@
1
+ {
2
+ "title": "Sample Eris App",
3
+ "id": "com.example.sampleapp",
4
+ "icon": "icon.png",
5
+ "uiRevision": 2,
6
+ "type": "web",
7
+ "version": "0.0.1",
8
+ "main": "index.html",
9
+ "vendor": "ExampleCo"
10
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "enyoRoot": "../"
3
+ }
@@ -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>
@@ -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&#39;s information, including webpages, images, videos and more. Google has many special features to help you find exactly what you&#39;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&hellip;");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 &raquo;</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%>&nbsp;</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&#39;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&nbsp;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">&copy; 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,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Eris do
4
+ it "sets a constant of the base file path" do
5
+ Eris::FILE_PATH.should == File.expand_path(File.dirname(__FILE__) + '/../../../../lib/')
6
+ end
7
+ 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