I have been neglecting the test suite in the Dart version of the ICE Code Editor. I still have the original four specs that I wrote for it and they still pass. The code still passes
dart_analyzer
. So it ought to be in pretty decent shape. Still, I need to go back to add some tests to catch regressions and the like. But I'll leave that for another day. Maybe even for a #pairwithme session.
Tonight I am going to start working through new code, but I hope to be better about driving it with tests. The next feature that I want to add to ICE is the ability to interface with localStorage. Before I do that, I need to be able to deflate and inflate compressed data that will be stored therein. A little while back, I spiked some exploratory code to find that Dart could use its Zlib package to work with this data. Unfortunately, I also found that it was only capable of doing so on the server. Since this needs to work in the browser, I need to js-interop with the legacy JavaScript.
From the JavaScript version, I know how the string
"Howdy, Bob!"
should look when it is encoded (gzip'd and mime64 encoded). This makes it easy to write two tests:import 'package:unittest/unittest.dart'; import 'package:ice_code_editor/store.dart'; import 'dart:html'; main() { group("gzipping", () { test("it can encode text", (){ expect(Store.encode("Howdy, Bob!"), equals("88gvT6nUUXDKT1IEAA==")); }); test("it can decode as text", (){ expect(Store.decode("88gvT6nUUXDKT1IEAA=="), equals("Howdy, Bob!")); }); }); }From there, the tests drive me. First up, I need to change the message indicating that I do not have a
store.dart
file:Failed to load a file file:///home/chris/repos/ice-code-editor/test/packages/ice_code_editor/store.dart store_test.dart:-1 GET file:///home/chris/repos/ice-code-editor/test/packages/ice_code_editor/store.dartAfter fixing that, my tests tell me that I need a
Store
class, then that I need static methods encode
and decode
. This leaves me with:library ice; class Store { static String encode(String string) { } static String decode(String string) { } }At this point, the message that I need to change is:
FAIL: gzipping it can encode text Expected: '88gvT6nUUXDKT1IEAA==' but: expected String:'88gvT6nUUXDKT1IEAA==' but was null:<null>.Finally, to make that pass, I use a bit of knowledge left over from the spike. The
RawDeflate.deflate()
call from Dart looks like:js.context.RawDeflate.deflate(string)
thanks to the magic of js-interop. That returns a string of gzip'd data. I then use CryptoUtils.bytesToBase64()
from the dart:crypto
package (why is base64 encoding in dart:crypto
, but zlib is not?) package to base64 encode the gzip compressed data. The end result that make my test pass is:library ice; import 'dart:crypto'; import 'package:js/js.dart' as js; class Store { static String encode(String string) { var gzip = js.context.RawDeflate.deflate(string); return CryptoUtils.bytesToBase64(gzip.codeUnits); } static String decode(String string) { } }To support decoding, I implement the reverse as:
library ice; import 'dart:crypto'; import 'package:js/js.dart' as js; class Store { static String encode(String string) { var gzip = js.context.RawDeflate.deflate(string); return CryptoUtils.bytesToBase64(gzip.codeUnits); } static String decode(String string) { var bytes = CryptoUtils.base64StringToBytes(string); var gzip = new String.fromCharCodes(bytes); return js.context.RawDeflate.inflate(gzip); } }With that, I have two passing tests that will let me work with existing data stored from the JavaScript version of the code editor. This seems like a fine stopping point for tonight. At least until my next #pairwithme session!
Day #745
No comments:
Post a Comment