summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/frontend/specs/automatic_reconnect.js71
-rw-r--r--tests/frontend/specs/drag_and_drop.js12
-rw-r--r--tests/frontend/specs/helper.js41
-rw-r--r--tests/frontend/specs/ordered_list.js98
-rw-r--r--tests/frontend/specs/pad_modal.js131
-rwxr-xr-xtests/frontend/travis/sauce_tunnel.sh14
6 files changed, 331 insertions, 36 deletions
diff --git a/tests/frontend/specs/automatic_reconnect.js b/tests/frontend/specs/automatic_reconnect.js
new file mode 100644
index 00000000..e2d2df36
--- /dev/null
+++ b/tests/frontend/specs/automatic_reconnect.js
@@ -0,0 +1,71 @@
+describe('Automatic pad reload on Force Reconnect message', function() {
+ var padId, $originalPadFrame;
+
+ beforeEach(function(done) {
+ padId = helper.newPad(function() {
+ // enable userdup error to have timer to force reconnect
+ var $errorMessageModal = helper.padChrome$('#connectivity .userdup');
+ $errorMessageModal.addClass('with_reconnect_timer');
+
+ // make sure there's a timeout set, otherwise automatic reconnect won't be enabled
+ helper.padChrome$.window.clientVars.automaticReconnectionTimeout = 2;
+
+ // open same pad on another iframe, to force userdup error
+ var $otherIframeWithSamePad = $('<iframe src="/p/' + padId + '" style="height: 1px;"></iframe>');
+ $originalPadFrame = $('#iframe-container iframe');
+ $otherIframeWithSamePad.insertAfter($originalPadFrame);
+
+ // wait for modal to be displayed
+ helper.waitFor(function() {
+ return $errorMessageModal.is(':visible');
+ }, 50000).done(done);
+ });
+
+ this.timeout(60000);
+ });
+
+ it('displays a count down timer to automatically reconnect', function(done) {
+ var $errorMessageModal = helper.padChrome$('#connectivity .userdup');
+ var $countDownTimer = $errorMessageModal.find('.reconnecttimer');
+
+ expect($countDownTimer.is(':visible')).to.be(true);
+
+ done();
+ });
+
+ context('and user clicks on Cancel', function() {
+ beforeEach(function() {
+ var $errorMessageModal = helper.padChrome$('#connectivity .userdup');
+ $errorMessageModal.find('#cancelreconnect').click();
+ });
+
+ it('does not show Cancel button nor timer anymore', function(done) {
+ var $errorMessageModal = helper.padChrome$('#connectivity .userdup');
+ var $countDownTimer = $errorMessageModal.find('.reconnecttimer');
+ var $cancelButton = $errorMessageModal.find('#cancelreconnect');
+
+ expect($countDownTimer.is(':visible')).to.be(false);
+ expect($cancelButton.is(':visible')).to.be(false);
+
+ done();
+ });
+ });
+
+ context('and user does not click on Cancel until timer expires', function() {
+ var padWasReloaded = false;
+
+ beforeEach(function() {
+ $originalPadFrame.one('load', function() {
+ padWasReloaded = true;
+ });
+ });
+
+ it('reloads the pad', function(done) {
+ helper.waitFor(function() {
+ return padWasReloaded;
+ }, 5000).done(done);
+
+ this.timeout(5000);
+ });
+ });
+});
diff --git a/tests/frontend/specs/drag_and_drop.js b/tests/frontend/specs/drag_and_drop.js
index bcec0bd2..821d3aac 100644
--- a/tests/frontend/specs/drag_and_drop.js
+++ b/tests/frontend/specs/drag_and_drop.js
@@ -154,7 +154,15 @@ describe('drag and drop', function() {
var $target = getLine(targetLineNumber);
$target.sendkeys('{selectall}{rightarrow}{leftarrow}');
- // insert content
- innerDocument.execCommand('insertHTML', false, draggedHtml);
+ // Insert content.
+ // Based on http://stackoverflow.com/a/6691294, to be IE-compatible
+ var range = innerDocument.getSelection().getRangeAt(0);
+ var frag = innerDocument.createDocumentFragment();
+ var el = innerDocument.createElement('div');
+ el.innerHTML = draggedHtml;
+ while (el.firstChild) {
+ frag.appendChild(el.firstChild);
+ }
+ range.insertNode(frag);
}
});
diff --git a/tests/frontend/specs/helper.js b/tests/frontend/specs/helper.js
index bb47f4dc..8520769a 100644
--- a/tests/frontend/specs/helper.js
+++ b/tests/frontend/specs/helper.js
@@ -101,20 +101,21 @@ describe("the test helper", function(){
// function to support tests, use a single way to represent whitespaces
var cleanText = function(text){
return text
- .replace(/\n/gi, "\\\\n") // avoid \n to be replaced by \s on next line
- .replace(/\s/gi, " ")
- .replace(/\\\\n/gi, "\n"); // move back \n to its original state
+ // IE replaces line breaks with a whitespace, so we need to unify its behavior
+ // for other browsers, to have all tests running for all browsers
+ .replace(/\n/gi, "")
+ .replace(/\s/gi, " ");
}
before(function(done){
helper.newPad(function() {
// create some lines to be used on the tests
var $firstLine = helper.padInner$("div").first();
- $firstLine.sendkeys("{selectall}some{enter}short{enter}lines{enter}to test{enter}");
+ $firstLine.sendkeys("{selectall}some{enter}short{enter}lines{enter}to test{enter}{enter}");
// wait for lines to be split
helper.waitFor(function(){
- var $fourthLine = helper.padInner$("div").slice(3,4);
+ var $fourthLine = helper.padInner$("div").eq(3);
return $fourthLine.text() === "to test";
}).done(done);
});
@@ -129,13 +130,13 @@ describe("the test helper", function(){
var endOffset = 4;
var $lines = inner$("div");
- var $startLine = $lines.slice(1,2);
- var $endLine = $lines.slice(3,4);
+ var $startLine = $lines.eq(1);
+ var $endLine = $lines.eq(3);
helper.selectLines($startLine, $endLine, startOffset, endOffset);
var selection = inner$.document.getSelection();
- expect(cleanText(selection.toString())).to.be("ort \nlines \nto t");
+ expect(cleanText(selection.toString())).to.be("ort lines to t");
done();
});
@@ -147,13 +148,13 @@ describe("the test helper", function(){
var endOffset = 1;
var $lines = inner$("div");
- var $startLine = $lines.slice(1,2);
- var $endLine = $lines.slice(4,5);
+ var $startLine = $lines.eq(1);
+ var $endLine = $lines.eq(4);
helper.selectLines($startLine, $endLine, startOffset, endOffset);
var selection = inner$.document.getSelection();
- expect(cleanText(selection.toString())).to.be("ort \nlines \nto test\n");
+ expect(cleanText(selection.toString())).to.be("ort lines to test");
done();
});
@@ -165,13 +166,13 @@ describe("the test helper", function(){
var endOffset = 0;
var $lines = inner$("div");
- var $startLine = $lines.slice(1,2);
- var $endLine = $lines.slice(3,4);
+ var $startLine = $lines.eq(1);
+ var $endLine = $lines.eq(3);
helper.selectLines($startLine, $endLine, startOffset, endOffset);
var selection = inner$.document.getSelection();
- expect(cleanText(selection.toString())).to.be("ort \nlines \n");
+ expect(cleanText(selection.toString())).to.be("ort lines ");
done();
});
@@ -183,13 +184,13 @@ describe("the test helper", function(){
var endOffset = 50;
var $lines = inner$("div");
- var $startLine = $lines.slice(1,2);
- var $endLine = $lines.slice(3,4);
+ var $startLine = $lines.eq(1);
+ var $endLine = $lines.eq(3);
helper.selectLines($startLine, $endLine, startOffset, endOffset);
var selection = inner$.document.getSelection();
- expect(cleanText(selection.toString())).to.be("ort \nlines \nto test");
+ expect(cleanText(selection.toString())).to.be("ort lines to test");
done();
});
@@ -198,13 +199,13 @@ describe("the test helper", function(){
var inner$ = helper.padInner$;
var $lines = inner$("div");
- var $startLine = $lines.slice(1,2);
- var $endLine = $lines.slice(3,4);
+ var $startLine = $lines.eq(1);
+ var $endLine = $lines.eq(3);
helper.selectLines($startLine, $endLine);
var selection = inner$.document.getSelection();
- expect(cleanText(selection.toString())).to.be("short \nlines \nto test");
+ expect(cleanText(selection.toString())).to.be("short lines to test");
done();
});
diff --git a/tests/frontend/specs/ordered_list.js b/tests/frontend/specs/ordered_list.js
index ca7d755e..57196fef 100644
--- a/tests/frontend/specs/ordered_list.js
+++ b/tests/frontend/specs/ordered_list.js
@@ -5,8 +5,8 @@ describe("assign ordered list", function(){
this.timeout(60000);
});
- it("insert ordered list text", function(done){
- var inner$ = helper.padInner$;
+ it("inserts ordered list text", function(done){
+ var inner$ = helper.padInner$;
var chrome$ = helper.padChrome$;
var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist");
@@ -17,8 +17,72 @@ describe("assign ordered list", function(){
}).done(done);
});
+ context('when user presses Ctrl+Shift+N', function() {
+ context('and pad shortcut is enabled', function() {
+ beforeEach(function() {
+ makeSureShortcutIsEnabled('cmdShiftN');
+ triggerCtrlShiftShortcut('N');
+ });
+
+ it('inserts unordered list', function(done) {
+ helper.waitFor(function() {
+ return helper.padInner$('div').first().find('ol li').length === 1;
+ }).done(done);
+ });
+ });
+
+ context('and pad shortcut is disabled', function() {
+ beforeEach(function() {
+ makeSureShortcutIsDisabled('cmdShiftN');
+ triggerCtrlShiftShortcut('N');
+ });
+
+ it('does not insert unordered list', function(done) {
+ helper.waitFor(function() {
+ return helper.padInner$('div').first().find('ol li').length === 1;
+ }).done(function() {
+ expect().fail(function() { return 'Unordered list inserted, should ignore shortcut' });
+ }).fail(function() {
+ done();
+ });
+ });
+ });
+ });
+
+ context('when user presses Ctrl+Shift+1', function() {
+ context('and pad shortcut is enabled', function() {
+ beforeEach(function() {
+ makeSureShortcutIsEnabled('cmdShift1');
+ triggerCtrlShiftShortcut('1');
+ });
+
+ it('inserts unordered list', function(done) {
+ helper.waitFor(function() {
+ return helper.padInner$('div').first().find('ol li').length === 1;
+ }).done(done);
+ });
+ });
+
+ context('and pad shortcut is disabled', function() {
+ beforeEach(function() {
+ makeSureShortcutIsDisabled('cmdShift1');
+ triggerCtrlShiftShortcut('1');
+ });
+
+ it('does not insert unordered list', function(done) {
+ helper.waitFor(function() {
+ return helper.padInner$('div').first().find('ol li').length === 1;
+ }).done(function() {
+ expect().fail(function() { return 'Unordered list inserted, should ignore shortcut' });
+ }).fail(function() {
+ done();
+ });
+ });
+ });
+ });
+
xit("issue #1125 keeps the numbered list on enter for the new line - EMULATES PASTING INTO A PAD", function(done){
- var inner$ = helper.padInner$;
+ var inner$ = helper.padInner$;
var chrome$ = helper.padChrome$;
var $insertorderedlistButton = chrome$(".buttonicon-insertorderedlist");
@@ -26,9 +90,9 @@ describe("assign ordered list", function(){
//type a bit, make a line break and type again
var $firstTextElement = inner$("div span").first();
- $firstTextElement.sendkeys('line 1');
- $firstTextElement.sendkeys('{enter}');
- $firstTextElement.sendkeys('line 2');
+ $firstTextElement.sendkeys('line 1');
+ $firstTextElement.sendkeys('{enter}');
+ $firstTextElement.sendkeys('line 2');
$firstTextElement.sendkeys('{enter}');
helper.waitFor(function(){
@@ -44,4 +108,26 @@ describe("assign ordered list", function(){
done();
});
});
+
+ var triggerCtrlShiftShortcut = function(shortcutChar) {
+ var inner$ = helper.padInner$;
+ if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE) { // if it's a mozilla or IE
+ var evtType = "keypress";
+ }else{
+ var evtType = "keydown";
+ }
+ var e = inner$.Event(evtType);
+ e.ctrlKey = true;
+ e.shiftKey = true;
+ e.which = shortcutChar.toString().charCodeAt(0);
+ inner$("#innerdocbody").trigger(e);
+ }
+
+ var makeSureShortcutIsDisabled = function(shortcut) {
+ helper.padChrome$.window.clientVars.padShortcutEnabled[shortcut] = false;
+ }
+ var makeSureShortcutIsEnabled = function(shortcut) {
+ helper.padChrome$.window.clientVars.padShortcutEnabled[shortcut] = true;
+ }
+
});
diff --git a/tests/frontend/specs/pad_modal.js b/tests/frontend/specs/pad_modal.js
new file mode 100644
index 00000000..80752e4b
--- /dev/null
+++ b/tests/frontend/specs/pad_modal.js
@@ -0,0 +1,131 @@
+describe('Pad modal', function() {
+ context('when modal is a "force reconnect" message', function() {
+ var MODAL_SELECTOR = '#connectivity .slowcommit';
+
+ beforeEach(function(done) {
+ helper.newPad(function() {
+ // force a "slowcommit" error
+ helper.padChrome$.window.pad.handleChannelStateChange('DISCONNECTED', 'slowcommit');
+
+ // wait for modal to be displayed
+ var $modal = helper.padChrome$(MODAL_SELECTOR);
+ helper.waitFor(function() {
+ return $modal.is(':visible');
+ }, 50000).done(done);
+ });
+
+ this.timeout(60000);
+ });
+
+ it('disables editor', function(done) {
+ expect(isEditorDisabled()).to.be(true);
+
+ done();
+ });
+
+ context('and user clicks on editor', function() {
+ beforeEach(function() {
+ clickOnPadInner();
+ });
+
+ it('does not close the modal', function(done) {
+ var $modal = helper.padChrome$(MODAL_SELECTOR);
+ var modalIsVisible = $modal.is(':visible');
+
+ expect(modalIsVisible).to.be(true);
+
+ done();
+ });
+ });
+
+ context('and user clicks on pad outer', function() {
+ beforeEach(function() {
+ clickOnPadOuter();
+ });
+
+ it('does not close the modal', function(done) {
+ var $modal = helper.padChrome$(MODAL_SELECTOR);
+ var modalIsVisible = $modal.is(':visible');
+
+ expect(modalIsVisible).to.be(true);
+
+ done();
+ });
+ });
+ });
+
+ // we use "settings" here, but other modals have the same behaviour
+ context('when modal is not an error message', function() {
+ var MODAL_SELECTOR = '#settings';
+
+ beforeEach(function(done) {
+ helper.newPad(function() {
+ openSettingsAndWaitForModalToBeVisible(done);
+ });
+
+ this.timeout(60000);
+ });
+
+ it('does not disable editor', function(done) {
+ expect(isEditorDisabled()).to.be(false);
+ done();
+ });
+
+ context('and user clicks on editor', function() {
+ beforeEach(function() {
+ clickOnPadInner();
+ });
+
+ it('closes the modal', function(done) {
+ expect(isModalOpened(MODAL_SELECTOR)).to.be(false);
+ done();
+ });
+ });
+
+ context('and user clicks on pad outer', function() {
+ beforeEach(function() {
+ clickOnPadOuter();
+ });
+
+ it('closes the modal', function(done) {
+ expect(isModalOpened(MODAL_SELECTOR)).to.be(false);
+ done();
+ });
+ });
+ });
+
+ var clickOnPadInner = function() {
+ var $editor = helper.padInner$('#innerdocbody');
+ $editor.click();
+ }
+
+ var clickOnPadOuter = function() {
+ var $lineNumbersColumn = helper.padOuter$('#sidedivinner');
+ $lineNumbersColumn.click();
+ }
+
+ var openSettingsAndWaitForModalToBeVisible = function(done) {
+ helper.padChrome$('.buttonicon-settings').click();
+
+ // wait for modal to be displayed
+ var modalSelector = '#settings';
+ helper.waitFor(function() {
+ return isModalOpened(modalSelector);
+ }, 10000).done(done);
+ }
+
+ var isEditorDisabled = function() {
+ var editorDocument = helper.padOuter$("iframe[name='ace_inner']").get(0).contentDocument;
+ var editorBody = editorDocument.getElementById('innerdocbody');
+
+ var editorIsDisabled = editorBody.contentEditable === 'false' // IE/Safari
+ || editorDocument.designMode === 'off'; // other browsers
+
+ return editorIsDisabled;
+ }
+
+ var isModalOpened = function(modalSelector) {
+ var $modal = helper.padChrome$(modalSelector);
+ return $modal.is(':visible');
+ }
+});
diff --git a/tests/frontend/travis/sauce_tunnel.sh b/tests/frontend/travis/sauce_tunnel.sh
index f519f8d9..b19268d0 100755
--- a/tests/frontend/travis/sauce_tunnel.sh
+++ b/tests/frontend/travis/sauce_tunnel.sh
@@ -1,16 +1,14 @@
#!/bin/bash
# download and unzip the sauce connector
-curl http://saucelabs.com/downloads/Sauce-Connect-latest.zip > /tmp/sauce.zip
-unzip /tmp/sauce.zip -d /tmp
+curl https://saucelabs.com/downloads/sc-latest-linux.tar.gz > /tmp/sauce.tar.gz
+tar zxf /tmp/sauce.tar.gz --directory /tmp
+mv /tmp/sc-*-linux /tmp/sauce_connect
# start the sauce connector in background and make sure it doesn't output the secret key
-(java -jar /tmp/Sauce-Connect.jar $SAUCE_USERNAME $SAUCE_ACCESS_KEY -f /tmp/tunnel > /dev/null )&
-
-# save the sauce pid in a file
-echo $! > /tmp/sauce.pid
+(/tmp/sauce_connect/bin/sc --user $SAUCE_USERNAME --key $SAUCE_ACCESS_KEY --pidfile /tmp/sauce.pid --readyfile /tmp/tunnel > /dev/null )&
# wait for the tunnel to build up
while [ ! -e "/tmp/tunnel" ]
do
- sleep 1
-done \ No newline at end of file
+ sleep 1
+done