mirror of
https://github.com/darkwire/darkwire.io.git
synced 2025-07-18 02:44:01 +00:00
Better sanitation of chat messages, support for multiline messages, updated username change method
This commit is contained in:
parent
383999b766
commit
57cef2f44f
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
npm-debug.log
|
||||
src/public/main.js
|
||||
|
@ -20,6 +20,6 @@ before_script:
|
||||
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16"
|
||||
- sleep 5 # give xvfb some time to start
|
||||
- gulp bundle
|
||||
- node index.js &
|
||||
- npm start &
|
||||
- sleep 5
|
||||
script: node_modules/mocha/bin/mocha test/unit --compilers js:babel-core/register && node_modules/nightwatch/bin/nightwatch --test test/acceptance/index.js --config test/acceptance/nightwatch.json -e chrome
|
||||
script: npm run test-travis
|
||||
|
@ -62,7 +62,7 @@ gulp.task('test', function() {
|
||||
|
||||
let acceptanceTest = spawn(
|
||||
'node_modules/nightwatch/bin/nightwatch',
|
||||
['--test', 'test/acceptance/index.js', '--config', 'test/acceptance/nightwatch.json'],
|
||||
['--test', 'test/acceptance/index.js', '--config', 'test/acceptance/nightwatch-local.json'],
|
||||
{stdio: 'inherit'}
|
||||
);
|
||||
|
||||
|
10
package.json
10
package.json
@ -12,6 +12,7 @@
|
||||
"forever": "^0.15.1",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-uglify": "^1.5.1",
|
||||
"he": "^0.5.0",
|
||||
"moment": "^2.11.2",
|
||||
"mustache-express": "^1.2.2",
|
||||
"sanitize-html": "^1.11.3",
|
||||
@ -39,13 +40,10 @@
|
||||
"vinyl-source-stream": "^1.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "gulp start",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "gulp start",
|
||||
"start": "npm run bundle && gulp start",
|
||||
"bundle": "gulp bundle",
|
||||
"test": "gulp test"
|
||||
"test": "npm run bundle && gulp test",
|
||||
"test-travis": "node_modules/mocha/bin/mocha test/unit --compilers js:babel-core/register && node_modules/nightwatch/bin/nightwatch --test test/acceptance/index.js --config test/acceptance/nightwatch.json -e chrome"
|
||||
},
|
||||
"author": "Daniel Seripap",
|
||||
"license": "MIT"
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Darkwire.io
|
||||
|
||||
[](https://travis-ci.org/seripap/darkwire.io) []()
|
||||
|
||||
Simple encrypted web chat. Powered by [socket.io](http://socket.io) and the [web cryptography API](https://developer.mozilla.org/en-US/docs/Web/API/Window/crypto).
|
||||
|
||||
### Installation
|
||||
@ -10,11 +12,12 @@ Simple encrypted web chat. Powered by [socket.io](http://socket.io) and the [web
|
||||
|
||||
# Bundle JS files (for deployment)
|
||||
npm bundle
|
||||
# Start a local instance of darkwire
|
||||
# Running tests locally
|
||||
brew install chromedriver # Installs chromedriver to /usr/local/bin
|
||||
npm test
|
||||
# Start a local instance of darkwire / for dev
|
||||
npm start
|
||||
|
||||
Create a **.secret** file in the **/src** folder with a your session secret. It doesn't matter what it is- just keep it private.
|
||||
|
||||
Darkwire is now running on `http://localhost:3000`
|
||||
|
||||
### Deployment
|
||||
|
@ -1,5 +1,6 @@
|
||||
import _ from 'underscore';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import he from 'he';
|
||||
|
||||
export default class Chat {
|
||||
constructor(darkwire, socket) {
|
||||
@ -172,11 +173,10 @@ export default class Chat {
|
||||
return this.log('Username must start with a letter or number.', {error: true});
|
||||
}
|
||||
|
||||
this.darkwire.updateUsername(newUsername).then((socketData) => {
|
||||
this.darkwire.updateUsername(window.username, newUsername).then((socketData) => {
|
||||
let modifiedSocketData = {
|
||||
username: window.username,
|
||||
newUsername: socketData.username,
|
||||
publicKey: socketData.publicKey
|
||||
newUsername: socketData.username
|
||||
};
|
||||
|
||||
this.socket.emit('update user', modifiedSocketData);
|
||||
@ -302,7 +302,10 @@ export default class Chat {
|
||||
if (messageType === 'action') {
|
||||
$usernameDiv.css('color','').prepend('*');
|
||||
}
|
||||
$messageBodyDiv.html(unescape(data.message));
|
||||
let unescapedMessage = unescape(data.message);
|
||||
let lineBreaks = /<br \/>/g;
|
||||
unescapedMessage = unescapedMessage.replace(lineBreaks, '<br />');
|
||||
$messageBodyDiv.html(unescapedMessage);
|
||||
} else {
|
||||
$messageBodyDiv.html(this.darkwire.addFileToQueue(data));
|
||||
}
|
||||
|
@ -51,12 +51,35 @@ export default class Darkwire {
|
||||
return this._connected;
|
||||
}
|
||||
|
||||
get audio() {
|
||||
return this._audio;
|
||||
}
|
||||
|
||||
get users() {
|
||||
return this._users;
|
||||
}
|
||||
|
||||
get audio() {
|
||||
return this._audio;
|
||||
getUserById(id) {
|
||||
return _.findWhere(this._users, {id: id});
|
||||
}
|
||||
|
||||
getUserByName(username) {
|
||||
return _.findWhere(this._users, {username: username});
|
||||
}
|
||||
|
||||
updateUser(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let user = this.getUserById(data.id);
|
||||
|
||||
if (!user) {
|
||||
return reject();
|
||||
}
|
||||
|
||||
let oldUsername = user.username;
|
||||
|
||||
user.username = data.username;
|
||||
resolve(oldUsername);
|
||||
});
|
||||
}
|
||||
|
||||
addUser(data) {
|
||||
@ -97,27 +120,40 @@ export default class Darkwire {
|
||||
return this._users;
|
||||
}
|
||||
|
||||
updateUsername(username) {
|
||||
updateUsername(username, newUsername) {
|
||||
let user = null;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (newUsername) {
|
||||
user = this.getUserByName(username);
|
||||
}
|
||||
|
||||
if (username) {
|
||||
Promise.all([
|
||||
this._cryptoUtil.createPrimaryKeys()
|
||||
])
|
||||
.then((data) => {
|
||||
this._keys = {
|
||||
public: data[0].publicKey,
|
||||
private: data[0].privateKey
|
||||
};
|
||||
return Promise.all([
|
||||
this._cryptoUtil.exportKey(data[0].publicKey, 'spki')
|
||||
]);
|
||||
})
|
||||
.then((exportedKeys) => {
|
||||
resolve({
|
||||
username: username,
|
||||
publicKey: exportedKeys[0]
|
||||
if (!user) {
|
||||
Promise.all([
|
||||
this._cryptoUtil.createPrimaryKeys()
|
||||
])
|
||||
.then((data) => {
|
||||
this._keys = {
|
||||
public: data[0].publicKey,
|
||||
private: data[0].privateKey
|
||||
};
|
||||
return Promise.all([
|
||||
this._cryptoUtil.exportKey(data[0].publicKey, 'spki')
|
||||
]);
|
||||
})
|
||||
.then((exportedKeys) => {
|
||||
resolve({
|
||||
username: username,
|
||||
publicKey: exportedKeys[0]
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
username: newUsername,
|
||||
publicKey: user.publicKey
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import CryptoUtil from './crypto';
|
||||
import Chat from './chat';
|
||||
import moment from 'moment';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import he from 'he';
|
||||
|
||||
let fs = window.RequestFileSystem || window.webkitRequestFileSystem;
|
||||
|
||||
@ -61,25 +62,21 @@ $(function() {
|
||||
|
||||
// Prevents input from having injected markup
|
||||
function cleanInput(input) {
|
||||
let message = sanitizeHtml(_.escape(input), {
|
||||
allowedTags: ['b', 'i', 'em', 'strong', 'a'],
|
||||
allowedAttributes: {
|
||||
'a': ['href']
|
||||
}
|
||||
});
|
||||
// let message = $('<div/>').html(input).text();
|
||||
message = Autolinker.link(message);
|
||||
return _.escape(message);
|
||||
input = input.replace(/\r?\n/g, '<br />');
|
||||
let sanitized = he.encode(input);
|
||||
sanitized = Autolinker.link(sanitized);
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
// Keyboard events
|
||||
|
||||
$window.keydown(function(event) {
|
||||
// When the client hits ENTER on their keyboard and chat message input is focused
|
||||
if (event.which === 13 && $('.inputMessage').is(':focus')) {
|
||||
if (event.which === 13 && !event.shiftKey && $('.inputMessage').is(':focus')) {
|
||||
handleMessageSending();
|
||||
socket.emit('stop typing');
|
||||
chat.typing = false;
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
});
|
||||
@ -107,7 +104,10 @@ $(function() {
|
||||
});
|
||||
|
||||
socket.on('user update', (data) => {
|
||||
updateUser(data);
|
||||
darkwire.updateUser(data).then((oldUsername) => {
|
||||
chat.log(oldUsername + ' changed name to ' + data.username);
|
||||
renderParticipantsList();
|
||||
});
|
||||
});
|
||||
|
||||
// Whenever the server emits 'new message', update the chat body
|
||||
@ -227,20 +227,6 @@ $(function() {
|
||||
});
|
||||
}
|
||||
|
||||
function updateUser(data) {
|
||||
let logMessage = data.username + ' changed name to ';
|
||||
darkwire.removeUser(data);
|
||||
|
||||
data.username = data.newUsername;
|
||||
logMessage += data.username;
|
||||
let importKeysPromises = darkwire.addUser(data);
|
||||
Promise.all(importKeysPromises).then(() => {
|
||||
chat.log(logMessage);
|
||||
renderParticipantsList();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
window.triggerFileTransfer = function(context) {
|
||||
const fileId = context.getAttribute('data-file');
|
||||
if (fileId) {
|
||||
|
@ -31,7 +31,6 @@ export default class WindowHandler {
|
||||
|
||||
enableFileTransfer() {
|
||||
if (this.fileHandler.isSupported) {
|
||||
console.log('enabled');
|
||||
$('#send-file').click((e) => {
|
||||
e.preventDefault();
|
||||
$('#fileInput').trigger('click');
|
||||
|
@ -9,7 +9,7 @@ html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
html, body, input {
|
||||
html, body, input, textarea {
|
||||
font-family:
|
||||
"SourceCodePro-Regular",
|
||||
"HelveticaNeue-Light",
|
||||
@ -160,6 +160,10 @@ input {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.log {
|
||||
color: gray;
|
||||
font-size: 70%;
|
||||
@ -196,19 +200,24 @@ input {
|
||||
|
||||
/* Input */
|
||||
|
||||
.inputContainer {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.inputMessage{
|
||||
background: black !important;
|
||||
color: white !important;
|
||||
border: none;
|
||||
border-top: 1px solid #282828;
|
||||
bottom: 0;
|
||||
height: 60px;
|
||||
left: 0;
|
||||
outline: none;
|
||||
padding-left: 10px;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
padding: 10px 75px 10px 10px;
|
||||
/*Fix for inner shadow on iOS*/
|
||||
-webkit-appearance: none;
|
||||
border-radius: 0px;
|
||||
@ -218,7 +227,7 @@ input {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
padding: 15px;
|
||||
padding: 22px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
76
src/public/vendor/autogrow.js
vendored
Normal file
76
src/public/vendor/autogrow.js
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
(function($)
|
||||
{
|
||||
/**
|
||||
* Auto-growing textareas; technique ripped from Facebook
|
||||
*
|
||||
*
|
||||
* http://github.com/jaz303/jquery-grab-bag/tree/master/javascripts/jquery.autogrow-textarea.js
|
||||
*/
|
||||
$.fn.autogrow = function(options)
|
||||
{
|
||||
return this.filter('textarea').each(function()
|
||||
{
|
||||
var self = this;
|
||||
var $self = $(self);
|
||||
var minHeight = $self.height();
|
||||
var noFlickerPad = $self.hasClass('autogrow-short') ? 0 : parseInt($self.css('lineHeight')) || 0;
|
||||
var settings = $.extend({
|
||||
preGrowCallback: null,
|
||||
postGrowCallback: null
|
||||
}, options );
|
||||
|
||||
var shadow = $('<div></div>').css({
|
||||
position: 'absolute',
|
||||
top: -10000,
|
||||
left: -10000,
|
||||
width: $self.width(),
|
||||
fontSize: $self.css('fontSize'),
|
||||
fontFamily: $self.css('fontFamily'),
|
||||
fontWeight: $self.css('fontWeight'),
|
||||
lineHeight: $self.css('lineHeight'),
|
||||
resize: 'none',
|
||||
'word-wrap': 'break-word'
|
||||
}).appendTo(document.body);
|
||||
|
||||
var update = function(event)
|
||||
{
|
||||
var times = function(string, number)
|
||||
{
|
||||
for (var i=0, r=''; i<number; i++) r += string;
|
||||
return r;
|
||||
};
|
||||
|
||||
var val = self.value.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/\n$/, '<br/> ')
|
||||
.replace(/\n/g, '<br/>')
|
||||
.replace(/ {2,}/g, function(space){ return times(' ', space.length - 1) + ' ' });
|
||||
|
||||
// Did enter get pressed? Resize in this keydown event so that the flicker doesn't occur.
|
||||
if (event && event.data && event.data.event === 'keydown' && event.keyCode === 13) {
|
||||
val += '<br />';
|
||||
}
|
||||
|
||||
shadow.css('width', $self.width());
|
||||
shadow.html(val + (noFlickerPad === 0 ? '...' : '')); // Append '...' to resize pre-emptively.
|
||||
|
||||
var newHeight=Math.max(shadow.height() + noFlickerPad, minHeight);
|
||||
if(settings.preGrowCallback!=null){
|
||||
newHeight=settings.preGrowCallback($self,shadow,newHeight,minHeight);
|
||||
}
|
||||
|
||||
$self.height(newHeight);
|
||||
|
||||
if(settings.postGrowCallback!=null){
|
||||
settings.postGrowCallback($self);
|
||||
}
|
||||
}
|
||||
|
||||
$self.change(update).keyup(update).keydown({event:'keydown'},update);
|
||||
$(window).resize(update);
|
||||
|
||||
update();
|
||||
});
|
||||
};
|
||||
})(jQuery);
|
33
src/room.js
33
src/room.js
@ -93,27 +93,22 @@ class Room {
|
||||
if (data.newUsername.length > 16) {
|
||||
return false;
|
||||
}
|
||||
this.users = _.without(this.users, socket.user);
|
||||
let modifiedUser = {
|
||||
id: socket.user.id,
|
||||
username: data.newUsername,
|
||||
publicKey: data.publicKey
|
||||
};
|
||||
|
||||
this.users.push(modifiedUser);
|
||||
|
||||
socket.username = data.newUsername;
|
||||
socket.user = modifiedUser;
|
||||
|
||||
thisIO.emit('user update', {
|
||||
id: socket.user.id,
|
||||
username: data.username,
|
||||
newUsername: data.newUsername,
|
||||
publicKey: data.publicKey,
|
||||
users: this.users,
|
||||
timestamp: new Date()
|
||||
let user = _.find(this.users, (users) => {
|
||||
return users === socket.user;
|
||||
});
|
||||
|
||||
if (user) {
|
||||
user.username = data.newUsername;
|
||||
socket.username = user.username;
|
||||
socket.user = user;
|
||||
|
||||
thisIO.emit('user update', {
|
||||
username: socket.username,
|
||||
id: socket.user.id,
|
||||
timestamp: new Date()
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -53,11 +53,13 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<input class="inputMessage" placeholder="Type here..."/>
|
||||
<div id="input-icons">
|
||||
<span class="glyphicon glyphicon-file" id="send-file"></span>
|
||||
<input type="file" id="fileInput">
|
||||
<span class="glyphicon glyphicon-send" id="send-message-btn" aria-hidden="true"></span>
|
||||
<div class="inputContainer">
|
||||
<textarea class="inputMessage" placeholder="Type here..."/></textarea>
|
||||
<div id="input-icons">
|
||||
<span class="glyphicon glyphicon-file" id="send-file"></span>
|
||||
<input type="file" name="fileUploader" id="fileInput">
|
||||
<span class="glyphicon glyphicon-send" id="send-message-btn" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -173,6 +175,7 @@
|
||||
<script src="/vendor/bootstrap-switch.min.js"></script>
|
||||
<script src="/vendor/web-crypto-shim.js"></script>
|
||||
<script src="/vendor/fastclick-1.0.6.min.js"></script>
|
||||
<script src="/vendor/autogrow.js"></script>
|
||||
<script src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,7 +1,11 @@
|
||||
/*jshint -W030 */
|
||||
import App from '../../package.json';
|
||||
|
||||
describe('Darkwire', () => {
|
||||
|
||||
describe('starting a room', () => {
|
||||
describe('Creating a room', () => {
|
||||
|
||||
var testingRoom = null;
|
||||
let browser;
|
||||
|
||||
before((client, done) => {
|
||||
@ -25,31 +29,31 @@ describe('Darkwire', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
it('should show welcome modal', () => {
|
||||
it('Should show welcome modal', () => {
|
||||
browser
|
||||
.waitForElementVisible('#first-modal', 5000)
|
||||
.assert.containsText('#first-modal .modal-title', 'Welcome to darkwire.io');
|
||||
.expect.element('#first-modal').to.be.visible;
|
||||
});
|
||||
|
||||
it('should have correct header', () => {
|
||||
browser.expect.element('#first-modal .modal-title').text.to.equal('Welcome to darkwire.io');
|
||||
it('Should be started with NPM', () => {
|
||||
browser.expect.element('#first-modal .modal-title').text.to.equal('Welcome to darkwire.io v' + App.version);
|
||||
});
|
||||
|
||||
describe('opening a second window', () => {
|
||||
describe('Joining chat room', () => {
|
||||
|
||||
before((client, done) => {
|
||||
browser.url((result) => {
|
||||
let urlSplit = result.value.split('/');
|
||||
let roomId = urlSplit[urlSplit.length - 1];
|
||||
let url = 'http://localhost:3000/' + roomId;
|
||||
testingRoom = urlSplit[urlSplit.length - 1];
|
||||
let url = 'http://localhost:3000/' + testingRoom;
|
||||
browser.execute(() => {
|
||||
window.open('http://localhost:3000/', '_blank');
|
||||
}, [], () => {
|
||||
browser.window_handles((result) => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[1], () => {
|
||||
browser.execute((id) => {
|
||||
window.open('http://localhost:3000/' + id, '_self');
|
||||
}, [roomId], () => {
|
||||
}, [testingRoom], () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -58,25 +62,26 @@ describe('Darkwire', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should not show welcome modal', () => {
|
||||
it('Should not show welcome modal', () => {
|
||||
browser.assert.hidden('#first-modal');
|
||||
});
|
||||
|
||||
describe('sending messages', () => {
|
||||
describe('Sending chat message', () => {
|
||||
|
||||
before((client, done) => {
|
||||
browser.waitForElementPresent('ul.users li:nth-child(2)', 5000, () => {
|
||||
browser.setValue('input.inputMessage', ['Hello world', browser.Keys.RETURN], () => {
|
||||
browser.setValue('textarea.inputMessage', ['Hello world!', browser.Keys.RETURN], () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should work', () => {
|
||||
browser.window_handles((result) => {
|
||||
it('Should send a message', () => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[0], () => {
|
||||
browser.waitForElementPresent('span.messageBody', 5000, () => {
|
||||
browser.assert.containsText('span.messageBody', 'Hello world');
|
||||
browser.pause(2000);
|
||||
browser.assert.containsText('span.messageBody', 'Hello world!');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -86,5 +91,129 @@ describe('Darkwire', () => {
|
||||
|
||||
});
|
||||
|
||||
describe('Slash Commands', () => {
|
||||
|
||||
before((client, done) => {
|
||||
let url = 'http://localhost:3000/' + testingRoom;
|
||||
browser.url(url, () => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[0], () => {
|
||||
browser.execute((id) => {
|
||||
window.open('http://localhost:3000/' + id, '_self');
|
||||
}, [testingRoom], () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('/me', () => {
|
||||
|
||||
before((client, done) => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[0], () => {
|
||||
browser.waitForElementPresent('ul.users li:nth-child(2)', 5000, () => {
|
||||
browser.setValue('textarea.inputMessage', ['/me is no stranger to love', browser.Keys.RETURN], () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should express an interactive action', () => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[0], () => {
|
||||
browser.waitForElementPresent('span.messageBody', 5000, () => {
|
||||
browser.pause(5000);
|
||||
browser.assert.containsText('.action span.messageBody', 'is no stranger to love');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('/nick', () => {
|
||||
|
||||
before((client, done) => {
|
||||
browser.url('http://localhost:3000/' + testingRoom, () => {
|
||||
browser.waitForElementPresent('ul.users li:nth-child(2)', 5000, () => {
|
||||
browser.setValue('textarea.inputMessage', ['/nick rickAnsley', browser.Keys.RETURN], () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should change username', () => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[3], () => {
|
||||
browser.pause(5000);
|
||||
browser.assert.containsText('.log:last-child', 'rickAnsley');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Before file transfer: Image: Confirm sending', () => {
|
||||
|
||||
before((client, done) => {
|
||||
let url = 'http://localhost:3000/' + testingRoom;
|
||||
browser.url(url, () => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[0], () => {
|
||||
browser.execute((id) => {
|
||||
window.open('http://localhost:3000/' + id, '_self');
|
||||
}, [testingRoom], () => {
|
||||
browser.waitForElementPresent('#send-file', 5000, () => {
|
||||
browser.execute(() => {
|
||||
$('input[name="fileUploader"]').show();
|
||||
}, [], () => {
|
||||
browser.waitForElementPresent('input[name="fileUploader"]', 5000, () => {
|
||||
let testFile = __dirname + '/ricky.jpg';
|
||||
browser.setValue('input[name="fileUploader"]', testFile, (result) => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should prompt user confirmation', () => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[0], () => {
|
||||
browser.waitForElementPresent('span.messageBody', 5000, () => {
|
||||
browser.pause(5000);
|
||||
browser.assert.containsText('span.messageBody', 'You are about to send ricky.jpg to all parties in this chat. Confirm | Cancel');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should show sent confirmation message', () => {
|
||||
browser.windowHandles((result) => {
|
||||
browser.switchWindow(result.value[0], () => {
|
||||
browser.waitForElementPresent('span.messageBody a:first-child', 5000, () => {
|
||||
browser.click('span.messageBody a:first-child', () => {
|
||||
browser.waitForElementNotPresent('span.messageBody a:first-child', 5000, () => {
|
||||
browser.assert.containsText('span.messageBody', 'Sent ricky.jpg');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
1
test/acceptance/fileUtility.js
Normal file
1
test/acceptance/fileUtility.js
Normal file
@ -0,0 +1 @@
|
||||
($('#fileInput').show)();
|
52
test/acceptance/nightwatch-local.json
Normal file
52
test/acceptance/nightwatch-local.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"src_folders" : ["test"],
|
||||
"output_folder" : "reports",
|
||||
"custom_commands_path" : "",
|
||||
"custom_assertions_path" : "",
|
||||
"page_objects_path" : "",
|
||||
"globals_path" : "",
|
||||
"test_runner" : "mocha",
|
||||
"selenium" : {
|
||||
"start_process" : true,
|
||||
"server_path" : "test/acceptance/bin/selenium-server-standalone-2.52.0.jar",
|
||||
"log_path" : false,
|
||||
"host" : "127.0.0.1",
|
||||
"port" : 4444,
|
||||
"cli_args" : {
|
||||
"webdriver.chrome.driver" : "/usr/local/bin/chromedriver",
|
||||
"webdriver.ie.driver" : ""
|
||||
}
|
||||
},
|
||||
|
||||
"test_settings" : {
|
||||
"default" : {
|
||||
"launch_url" : "http://localhost",
|
||||
"selenium_port" : 4444,
|
||||
"selenium_host" : "localhost",
|
||||
"silent": true,
|
||||
"screenshots" : {
|
||||
"enabled" : false,
|
||||
"path" : ""
|
||||
},
|
||||
"desiredCapabilities": {
|
||||
"browserName": "chrome",
|
||||
"javascriptEnabled": true,
|
||||
"acceptSslCerts": true,
|
||||
"chromeOptions" : {
|
||||
"binary": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"chrome" : {
|
||||
"desiredCapabilities": {
|
||||
"browserName": "chrome",
|
||||
"javascriptEnabled": true,
|
||||
"acceptSslCerts": true,
|
||||
"chromeOptions" : {
|
||||
"args" : ["-e", "--no-sandbox"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
test/acceptance/ricky.jpg
Normal file
BIN
test/acceptance/ricky.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
Loading…
x
Reference in New Issue
Block a user