Starting work on spec files
This commit is contained in:
parent
f69d24e302
commit
5537928a80
@ -1,28 +0,0 @@
|
|||||||
import parser from 'src/js/parser/javascript.js';
|
|
||||||
|
|
||||||
describe('parser/javascript.peg', function() {
|
|
||||||
|
|
||||||
describe('regular expression literals', function() {
|
|
||||||
|
|
||||||
describe('flags support', function() {
|
|
||||||
|
|
||||||
it('handles the ignore case flag', function() {
|
|
||||||
expect(parser.parse('/test/i').flags().ignore_case).toEqual(true);
|
|
||||||
expect(parser.parse('/test/').flags().ignore_case).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('handles the global flag', function() {
|
|
||||||
expect(parser.parse('/test/g').flags().global).toEqual(true);
|
|
||||||
expect(parser.parse('/test/').flags().global).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('handles the multiline flag', function() {
|
|
||||||
expect(parser.parse('/test/m').flags().multiline).toEqual(true);
|
|
||||||
expect(parser.parse('/test/').flags().multiline).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
333
spec/regexper_spec.js
Normal file
333
spec/regexper_spec.js
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
import Regexper from 'src/js/regexper.js';
|
||||||
|
import Q from 'q';
|
||||||
|
|
||||||
|
describe('regexper.js', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.root = document.createElement('div');
|
||||||
|
this.root.innerHTML = [
|
||||||
|
'<form id="regexp-form" action="/"><input type="text" id="regexp-input" /></form>',
|
||||||
|
'<div id="error"></div>',
|
||||||
|
'<div><a href="#" data-glyph="link-intact"></a></div>',
|
||||||
|
'<div><a href="#" data-glyph="data-transfer-download"></a></div>',
|
||||||
|
'<div id="progress"><div></div></div>',
|
||||||
|
'<div id="regexp-render"><svg></svg></div>'
|
||||||
|
].join('');
|
||||||
|
|
||||||
|
this.regexper = new Regexper(this.root);
|
||||||
|
spyOn(this.regexper, '_setHash');
|
||||||
|
spyOn(this.regexper, '_getHash').and.returnValue('example hash value');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#keypressListener', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.event = document.createEvent('Event');
|
||||||
|
spyOn(this.event, 'preventDefault');
|
||||||
|
spyOn(this.regexper.form, 'dispatchEvent');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the shift key is not depressed', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.event.shiftKey = false;
|
||||||
|
this.event.keyCode = 13;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not prevent the default action', function() {
|
||||||
|
this.regexper.keypressListener(this.event);
|
||||||
|
expect(this.event.returnValue).not.toEqual(false);
|
||||||
|
expect(this.event.preventDefault).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not trigger a submit event', function() {
|
||||||
|
this.regexper.keypressListener(this.event);
|
||||||
|
expect(this.regexper.form.dispatchEvent).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the keyCode is not 13 (Enter)', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.event.shiftKey = true;
|
||||||
|
this.event.keyCode = 42;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not prevent the default action', function() {
|
||||||
|
this.regexper.keypressListener(this.event);
|
||||||
|
expect(this.event.returnValue).not.toEqual(false);
|
||||||
|
expect(this.event.preventDefault).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not trigger a submit event', function() {
|
||||||
|
this.regexper.keypressListener(this.event);
|
||||||
|
expect(this.regexper.form.dispatchEvent).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the shift key is depressed and the keyCode is 13 (Enter)', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.event.shiftKey = true;
|
||||||
|
this.event.keyCode = 13;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('prevents the default action', function() {
|
||||||
|
this.regexper.keypressListener(this.event);
|
||||||
|
expect(this.event.returnValue).not.toEqual(true);
|
||||||
|
expect(this.event.preventDefault).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers a submit event', function() {
|
||||||
|
var event;
|
||||||
|
|
||||||
|
this.regexper.keypressListener(this.event);
|
||||||
|
expect(this.regexper.form.dispatchEvent).toHaveBeenCalled();
|
||||||
|
|
||||||
|
event = this.regexper.form.dispatchEvent.calls.mostRecent().args[0];
|
||||||
|
expect(event.type).toEqual('submit');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#submitListener', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.event = document.createEvent('Event');
|
||||||
|
spyOn(this.event, 'preventDefault');
|
||||||
|
|
||||||
|
this.regexper.field.value = 'example value';
|
||||||
|
});
|
||||||
|
|
||||||
|
it('prevents the default action', function() {
|
||||||
|
this.regexper.submitListener(this.event);
|
||||||
|
expect(this.event.returnValue).not.toEqual(true);
|
||||||
|
expect(this.event.preventDefault).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the location.hash', function() {
|
||||||
|
this.regexper.submitListener(this.event);
|
||||||
|
expect(this.regexper._setHash).toHaveBeenCalledWith('example value');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when setting location.hash fails', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.regexper._setHash.and.throwError('hash failure');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables the permalink', function() {
|
||||||
|
this.regexper.submitListener(this.event);
|
||||||
|
expect(this.regexper.permalinkEnabled).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the expression directly', function() {
|
||||||
|
spyOn(this.regexper, 'showExpression');
|
||||||
|
this.regexper.submitListener(this.event);
|
||||||
|
expect(this.regexper.showExpression).toHaveBeenCalledWith('example value');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#hashchangeListener', function() {
|
||||||
|
|
||||||
|
it('enables the permalink', function() {
|
||||||
|
this.regexper.hashchangeListener();
|
||||||
|
expect(this.regexper.permalinkEnabled).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the expression from the hash', function() {
|
||||||
|
spyOn(this.regexper, 'showExpression');
|
||||||
|
this.regexper.hashchangeListener();
|
||||||
|
expect(this.regexper.showExpression).toHaveBeenCalledWith('example hash value');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#updatePercentage', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.event = document.createEvent('Event');
|
||||||
|
this.event.detail = { percentage: 0.42 };
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the width of the progress bar', function() {
|
||||||
|
this.regexper.updatePercentage(this.event);
|
||||||
|
expect(this.regexper.percentage.style.width).toEqual('42%');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#bindListeners', function() {
|
||||||
|
|
||||||
|
it('binds #keypressListener to keypress on the text field', function() {
|
||||||
|
spyOn(this.regexper.field, 'addEventListener');
|
||||||
|
spyOn(this.regexper, 'keypressListener');
|
||||||
|
this.regexper.bindListeners();
|
||||||
|
expect(this.regexper.field.addEventListener).toHaveBeenCalledWith('keypress', jasmine.any(Function));
|
||||||
|
|
||||||
|
this.regexper.field.addEventListener.calls.mostRecent().args[1]();
|
||||||
|
expect(this.regexper.keypressListener).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('binds #submitListener to submit on the form', function() {
|
||||||
|
spyOn(this.regexper.form, 'addEventListener');
|
||||||
|
spyOn(this.regexper, 'submitListener');
|
||||||
|
this.regexper.bindListeners();
|
||||||
|
expect(this.regexper.form.addEventListener).toHaveBeenCalledWith('submit', jasmine.any(Function));
|
||||||
|
|
||||||
|
this.regexper.form.addEventListener.calls.mostRecent().args[1]();
|
||||||
|
expect(this.regexper.submitListener).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('binds #updatePercentage to updateStatus on the root', function() {
|
||||||
|
spyOn(this.regexper.root, 'addEventListener');
|
||||||
|
spyOn(this.regexper, 'updatePercentage');
|
||||||
|
this.regexper.bindListeners();
|
||||||
|
expect(this.regexper.root.addEventListener).toHaveBeenCalledWith('updateStatus', jasmine.any(Function));
|
||||||
|
|
||||||
|
this.regexper.root.addEventListener.calls.mostRecent().args[1]();
|
||||||
|
expect(this.regexper.updatePercentage).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('binds #hashchangeListener to hashchange on the window', function() {
|
||||||
|
spyOn(window, 'addEventListener');
|
||||||
|
spyOn(this.regexper, 'hashchangeListener');
|
||||||
|
this.regexper.bindListeners();
|
||||||
|
expect(window.addEventListener).toHaveBeenCalledWith('hashchange', jasmine.any(Function));
|
||||||
|
|
||||||
|
window.addEventListener.calls.mostRecent().args[1]();
|
||||||
|
expect(this.regexper.hashchangeListener).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#showExpression', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.renderPromise = Q.defer();
|
||||||
|
spyOn(this.regexper, 'renderRegexp').and.returnValue(this.renderPromise.promise);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the text field value', function() {
|
||||||
|
this.regexper.showExpression('example expression');
|
||||||
|
expect(this.regexper.field.value).toEqual('example expression');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the expression is blank', function() {
|
||||||
|
|
||||||
|
it('clears the state', function() {
|
||||||
|
this.regexper.showExpression('');
|
||||||
|
expect(this.regexper.state).toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the expression is not blank', function() {
|
||||||
|
|
||||||
|
it('sets the state to "is-loading"', function() {
|
||||||
|
this.regexper.showExpression('example expression');
|
||||||
|
expect(this.regexper.state).toEqual('is-loading');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the expression', function() {
|
||||||
|
this.regexper.showExpression('example expression');
|
||||||
|
expect(this.regexper.renderRegexp).toHaveBeenCalledWith('example expression');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the expression finishes rendering', function() {
|
||||||
|
|
||||||
|
beforeEach(function(done) {
|
||||||
|
spyOn(this.regexper, 'updateLinks');
|
||||||
|
this.regexper.showExpression('example expression');
|
||||||
|
this.renderPromise.resolve();
|
||||||
|
setTimeout(done, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the state to "has-results"', function() {
|
||||||
|
expect(this.regexper.state).toEqual('has-results');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates the links', function() {
|
||||||
|
expect(this.regexper.updateLinks).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#updateLinks', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
spyOn(this.regexper, 'buildBlobURL');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when blob URLs are supported', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.regexper.buildBlobURL.and.returnValue('http://example.com/blob');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the download link href', function() {
|
||||||
|
this.regexper.updateLinks();
|
||||||
|
expect(this.regexper.download.href).toEqual('http://example.com/blob');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when blob URLs are not supported', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.regexper.buildBlobURL.and.throwError('blob failure');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides the download link', function() {
|
||||||
|
this.regexper.updateLinks();
|
||||||
|
expect(this.regexper.download.parentNode.style.display).toEqual('none');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the permalink is enabled', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.regexper.permalinkEnabled = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the permalink href', function() {
|
||||||
|
this.regexper.updateLinks();
|
||||||
|
expect(this.regexper.permalink.href).toEqual(location.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the permalink is disabled', function() {
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
this.regexper.permalinkEnabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides the permalink', function() {
|
||||||
|
this.regexper.updateLinks();
|
||||||
|
expect(this.regexper.permalink.parentNode.style.display).toEqual('none');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#renderRegexp', function() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -33,40 +33,25 @@ export default class Regexper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
submitListener(event) {
|
submitListener(event) {
|
||||||
event.preventDefault();
|
event.returnValue = false;
|
||||||
|
if (event.preventDefault) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.disablePermalink = false;
|
this._setHash(this.field.value);
|
||||||
location.hash = this.field.value;
|
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
// Most likely failed to set the URL has (probably because the expression
|
// Most likely failed to set the URL has (probably because the expression
|
||||||
// is too long). Turn off the permalink and just show the expression
|
// is too long). Turn off the permalink and just show the expression
|
||||||
this.disablePermalink = true;
|
this.permalinkEnabled = false;
|
||||||
this.showExpression(this.field.value);
|
this.showExpression(this.field.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hashchangeListener() {
|
hashchangeListener() {
|
||||||
var expression = decodeURIComponent(location.hash.slice(1));
|
this.permalinkEnabled = true;
|
||||||
|
this.showExpression(this._getHash());
|
||||||
this.showExpression(expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
showExpression(expression) {
|
|
||||||
this.field.value = expression;
|
|
||||||
this.state = '';
|
|
||||||
|
|
||||||
if (expression !== '') {
|
|
||||||
this.state = 'is-loading';
|
|
||||||
|
|
||||||
this.renderRegexp(expression.replace(/\n/g, '\\n'))
|
|
||||||
.then(() => {
|
|
||||||
this.state = 'has-results';
|
|
||||||
this.updateLinks();
|
|
||||||
})
|
|
||||||
.done();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePercentage(event) {
|
updatePercentage(event) {
|
||||||
@ -80,27 +65,50 @@ export default class Regexper {
|
|||||||
window.addEventListener('hashchange', this.hashchangeListener.bind(this));
|
window.addEventListener('hashchange', this.hashchangeListener.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setHash(hash) {
|
||||||
|
location.hash = encodeURIComponent(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getHash() {
|
||||||
|
return decodeURIComponent(location.hash.slice(1));
|
||||||
|
}
|
||||||
|
|
||||||
set state(state) {
|
set state(state) {
|
||||||
this.root.className = state;
|
this.root.className = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
showError(message) {
|
get state() {
|
||||||
this.state = 'has-error';
|
return this.root.className;
|
||||||
this.error.innerHTML = '';
|
}
|
||||||
this.error.appendChild(document.createTextNode(message));
|
|
||||||
|
|
||||||
throw message;
|
showExpression(expression) {
|
||||||
|
this.field.value = expression;
|
||||||
|
this.state = '';
|
||||||
|
|
||||||
|
if (expression !== '') {
|
||||||
|
this.state = 'is-loading';
|
||||||
|
|
||||||
|
this.renderRegexp(expression)
|
||||||
|
.then(() => {
|
||||||
|
this.state = 'has-results';
|
||||||
|
this.updateLinks();
|
||||||
|
})
|
||||||
|
.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildBlobURL(content) {
|
||||||
|
blob = new Blob([content], { type: 'image/svg+xml' });
|
||||||
|
window.blob = blob; // Blob object has to stick around for IE
|
||||||
|
return URL.createObjectURL(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLinks() {
|
updateLinks() {
|
||||||
var blob, url;
|
var blob, url;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
blob = new Blob([this.svg.parentNode.innerHTML], { type: 'image/svg+xml' });
|
this.download.parentNode.style.display = null;
|
||||||
url = URL.createObjectURL(blob);
|
this.download.href = this.buildBlobURL(this.svg.parentNode.innerHTML);
|
||||||
window.blob = blob; // Blob object has to stick around for IE
|
|
||||||
|
|
||||||
this.download.setAttribute('href', url);
|
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
// Blobs or URLs created from them don't work here.
|
// Blobs or URLs created from them don't work here.
|
||||||
@ -108,11 +116,11 @@ export default class Regexper {
|
|||||||
this.download.parentNode.style.display = 'none';
|
this.download.parentNode.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.disablePermalink) {
|
if (this.permalinkEnabled) {
|
||||||
this.permalink.parentNode.style.display = 'none';
|
|
||||||
} else {
|
|
||||||
this.permalink.parentNode.style.display = null;
|
this.permalink.parentNode.style.display = null;
|
||||||
this.permalink.setAttribute('href', location.toString());
|
this.permalink.href = location.toString();
|
||||||
|
} else {
|
||||||
|
this.permalink.parentNode.style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,8 +131,14 @@ export default class Regexper {
|
|||||||
|
|
||||||
parser.resetGroupCounter();
|
parser.resetGroupCounter();
|
||||||
|
|
||||||
return Q.fcall(parser.parse.bind(parser), expression)
|
return Q.fcall(parser.parse.bind(parser), expression.replace(/\n/g, '\\n'))
|
||||||
.then(null, this.showError.bind(this))
|
.then(null, message => {
|
||||||
|
this.state = 'has-error';
|
||||||
|
this.error.innerHTML = '';
|
||||||
|
this.error.appendChild(document.createTextNode(message));
|
||||||
|
|
||||||
|
throw message;
|
||||||
|
})
|
||||||
.invoke('render', snap.group())
|
.invoke('render', snap.group())
|
||||||
.then(result => {
|
.then(result => {
|
||||||
var box;
|
var box;
|
||||||
|
Loading…
Reference in New Issue
Block a user