diff --git a/spec/regexper_spec.js b/spec/regexper_spec.js index f6a2cb5..34835db 100644 --- a/spec/regexper_spec.js +++ b/spec/regexper_spec.js @@ -1,4 +1,6 @@ import Regexper from 'src/js/regexper.js'; +import parser from 'src/js/parser/javascript.js'; +import Snap from 'snapsvg'; import Q from 'q'; describe('regexper.js', function() { @@ -326,7 +328,100 @@ describe('regexper.js', function() { describe('#renderRegexp', function() { + beforeEach(function() { + spyOn(parser, 'parse'); + }); + it('parses the expression', function(done) { + this.regexper.renderRegexp('example expression'); + + setTimeout(() => { + expect(parser.parse).toHaveBeenCalledWith('example expression'); + done(); + }, 100); + }); + + it('replaces newlines with "\\n"', function(done) { + this.regexper.renderRegexp('multiline\nexpression'); + + setTimeout(() => { + expect(parser.parse).toHaveBeenCalledWith('multiline\\nexpression'); + done(); + }, 100); + }); + + describe('when parsing fails', function() { + + beforeEach(function(done) { + parser.parse.and.throwError('parsing failure'); + this.regexper.renderRegexp('example expression'); + + setTimeout(done, 100); + }); + + it('sets the state to be "has-error"', function() { + expect(this.regexper.state).toEqual('has-error'); + }); + + it('displays the error message', function() { + expect(this.regexper.error.innerHTML).toEqual('Error: parsing failure'); + }); + + }); + + describe('when parsing succeeds', function() { + + beforeEach(function(done) { + this.renderPromise = Q.defer(); + this.parsedExpr = jasmine.createSpyObj('parsedExpr', ['render']); + this.parsedExpr.render.and.returnValue(this.renderPromise.promise); + + parser.parse.and.returnValue(this.parsedExpr); + + spyOn(this.regexper.snap, 'group').and.returnValue('example group'); + + this.regexper.renderRegexp('example expression'); + + setTimeout(done, 100); + }); + + it('renders the parsed expression', function() { + expect(this.parsedExpr.render).toHaveBeenCalledWith('example group'); + }); + + describe('when rendering is complete', function() { + + beforeEach(function(done) { + this.result = jasmine.createSpyObj('result', ['getBBox', 'transform']); + this.result.getBBox.and.returnValue({ + x: 4, + y: 2, + width: 42, + height: 24 + }); + + spyOn(this.regexper.snap, 'attr'); + + this.renderPromise.resolve(this.result); + + setTimeout(done, 100); + }); + + it('positions the renderd expression', function() { + expect(this.result.transform).toHaveBeenCalledWith(Snap.matrix() + .translate(6, 8)); + }); + + it('sets the dimensions of the image', function() { + expect(this.regexper.snap.attr).toHaveBeenCalledWith({ + width: 62, + height: 44 + }); + }); + + }); + + }); }); diff --git a/src/js/parser/javascript.js b/src/js/parser/javascript.js index 48ce9f2..1b7a297 100644 --- a/src/js/parser/javascript.js +++ b/src/js/parser/javascript.js @@ -36,8 +36,11 @@ parser.Parser.RepeatOptional = RepeatOptional; parser.Parser.RepeatRequired = RepeatRequired; parser.Parser.RepeatSpec = RepeatSpec; -parser.resetGroupCounter = () => { - parser.Parser.Subexp.resetCounter(); -} +parser.parse = (parse => { + return function() { + Subexp.resetCounter(); + return parse.apply(this, arguments); + }; +})(parser.parse); export default parser; diff --git a/src/js/regexper.js b/src/js/regexper.js index 9d96629..3a2a492 100644 --- a/src/js/regexper.js +++ b/src/js/regexper.js @@ -125,11 +125,7 @@ export default class Regexper { } renderRegexp(expression) { - var snap = Snap(this.svg); - - snap.selectAll('g').remove(); - - parser.resetGroupCounter(); + this.snap.selectAll('g').remove(); return Q.fcall(parser.parse.bind(parser), expression.replace(/\n/g, '\\n')) .then(null, message => { @@ -139,14 +135,13 @@ export default class Regexper { throw message; }) - .invoke('render', snap.group()) + .invoke('render', this.snap.group()) .then(result => { - var box; + var box = result.getBBox(); - box = result.getBBox(); - result.container.transform(Snap.matrix() + result.transform(Snap.matrix() .translate(this.padding - box.x, this.padding - box.y)); - snap.attr({ + this.snap.attr({ width: box.width + this.padding * 2, height: box.height + this.padding * 2 });