I'm pretty sure this won't work, but…
I have been trying to get Sinon.js-like stubbing working in Dart. I wonder if I can simply use Sinon.js via js-interop? I have the feeling that this will not work in Dartium (or
content_shell
from the command line) because Dart is directly using the native implementation of HttpRequest
built into the browser.Still, it seems worth a shot.
So I grab the latest sinon.js and install it in Hipster MVC's
test
directory:➜ test git:(http-test-server) wget http://sinonjs.org/releases/sinon-1.7.3.js 2013-07-10 21:16:52 (109 KB/s) - `sinon-1.7.3.js' saved [132684/132684]I will need js-interop, which now involves two changes: installation via Dart Pub and updating the test's web page context to support it.
Installing js-interop via pub is a simple matter of updating my pubspec.yaml to include
js
as a dependency, which… Hipster MVC already includes:name: hipster_mvc version: 0.2.6 description: Dart-based MVC framework author: Chris Strom <chris@eeecomputes.com> homepage: https://github.com/eee-c/hipster-mvc dependencies: unittest: any dirty: any uuid: any js: anyThat should probably be
browser: any
instead of js: any
. Up until this point, I have not included js-interop in Hipster MVC. My guess is that I included the js
package from back before it was js-interop (I am not sure if that was ever actually the case) or if I mistakenly included it in an effort to get the browser library, which aids in Dart support in browsers that do not support Dart natively. Anyhow, I update my
pubspec.yaml
to explicitly depend on browser
:name: hipster_mvc version: 0.2.6 description: Dart-based MVC framework author: Chris StromAnd then pub install:homepage: https://github.com/eee-c/hipster-mvc dependencies: browser: any unittest: any dirty: any uuid: any js: any
➜ hipster-mvc git:(http-test-server) ✗ pub update Resolving dependencies........... Dependencies updated!That should change nothing since the js library depends on browser. I just prefer to be explicit about my dependencies.
The other change that I need for js-interop is to include the iterop.js file which is, oddly enough, included in the browser package. I add the
<script>
tag for browser/interop
to my test/index.html
context page, along with sinon.js
:<html> <head> <title>Hipster Test Suite</title> <script type="application/dart" src="hipster_mvc_test.dart"></script> <script type='text/javascript'> // Code to notify the test runner when all tests are done.... </script> <script src="packages/browser/dart.js"></script> <script src="packages/browser/interop.js"></script> <script src="sinon-1.7.3.js"></script> </head> <body> </body> </html>I next need to import the js-interop library into my test script:
library hipster_mvc_test; import 'package:unittest/unittest.dart'; import 'dart:html'; import 'dart:async'; import 'dart:json' as JSON; import 'package:js/js.dart' as js; //...That will allow me to reference JavaScript files under the
js.
prefix in Dart. I do so in the setUp()
block of my test: group("HTTP get", (){
var server;
setUp(() {
server = js.context.sinon.fakeServer.create();
server.respondWith(
'[{ "id": 12, "comment": "Hey there" }]'
);
});
// test here...
});
I am explicitly using the string response version of Sinon's fake server to avoid the need to convert Dart HashMap
s and List
s to JavaScript objects and arrays. If I get this working with the simplest approach, then I will worry about that. In JavaScript, the above would replace the XMLHttpRequest
object with a fake version that will respond to all requests with the specified JSON string. To see if Dart is using that same XMLHttpRequest object, I write my test as:
group("HTTP get", (){
var server;
setUp(() { /* ... */ });
test("it can parse responses", (){
var model = new FakeModel()
..url = '/test';
HipsterSync.
call('get', model).
then(
expectAsync1((response) {
expect(response, containsPair('comment', 'Hey there'));
})
);
server.respond();
});
});
This code works when hitting against a real server. The only change here is the addition of Sinon's server.respond()
, which will respond to all XHR requests that have been made in my test.Unfortunately, this does not work.
I never do see that response come back. I play around a bit with Sinon options. I set
autoRespond
to true. I set the URL to an http:// version instead. I even add console.log()
statements directly to my copy of sinon.js. But I get no joy.I can verify that the JavaScript XMLHttpRequest object is replaced:
But, Dart is, it would seem, by-passing this object to get to the native XHR object. That's good for Dart, but it stinks for my purposes tonight.
Just for giggles, I try compiling my test to JavaScript and running it from a normal Chrome browser. I get the following stacktrace:
FAIL: Hipster Sync HTTP get it can parse responses Caught NoSuchMethodError : method not found: 'Object #<JSUnknown> has no method '$$dom_addEventListener$3'' Receiver: "" Arguments: [] TypeError: Object #<JSUnknown> has no method '$$dom_addEventListener$3' $.$$dom_addEventListener$3$x file:///home/chris/repos/hipster-mvc/test/hipster_mvc_test.dart.js 18979:39 hipster_sync_tests___closure6.call$0 file:///home/chris/repos/hipster-mvc/test/hipster_mvc_test.dart.js 13852:9 TestCase.testFunction$0 file:///home/chris/repos/hipster-mvc/test/hipster_mvc_test.dart.js 16052:30I try passing a Dart callback to Sinon's
respondWith()
on the off chance that this is what it is “JSUnknown”: setUp(() {
server = js.context.sinon.fakeServer.create();
var cb = new js.Callback.once((req) {
req.respond(200, [], '{ "id": 12, "comment": "Hey there" }');
});
server.respondWith(cb);
});
But that has no effect upon recompilation. Ah well, it was a long shot to begin with. With definitive proof that overriding JavaScript's XMLHttpRequest will have no effect on my Dart tests, I can move onto other avenues of exploration. Tomorrow.
Day #808
No comments:
Post a Comment