juliocesar-harmony 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .yardoc/
3
+ doc/
4
+ TODO
5
+ .yard_issues.md
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright © 2009 Martin Aumont (mynyml)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,13 @@
1
+ .gitignore
2
+ LICENSE
3
+ Manifest
4
+ README.md
5
+ Rakefile
6
+ docs.watchr
7
+ harmony.gemspec
8
+ lib/harmony.rb
9
+ lib/harmony/page.rb
10
+ specs.watchr
11
+ test/harmony_test.rb
12
+ test/page_test.rb
13
+ test/test_helper.rb
data/README.md ADDED
@@ -0,0 +1,162 @@
1
+ Harmony
2
+ =======
3
+
4
+ .,ad88888888baa,
5
+ ,d8P""" ""9888ba.
6
+ .a8" ,ad88888888888a
7
+ aP' ,88888888888888888a
8
+ ,8" ,88888888888888888888,
9
+ ,8' (888888888( )888888888,
10
+ ,8' `8888888888888888888888
11
+ 8) `888888888888888888888,
12
+ 8 "8888888888888888888)
13
+ 8 `888888888888888888)
14
+ 8) "8888888888888888
15
+ (b "88888888888888'
16
+ `8, (8) 8888888888888)
17
+ "8a ,888888888888)
18
+ V8, d88888888888"
19
+ `8b, ,d8888888888P'
20
+ `V8a, ,ad8888888888P'
21
+ ""88888888888888888P"
22
+ """"""""""""
23
+
24
+ Summary
25
+ -------
26
+
27
+ Harmony provides a simple DSL to execute javascript + DOM code within ruby.
28
+
29
+ Examples
30
+ --------
31
+
32
+ ### Simple Javascript Parsing
33
+
34
+ require 'harmony'
35
+
36
+ page = Harmony::Page.new(<<-HTML)
37
+ <html>
38
+ <head>
39
+ <title>Foo</title>
40
+ </head>
41
+ <body></body>
42
+ </html>
43
+ HTML
44
+
45
+ page.execute_js("1+1") #=> 2
46
+ page.execute_js("document.title") #=> "Foo"
47
+
48
+ The Page object's `#execute_js` method (aliased as `#x` for convenience) takes a
49
+ string of javascript code, executes it and returns the last statement's value
50
+ (just like a ruby method).
51
+
52
+ ### Javascript Unit Tests
53
+
54
+ One interesting use of Harmony is to test your javascript code within your ruby
55
+ application's own tests (test/unit, minitest, RSpec, nanotest, etc). Which
56
+ consequently means that you can now run browser-less, fully command-line
57
+ based, DOM-javascript tests.
58
+
59
+ require 'test/unit'
60
+ require 'harmony'
61
+
62
+ class JavascriptTest < Test::Unit::TestCase
63
+ def setup
64
+ @page = Harmony::Page.new
65
+ @page.load('public/javascripts/foo.js')
66
+ end
67
+
68
+ def test_foo
69
+ assert_equal "world", @page.execute_js(<<-JS)
70
+ foo = new Foo;
71
+ foo.hello();
72
+ JS
73
+ end
74
+ end
75
+
76
+ ### DOM Handling
77
+
78
+ Don't be affraid to throw in your favorite client-side js framework, like
79
+ JQuery or Prototype. And notice that scripts linked to in `<script>` tags will
80
+ automatically get pulled in.
81
+
82
+ require 'harmony'
83
+
84
+ page = Harmony::Page.new(<<-HTML)
85
+ <html>
86
+ <head>
87
+ <script src="javascripts/jquery.js" type="text/javascript"></script>
88
+ </head>
89
+ <body>
90
+ <div id="widget">ohaie</div>
91
+ </body>
92
+ </html>
93
+ HTML
94
+
95
+ page.execute_js("$('#widget').innerHTML") #=> "ohaie"
96
+
97
+ ### Fetching Documents
98
+
99
+ Use `Harmony::Page.fetch(uri)` to create a page from a remote document.
100
+
101
+ require 'harmony'
102
+
103
+ page = Harmony::Page.fetch('http://example.com')
104
+ page.execute_js('document.title') #=> "Example Web Page"
105
+
106
+ `fetch` also accepts "file://" uris.
107
+
108
+ Install
109
+ -------
110
+
111
+ # There's a gem dependency bug in rubygems currently, so we'll have to
112
+ # install dependencies manually. This will be fixed soon.
113
+ gem install stackdeck
114
+ gem install johnson -v "2.0.0.pre1"
115
+
116
+ gem install harmony
117
+
118
+ See Also
119
+ --------
120
+
121
+ * [holygrail][20]: Harmony plugin for Rails tests
122
+
123
+ Acknowledgement
124
+ ---------------
125
+
126
+ Harmony is a thin DSL wrapper around three **amazing** libs, [Johnson][1],
127
+ [env.js][30] and [Envjs][2] . The authors of those libs have been doing a huge
128
+ amount of great work for quite a while, so please go recommend them on
129
+ WorkingWithRails right now and/or follow them on github:
130
+
131
+ [jbarnette][3], [tenderlove][4], [smparkes][5], [wycats][6], [matthewd][7], [thatcher][8], [jeresig][9]
132
+
133
+ Special thanks go to [smparkes][10] for his patient help, and for providing the
134
+ last puzzle pieces that made [everything][12] [work][11] [together][13].
135
+
136
+ Links
137
+ -----
138
+ * code: <http://github.com/mynyml/harmony>
139
+ * docs: <http://yardoc.org/docs/mynyml-harmony>
140
+ * wiki: <http://wiki.github.com/mynyml/harmony>
141
+ * bugs: <http://github.com/mynyml/harmony/issues>
142
+
143
+
144
+
145
+ YinYang ASCII art is © Normand Veilleux (nveilleuATemr1.emrDOTca)
146
+
147
+
148
+ [1]: http://github.com/jbarnette/johnson/
149
+ [2]: http://env-js.appspot.com/
150
+ [3]: http://www.workingwithrails.com/person/10668-john-barnette
151
+ [4]: http://github.com/tenderlove/
152
+ [5]: http://www.workingwithrails.com/person/11739-steven-parkes
153
+ [6]: http://www.workingwithrails.com/person/1805-yehuda-katz
154
+ [7]: http://www.workingwithrails.com/person/6221-matthew-draper
155
+ [8]: http://github.com/thatcher/
156
+ [9]: http://ejohn.org/
157
+ [10]: http://github.com/smparkes/
158
+ [11]: http://github.com/smparkes/env-js/commit/49abe259813a505b0761e6d31dde671344b5bc87#L0R279
159
+ [12]: http://groups.google.com/group/envjs/msg/4ac719f7db7912f5
160
+ [13]: http://gemcutter.org/gems/envjs
161
+ [20]: http://github.com/mynyml/holygrail
162
+ [30]: http://github.com/thatcher/env-js
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ def gem_opt
2
+ defined?(Gem) ? "-rubygems" : ""
3
+ end
4
+
5
+ # --------------------------------------------------
6
+ # Tests
7
+ # --------------------------------------------------
8
+ task(:default => "test:all")
9
+
10
+ namespace(:test) do
11
+
12
+ desc "Run all tests"
13
+ task(:all) do
14
+ exit system("ruby #{gem_opt} -I.:lib:test -e'%w( #{Dir['test/**/*_test.rb'].join(' ')} ).each {|p| require p }'")
15
+ end
16
+
17
+ desc "Run all tests on multiple ruby versions (requires rvm)"
18
+ task(:portability) do
19
+ versions = %w( 1.8.6 1.8.7 )
20
+ versions.each do |version|
21
+ system <<-BASH
22
+ bash -c 'source ~/.rvm/scripts/rvm;
23
+ rvm use #{version};
24
+ echo "--------- #{version} ----------";
25
+ rake -s test:all'
26
+ BASH
27
+ end
28
+ end
29
+ end
30
+
31
+ # --------------------------------------------------
32
+ # Docs
33
+ # --------------------------------------------------
34
+ desc "Generate YARD Documentation"
35
+ task :yardoc do
36
+ require 'yard'
37
+ YARD::CLI::Yardoc.run *%w( --no-private --no-highlight -o doc/yard --readme README.md --markup markdown - LICENSE )
38
+ end
39
+
data/docs.watchr ADDED
@@ -0,0 +1,25 @@
1
+ # Run me with:
2
+ # $ watchr docs.watchr
3
+
4
+ require 'yard'
5
+ # --------------------------------------------------
6
+ # Rules
7
+ # --------------------------------------------------
8
+ watch( 'lib/.*\.rb' ) { yard }
9
+ watch( 'README.md' ) { yard }
10
+
11
+ # --------------------------------------------------
12
+ # Signal Handling
13
+ # --------------------------------------------------
14
+ Signal.trap('QUIT') { yard } # Ctrl-\
15
+ Signal.trap('INT' ) { abort("\n") } # Ctrl-C
16
+
17
+ # --------------------------------------------------
18
+ # Helpers
19
+ # --------------------------------------------------
20
+ def yard
21
+ print "Updating yardocs... "; STDOUT.flush
22
+ YARD::CLI::Yardoc.run *%w( --no-private --no-highlight -o doc/yard --readme README.md --markup markdown - LICENSE )
23
+ print "done\n"
24
+ end
25
+
data/harmony.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ require 'lib/harmony'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "juliocesar-harmony"
5
+ s.summary = "Javascript + DOM in your ruby, the simple way"
6
+ s.description = "Javascript + DOM in your ruby, the simple way."
7
+ s.author = "Julio Cesar Ody"
8
+ s.email = "julioody@gmail.com"
9
+ s.homepage = "http://github.com/juliocesar/harmony"
10
+ s.require_path = "lib"
11
+ s.rubygems_version = "1.3.5"
12
+ s.version = Harmony::VERSION
13
+ s.files = File.read("Manifest").strip.split("\n")
14
+
15
+ s.add_dependency 'johnson', '2.0.0.pre2'
16
+ s.add_dependency 'envjs', '0.1.4'
17
+ s.add_development_dependency 'minitest'
18
+ end
data/lib/harmony.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Harmony
2
+ VERSION = '0.5.2'
3
+
4
+ autoload :Page, 'harmony/page'
5
+ end
@@ -0,0 +1,123 @@
1
+ require 'pathname'
2
+ require 'tempfile'
3
+
4
+ require 'johnson/tracemonkey'
5
+ require 'envjs/runtime'
6
+
7
+ module Harmony
8
+ class Page
9
+
10
+ # Window factory
11
+ #
12
+ # @private
13
+ module Window #:nodoc:
14
+ extend self
15
+
16
+ # Cache the initial runtime. Parsing env.js (done automatically when
17
+ # Envjs::Runtime is extended) takes a while, so we only want to do this
18
+ # once.
19
+ #
20
+ # @private
21
+ BASE_RUNTIME = Johnson::Runtime.new
22
+ BASE_RUNTIME.extend(Envjs::Runtime)
23
+
24
+ def from_uri(uri)
25
+ BASE_RUNTIME.evaluate("window.open('#{uri}')")
26
+ end
27
+
28
+ def from_document(document)
29
+ Tempfile.open('harmony') {|f| f << document; @path = f.path }
30
+ from_uri("file://#{@path}")
31
+ end
32
+
33
+ def blank
34
+ from_uri('about:blank')
35
+ end
36
+ end
37
+
38
+ # Create page from remote document.
39
+ #
40
+ # @example
41
+ #
42
+ # Page.fetch('http://montrealrb.org')
43
+ # Page.fetch('http://localhost:3000')
44
+ # Page.fetch('file:///home/mynyml/www/foo/index.html')
45
+ #
46
+ # @param [String] uri
47
+ # uri to fetch document from
48
+ #
49
+ # @return [Page]
50
+ # new page object preloaded with fetched document
51
+ #
52
+ def self.fetch(uri)
53
+ page = new
54
+ page.instance_variable_set(:@window, Window.from_uri(uri))
55
+ page
56
+ end
57
+
58
+ # Create new page containing given document.
59
+ #
60
+ # @param [String] document
61
+ # HTML document. Defaults to an "about:blank" window, with the basic
62
+ # structure: `<html><head><title></title></head><body></body></html>`
63
+ #
64
+ def initialize(document=nil)
65
+ @window = Window.from_document(document) if document
66
+ end
67
+
68
+ # Load one or more javascript files in page's context
69
+ #
70
+ # @param [#to_s, #to_s, ...] paths
71
+ # paths to js file
72
+ # @return [Page] self
73
+ #
74
+ def load(*paths)
75
+ paths.flatten.each do |path|
76
+ window.load(path.to_s)
77
+ end
78
+ self
79
+ end
80
+
81
+ # Evaluate Javascript code within this page's context.
82
+ #
83
+ # @param [String] code
84
+ # javascript code to execute
85
+ #
86
+ # @return [Object]
87
+ # last javascript statement's value, cast to a ruby object
88
+ #
89
+ def execute_js(code)
90
+ window.evaluate(code)
91
+ end
92
+ alias :x :execute_js
93
+
94
+ # DOM document's `window` object. Equivalent to the return value of
95
+ # `page.execute_js('window')`
96
+ #
97
+ # @return [Object]
98
+ # window DOM object
99
+ #
100
+ def window
101
+ @window ||= Window.blank
102
+ end
103
+
104
+ # Convenience method, equivalent to the return value of
105
+ # `page.execute_js('window.document')`
106
+ #
107
+ # @return [Object]
108
+ # document DOM object
109
+ #
110
+ def document
111
+ window.document
112
+ end
113
+
114
+ # Page as html document
115
+ #
116
+ # @return [String] html
117
+ #
118
+ def to_html
119
+ document.innerHTML
120
+ end
121
+ end
122
+ end
123
+
data/specs.watchr ADDED
@@ -0,0 +1,36 @@
1
+ # Run me with:
2
+ # $ watchr specs.watchr
3
+
4
+ # --------------------------------------------------
5
+ # Rules
6
+ # --------------------------------------------------
7
+ watch( '^test.*/.*_test\.rb' ) {|m| ruby m[0] }
8
+ watch( '^lib/(.*)\.rb' ) {|m| ruby "test/#{m[1]}_test.rb" }
9
+ watch( '^lib/harmony/(.*)\.rb' ) {|m| ruby "test/#{m[1]}_test.rb" }
10
+ watch( '^test/test_helper\.rb' ) { ruby tests }
11
+
12
+ # --------------------------------------------------
13
+ # Signal Handling
14
+ # --------------------------------------------------
15
+ Signal.trap('QUIT') { ruby tests } # Ctrl-\
16
+ Signal.trap('INT' ) { abort("\n") } # Ctrl-C
17
+
18
+ # --------------------------------------------------
19
+ # Helpers
20
+ # --------------------------------------------------
21
+ def ruby(*paths)
22
+ run "ruby #{gem_opt} -I.:lib:test -e'%w( #{paths.flatten.join(' ')} ).each {|p| require p }'"
23
+ end
24
+
25
+ def tests
26
+ Dir['test/**/*_test.rb']
27
+ end
28
+
29
+ def run( cmd )
30
+ puts cmd
31
+ system cmd
32
+ end
33
+
34
+ def gem_opt
35
+ defined?(Gem) ? "-rubygems" : ""
36
+ end
@@ -0,0 +1,8 @@
1
+ require 'test/test_helper'
2
+
3
+ class HarmonyTest < MiniTest::Unit::TestCase
4
+ test "version" do
5
+ refute_nil Harmony::VERSION
6
+ end
7
+ end
8
+
data/test/page_test.rb ADDED
@@ -0,0 +1,101 @@
1
+ require 'test/test_helper'
2
+
3
+ class PageTest < MiniTest::Unit::TestCase
4
+ include Harmony
5
+
6
+ PAGE = Page.new
7
+
8
+ test "api" do
9
+ assert_respond_to Page, :fetch
10
+ assert_respond_to Page, :new
11
+ assert_respond_to PAGE, :window
12
+ assert_respond_to PAGE, :document
13
+ assert_respond_to PAGE, :execute_js
14
+ assert_respond_to PAGE, :x
15
+ assert_respond_to PAGE, :to_s
16
+ end
17
+
18
+ test "document shortcut" do
19
+ assert_equal PAGE.window.document, PAGE.document
20
+ end
21
+
22
+ test "executes javascript" do
23
+ assert_equal 7, PAGE.x('5+2')
24
+ end
25
+
26
+ test "excutes DOM-accessing javascript" do
27
+ page = Page.new(<<-HTML)
28
+ <html>
29
+ <head>
30
+ <title>Harmony</title>
31
+ </head>
32
+ <body>
33
+ <div></div>
34
+ <div></div>
35
+ </body>
36
+ </html>
37
+ HTML
38
+ assert_equal 'Harmony', page.document.title
39
+ assert_equal 2, page.x(<<-JS)
40
+ document.getElementsByTagName('div').length
41
+ JS
42
+ end
43
+
44
+ test "fetches remote document" do
45
+ path = tempfile(<<-HTML)
46
+ <html><head><title>foo</title></head><body></body></html>
47
+ HTML
48
+ page = Page.fetch("file://#{path}")
49
+ assert_equal 'foo', page.document.title
50
+ end
51
+
52
+ test "default window" do
53
+ assert_empty Page.new.document.title
54
+ end
55
+
56
+ test "cast to html" do
57
+ assert_equal "<html><head><title></title></head><body></body></html>", Page.new.to_html
58
+ end
59
+
60
+ test "loads javascript file" do
61
+ path = tempfile(<<-HTML)
62
+ function foo() { return 'bar' };
63
+ HTML
64
+ page = Page.new.load(path)
65
+ assert_equal 'bar', page.x('foo()')
66
+ end
67
+
68
+ test "can load multiple files as array" do
69
+ paths = []
70
+ paths << tempfile(<<-HTML)
71
+ function foo() { return 'bar' };
72
+ HTML
73
+ paths << tempfile(<<-HTML)
74
+ function moo() { return 'boo' };
75
+ HTML
76
+
77
+ page = Page.new.load(paths)
78
+ assert_equal 'bar', page.x('foo()')
79
+ assert_equal 'boo', page.x('moo()')
80
+ end
81
+
82
+ test "can load multiple files as splat" do
83
+ paths = []
84
+ paths << tempfile(<<-HTML)
85
+ function foo() { return 'bar' };
86
+ HTML
87
+ paths << tempfile(<<-HTML)
88
+ function moo() { return 'boo' };
89
+ HTML
90
+
91
+ page = Page.new.load(*paths)
92
+ assert_equal 'bar', page.x('foo()')
93
+ assert_equal 'boo', page.x('moo()')
94
+ end
95
+
96
+ private
97
+ def tempfile(content)
98
+ Tempfile.open('abc') {|f| f << content; @__path = f.path }
99
+ @__path
100
+ end
101
+ end
@@ -0,0 +1,13 @@
1
+ require 'minitest/autorun'
2
+
3
+ begin require 'ruby-debug'; rescue LoadError; end
4
+ begin require 'redgreen' ; rescue LoadError; end
5
+ begin require 'phocus' ; rescue LoadError; end
6
+
7
+ require 'lib/harmony'
8
+
9
+ class MiniTest::Unit::TestCase
10
+ def self.test(name, &block)
11
+ define_method("test_#{name}".gsub(/\s/,'_'), &block)
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: juliocesar-harmony
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.2
5
+ platform: ruby
6
+ authors:
7
+ - Julio Cesar Ody
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-24 00:00:00 +11:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: johnson
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - "="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.0.pre2
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: envjs
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.4
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: minitest
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: Javascript + DOM in your ruby, the simple way.
46
+ email: julioody@gmail.com
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files: []
52
+
53
+ files:
54
+ - .gitignore
55
+ - LICENSE
56
+ - Manifest
57
+ - README.md
58
+ - Rakefile
59
+ - docs.watchr
60
+ - harmony.gemspec
61
+ - lib/harmony.rb
62
+ - lib/harmony/page.rb
63
+ - specs.watchr
64
+ - test/harmony_test.rb
65
+ - test/page_test.rb
66
+ - test/test_helper.rb
67
+ has_rdoc: true
68
+ homepage: http://github.com/juliocesar/harmony
69
+ licenses: []
70
+
71
+ post_install_message:
72
+ rdoc_options: []
73
+
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ version:
88
+ requirements: []
89
+
90
+ rubyforge_project:
91
+ rubygems_version: 1.3.5
92
+ signing_key:
93
+ specification_version: 3
94
+ summary: Javascript + DOM in your ruby, the simple way
95
+ test_files: []
96
+