Permalink
Browse files

sc - starting out with some better inspection tools to be more produc…

…tive working with cocoa
  • Loading branch information...
1 parent c41dc00 commit 4c38b139b9eb8705dd875b8c63a7d9288c77b568 @sconover committed Oct 16, 2009
View
BIN .DS_Store
Binary file not shown.
View
@@ -0,0 +1,38 @@
+class Object
+ def singleton_class
+ (class << self; self; end)
+ end
+end
+
+class Decorator
+ def before(&block)
+ @before = block
+ end
+
+ def after(&block)
+ @after = block
+ end
+
+ def apply_to(subject)
+ before_block = @before
+ after_block = @after
+
+ subject.public_methods(false).each do |method|
+ next if method == "inspect"
+ subject.singleton_class.class_eval do
+ original_method_symbol = "original_#{method}".to_sym
+ alias_method original_method_symbol, method
+
+ define_method(method) do |*args|
+ before_block.call(method.to_sym, args) if before_block
+
+ result = subject.send(original_method_symbol, *args)
+
+ after_block.call(method.to_sym, args, result) if after_block
+
+ result
+ end
+ end
+ end
+ end
+end
View
@@ -21,7 +21,7 @@ def self.request_handler=(block)
def startLoading
rack_response = CocoaToRackResponseAdapter.new(request, self)
-
+
@@block.call(
CocoaToRackRequestAdapter.new(request),
rack_response
@@ -63,7 +63,7 @@ def initialize(ns_url_request)
env["PATH_INFO"] ||= ns_url_request.URL.path.to_s
env["QUERY_STRING"] ||= ns_url_request.URL.query.to_s
env["rack.url_scheme"] = ns_url_request.URL.scheme.to_s
-
+
super(env)
end
View
@@ -0,0 +1,29 @@
+require "lib/decorator"
+
+class LogDecorator
+ def initialize(stream)
+ @stream = stream
+ end
+
+ def apply_to(subject)
+ the_stream = @stream
+
+ decorator = Decorator.new
+ decorator.before do |method_symbol, args|
+ the_stream << "-> #{subject.class}.#{method_symbol.to_s}#{_args_to_s(args)}\n"
+ end
+ decorator.after do |method_symbol, args, result|
+ the_stream << "<- #{subject.class}.#{method_symbol.to_s}#{_args_to_s(args)} : #{result.inspect}\n"
+ end
+
+ decorator.apply_to(subject)
+ end
+
+ def _args_to_s(args)
+ if args.length > 0
+ "(" + args.collect{|arg|arg.class.to_s}.join(", ") + ")"
+ else
+ ""
+ end
+ end
+end
View
@@ -1,6 +1,7 @@
require 'osx/cocoa'
require 'lib/cocoa_utils'
require "lib/local_protocol"
+require "lib/log_decorator"
OSX.require_framework 'WebKit'
@@ -76,7 +77,12 @@ def js(str)
end
end
-
+class Object
+ def log_calls(to=$stdout)
+ LogDecorator.new(to).apply_to(self)
+ self
+ end
+end
class WebResourceLoadDelegate < OSX::NSObject
@@ -94,7 +100,7 @@ def xwebView_identifierForInitialRequest_fromDataSource(v, request, source)
def webView_resource_willSendRequest_redirectResponse_fromDataSource(v, resource, request, response, source)
# puts "webView_resource_willSendRequest_redirectResponse_fromDataSource #{request.URL.to_s}"
-
+# p request.HTTPBody
request_headers = request.allHTTPHeaderFields.to_hash
if request_headers.values.collect{|v|v.to_s}.include?("XMLHttpRequest")
@unresolved_ajax_request = true
@@ -135,8 +141,6 @@ def webView_resource_didReceiveAuthenticationChallenge_fromDataSource(v, resourc
def webView_resource_didCancelAuthenticationChallenge_fromDataSource(v, resource, challenge, source)
# p 9
end
-
-
end
class WebFrameLoadDelegate < OSX::NSObject
@@ -152,9 +156,7 @@ def webView_didFailLoadWithError_forFrame(webview, load_error, frame)
def webView_didFailProvisionalLoadWithError_forFrame(webview, load_error, frame)
OSX.CFRunLoopStop(OSX.CFRunLoopGetCurrent)
end
-
-
-
+
def webView_didStartProvisionalLoadForFrame(v, frame)
end
View
@@ -1,4 +1,36 @@
+Coming back to schnauzer
+
+- I have no idea what's going on in this objc binding code
+- Neither would anyone else
+- So the objective ought to be to make a nice objc binding/exploration toolkit
+ - dynamic adapter class that logs automatically?
+...
+- and then, copious documentation on what I find is happening
+
+
+Thoughts
+
+- bundler-ify?
+- MacRuby mode / adapter (vs MRI+rubycocoa)?
+ - recognize MacRuby, run tests in that context
+
+===========
+
+Getting this done is about
+ 1) understanding webkit bugs and working with the community to get them fixed
+ 2) flexing the api and driving out memory leaks and such
+ 3) documenting the esoteric parts of the code
+ 4) webrat?
+
+
+No http daemons, no network traffic. It's all in-process.
+Real browser
+Fast
+Simple/minimal api
+
+=============
+
rack request/response
Schnauzer.new do |request, response|
#handle the request, write to the response
@@ -16,4 +48,10 @@ assert failures
-need to dealloc. lots of lurking memory issues.
+need to dealloc. lots of lurking memory issues.
+
+
+this project represents a lot of objc and cocoa webkit reverse engineering. comment that stuff carefully.
+
+
+mode where js errors raise a ruby exception?
View
@@ -0,0 +1,19 @@
+Gem::Specification.new do |s|
+ s.name = %q{schnauzer}
+ s.version = "0.1"
+
+ s.authors = ["Steve Conover"]
+ s.date = %q{2009-02-24}
+ s.description = %q{A real Safari browser in ruby}
+ s.email = %q{sconover@gmail.com}
+ s.extensions = []
+ s.extra_rdoc_files = ["README", "LICENSE"]
+ s.files = []
+ s.has_rdoc = true
+ s.homepage = %q{http://github.com/sconover/schnauzer/tree/master}
+ s.rdoc_options = ["--quiet", "--title", "Schnauzer", "--main", "README", "--inline-source"]
+ s.require_paths = ["lib"]
+ s.summary = %q{A real Safari browser in ruby. You can provide your own url request/response handling. It's fast.}
+ s.add_dependency "sinatra"
+ s.add_dependency "rubycocoa"
+end
@@ -2,12 +2,12 @@
require "benchmark"
require "lib/schnauzer"
require 'sinatra/test'
-require "spec"
+require "test/spec"
describe "schnauzer + sinatra app" do
- before(:all) do
+ before do
app =
Sinatra.new do
set :static, true
@@ -21,6 +21,33 @@
"#{params[:to_echo]}, echoed back"
end
+ post '/echo_standard_post' do
+ (<<-HTML)
+ <html>
+ <body>
+ <div id="message">You posted #{params[:to_echo]}</div>
+ </body>
+ </html>
+ HTML
+ end
+
+ post '/echo_post' do
+ "#{params[:to_echo]}, post echoed back"
+ end
+
+ get '/html_post' do
+ (<<-HTML)
+ <html>
+ <body>
+ hi I do standard post
+ <form id="the_form" method="post" action="/echo_standard_post">
+ <input id='message_to_post' type="hidden" name="to_echo" value=""/>
+ <input type="submit"/>
+ </form>
+ </body>
+ </html>
+ HTML
+ end
get '/ajax' do
(<<-HTML)
@@ -48,6 +75,35 @@
</html>
HTML
end
+
+ get '/ajax_post' do
+ (<<-HTML)
+ <html>
+ <head>
+ <script type="text/javascript" language="JavaScript" src="/prototype.js"></script>
+ <script type="text/javascript">
+ function doEchoPost(str) {
+ $('message').innerHTML = "echoing " + str
+ new Ajax.Request(
+ "/echo_post",
+ {method: 'post',
+ postBody: str,
+ onComplete: function(result){document.getElementById("message").innerHTML = result.responseText},
+ onFailure: function(){document.getElementById("message").innerHTML = "failed"}}
+ )
+ }
+ </script>
+
+ </head>
+ <body>
+ hi I do ajax post
+ <button id="ajax_button" onclick="doEchoPost('peter_rabbit')">click me to do ajax</button>
+ message goes here:<div id="message"></div>
+ </body>
+ </html>
+ HTML
+ end
+
end
harness = Sinatra::TestHarness.new(app)
@@ -58,7 +114,7 @@
@harness = harness
end
- after(:all) do
+ after do
Schnauzer.unload_request_handler
end
@@ -69,21 +125,42 @@
it "same thing but with schnauzer (using the session object to request)" do
@browser.load_url("local://host/foo/hi")
- @browser.js("document.body.innerHTML").should include("hi I'm a web app")
+ @browser.js("document.body.innerHTML").should.include("hi I'm a web app")
end
it "basic ajax works" do
@browser.load_url("local://host/ajax")
- @browser.js("document.body.innerHTML").should include("hi I do ajax")
+ @browser.js("document.body.innerHTML").should.include("hi I do ajax")
@browser.js("document.getElementById('ajax_button').onclick()")
- @browser.js("document.body.innerHTML").should include(%{message goes here:<div id="message">peter_rabbit, echoed back</div>})
+ @browser.js("document.body.innerHTML").should.include(%{message goes here:<div id="message">peter_rabbit, echoed back</div>})
@browser.js("doEcho('flopsy')")
- @browser.js("document.body.innerHTML").should include(%{message goes here:<div id="message">flopsy, echoed back</div>})
+ @browser.js("document.body.innerHTML").should.include(%{message goes here:<div id="message">flopsy, echoed back</div>})
+ end
+
+ xit "standard post" do
+ @browser.load_url("local://host/html_post")
+
+ @browser.js("document.getElementById('message_to_post').value = 'Peter Rabbit'")
+ @browser.js("document.getElementById('the_form').submit()")
+
+ @browser.js("document.body.innerHTML").should.include("You posted Peter Rabbit")
+ end
+
+
+ xit "ajax post works" do
+ @browser.load_url("local://host/ajax_post")
+ @browser.js("document.body.innerHTML").should.include("hi I do ajax")
+
+ @browser.js("document.getElementById('ajax_button').onclick()")
+ @browser.js("document.body.innerHTML").should.include(%{message goes here:<div id="message">peter_rabbit, post echoed back</div>})
+
+ # @browser.js("doEchoPost('flopsy')")
+ # @browser.js("document.body.innerHTML").should.include(%{message goes here:<div id="message">flopsy, post echoed back</div>})
end
- xit "ajax page performance" do
+ it "ajax page performance" do
n = 20
time =
Benchmark.realtime {
@@ -1,7 +1,7 @@
require "rubygems"
require "lib/schnauzer"
require "benchmark"
-require "spec"
+require "test/spec"
describe Schnauzer do
before do
@@ -19,7 +19,7 @@
HTML
)
- @browser.js("document.body.innerHTML").should include("<i>hello world</i>")
+ @browser.js("document.body.innerHTML").should.include("<i>hello world</i>")
end
it "uses base url provided to make absolute urls" do
@@ -32,7 +32,7 @@
"http://bar")
- @browser.js("document.getElementById('mylink').href").should == "http://bar/mypage.html"
+ @browser.js("document.getElementById('mylink').href").should.equal "http://bar/mypage.html"
end
it "executes javascript" do
@@ -51,12 +51,12 @@
)
@browser.js("document.body.innerHTML") \
- .should include(%{hello <div id="the_spot">world</div>})
+ .should.include(%{hello <div id="the_spot">world</div>})
end
it "load from url" do
@browser.load_url("file://#{File.expand_path("spec/little_page.html")}")
- @browser.js("document.body.innerHTML").should include(%{hello <div id="foo">world</div>})
+ @browser.js("document.body.innerHTML").should.include(%{hello <div id="foo">world</div>})
end
it "performance" do
Oops, something went wrong.

0 comments on commit 4c38b13

Please sign in to comment.