Merge pull request #91 from coralproject/stream-e2e

Embed stream end to end testing
This commit is contained in:
Belén Curcio
2016-12-05 19:39:14 -03:00
committed by GitHub
18 changed files with 376 additions and 40 deletions
+2 -1
View File
@@ -1,8 +1,9 @@
node_modules
npm-debug.log
npm-debug.log*
dist
!dist/coral-admin
dist/coral-admin/bundle.js
tests/e2e/reports
.DS_Store
*.iml
dump.rdb
+2 -1
View File
@@ -17,7 +17,8 @@ const util = require('../util');
/**
* Get port from environment and store in Express.
*/
const port = normalizePort(process.env.TALK_PORT || '3000');
const port = normalizePort(process.env.TALK_PORT || (process.env.NODE_ENV === 'test' ? '3011' : '3000'));
app.set('port', port);
+7 -17
View File
@@ -65,27 +65,17 @@ class CommentStream extends Component {
componentDidMount () {
// Set up messaging between embedded Iframe an parent component
// Using recommended Pym init code which violates .eslint standards
const pym = new Pym.Child({polling: 100});
this.pym = new Pym.Child({polling: 100});
if (/https?\:\/\/([^?]+)/.test(pym.parentUrl)) {
this.props.getStream(pym.parentUrl);
} else {
this.props.getStream(window.location);
}
const path = /https?\:\/\/([^?#]+)/.exec(this.pym.parentUrl);
this.props.getStream(path[1] || window.location);
this.path = path;
this.pym.sendMessage('childReady');
}
render () {
if (Object.keys(this.props.items).length === 0) {
// Loading mock asset
this.props.postItem({
comments: [],
url: 'http://coralproject.net'
}, 'asset', 'assetTest');
}
// TODO: Replace teststream id with id from params
const rootItemId = this.props.items.assets && Object.keys(this.props.items.assets)[0];
const rootItem = this.props.items.assets && this.props.items.assets[rootItemId];
const {actions, users, comments} = this.props.items;
@@ -78,6 +78,7 @@ class CommentBox extends Component {
{ author && (
<Button
cStyle='darkGrey'
className={`${name}-button`}
onClick={this.postComment}>
{lang.t('post')}
</Button>
@@ -44,7 +44,7 @@ const SignInContent = ({handleChange, formData, ...props}) => (
<div className={styles.action}>
{
!props.auth.isLoading ?
<Button type="submit" cStyle="black" className={styles.signInButton} full>
<Button id='coralLogInButton' type="submit" cStyle="black" className={styles.signInButton} full>
{lang.t('signIn.signIn')}
</Button>
:
@@ -56,7 +56,7 @@ const SignInContent = ({handleChange, formData, ...props}) => (
<span><a onClick={() => props.changeView('FORGOT')}>{lang.t('signIn.forgotYourPass')}</a></span>
<span>
{lang.t('signIn.needAnAccount')}
<a onClick={() => props.changeView('SIGNUP')}>
<a onClick={() => props.changeView('SIGNUP')} id='coralRegister'>
{lang.t('signIn.register')}
</a>
</span>
@@ -69,7 +69,7 @@ const SignUpContent = ({handleChange, formData, ...props}) => (
/>
<div className={styles.action}>
{ !props.auth.isLoading && !props.auth.successSignUp && (
<Button type="submit" cStyle="black" className={styles.signInButton} full>
<Button type="submit" cStyle="black" id='coralSignUpButton' className={styles.signInButton} full>
{lang.t('signIn.signUp')}
</Button>
)}
@@ -132,7 +132,9 @@ class SignInContainer extends Component {
const {auth, showSignInDialog, noButton} = this.props;
return (
<div>
{!noButton && <Button onClick={showSignInDialog} full> Sign in to comment</Button>}
{!noButton && <Button id='coralSignInButton' onClick={showSignInDialog} full>
Sign in to comment
</Button>}
<SignDialog
open={auth.showSignInDialog}
view={auth.view}
+7 -1
View File
@@ -1,7 +1,13 @@
const mongoose = require('mongoose');
const debug = require('debug')('talk:db');
const enabled = require('debug').enabled;
const url = process.env.TALK_MONGO_URL || (process.env.NODE_ENV === 'test' ? 'mongodb://localhost/test' : 'mongodb://localhost/talk');
//Append '-test' to the db if node_env === 'test'
let url = process.env.TALK_MONGO_URL || 'mongodb://localhost/coral-talk';
if (process.env.NODE_ENV === 'test') {
url += '-test';
}
// Use native promises
mongoose.Promise = global.Promise;
+44
View File
@@ -0,0 +1,44 @@
require('babel-core/register');
module.exports = {
'src_folders': './tests/e2e/tests',
'output_folder': './tests/e2e/reports',
'page_objects_path': './tests/e2e/pages',
'globals_path': './tests/e2e/globals',
'custom_commands_path' : '',
'custom_assertions_path' : '',
'selenium': {
'start_process': true,
'server_path': 'node_modules/selenium-standalone/.selenium/selenium-server/2.53.1-server.jar',
'log_path': './tests/e2e/reports',
'host': '127.0.0.1',
'port': 6666,
'cli_args': {
'webdriver.chrome.driver': 'node_modules/selenium-standalone/.selenium/chromedriver/2.25-x64-chromedriver'
}
},
'test_settings': {
'default': {
'selenium_port': 6666,
'selenium_host': 'localhost',
'silent': true,
'desiredCapabilities': {
'browserName': 'chrome',
'javascriptEnabled': true,
'acceptSslCerts': true,
'webStorageEnabled' : true,
'databaseEnabled' : true,
'applicationCacheEnabled' : false,
'nativeEvents' : true
},
'screenshots' : {
'enabled' : true,
'on_failure' : true,
'on_error' : true,
'path' : './tests/e2e/reports'
},
'exclude': [
]
}
}
};
+9 -15
View File
@@ -11,18 +11,15 @@
"lint-fix": "eslint . --fix",
"test": "NODE_ENV=test mocha --compilers js:babel-core/register --recursive tests",
"test-watch": "NODE_ENV=test mocha --compilers js:babel-core/register --recursive -w tests",
"pree2e": "NODE_ENV=test ./pree2e.sh",
"e2e": "NODE_ENV=test node_modules/.bin/nightwatch",
"embed-start": "NODE_ENV=development npm run build && ./bin/cli serve --jobs"
},
"config": {
"pre-git": {
"commit-msg": [],
"pre-commit": [
"npm run lint",
"npm test"
],
"pre-push": [
"npm test"
],
"pre-commit": ["npm run lint", "npm test"],
"pre-push": ["npm test"],
"post-commit": [],
"post-merge": []
}
@@ -31,12 +28,7 @@
"type": "git",
"url": "git+https://github.com/coralproject/talk.git"
},
"keywords": [
"talk",
"coral",
"coralproject",
"ask"
],
"keywords": ["talk", "coral", "coralproject", "ask"],
"author": "",
"license": "Apache-2.0",
"bugs": {
@@ -110,6 +102,8 @@
"material-design-lite": "^1.2.1",
"mocha": "^3.1.2",
"mocha-junit-reporter": "^1.12.1",
"nightwatch": "^0.9.9",
"node-fetch": "^1.6.3",
"postcss-loader": "^1.1.0",
"postcss-modules": "^0.5.2",
"postcss-smart-import": "^0.5.1",
@@ -127,11 +121,11 @@
"redux-mock-store": "^1.2.1",
"redux-thunk": "^2.1.0",
"regenerator": "^0.8.46",
"selenium-standalone": "^5.8.0",
"style-loader": "^0.13.1",
"supertest": "^2.0.1",
"timeago.js": "^2.0.3",
"webpack": "^1.13.3",
"whatwg-fetch": "^1.0.0"
"webpack": "^1.13.3"
},
"engines": {
"node": ">=7.0.0"
Executable
+2
View File
@@ -0,0 +1,2 @@
node_modules/selenium-standalone/bin/selenium-standalone install
npm start &
+4
View File
@@ -0,0 +1,4 @@
module.exports = {
waitForConditionTimeout: 20000,
baseUrl: 'localhost:3011/'
};
+25
View File
@@ -0,0 +1,25 @@
const Comments = require('../../models/comment');
const Users = require('../../models/user');
const Actions = require('../../models/action');
const Assets = require('../../models/asset');
const Settings = require('../../models/setting');
const globals = require('./globals');
/* Create an array of comments */
module.exports.comments = (comments) => Assets.findOrCreateByUrl(globals.baseUrl)
.then((asset) => {
comments = comments.map((comment) => {
comment.asset_id = asset.id;
return comment;
});
return Comments.create(comments);
});
/* Create an array of users */
module.exports.users = (users) => Users.createLocalUsers(users);
/* Create an array of actions */
module.exports.actions = (actions) => Actions.create(actions);
/* Update a setting */
module.exports.settings = (setting) => Settings.init().then(() => Settings.updateSettings(setting));
+45
View File
@@ -0,0 +1,45 @@
const fetch = require('node-fetch');
const embedCommands = {
ready() {
return this.resizeWindow(1200, 800)
.url(client.globals.baseUrl)
.waitForElementVisible('body', 2000)
.frame('coralStreamIframe');
},
setConfig(config, baseUrl) {
return fetch(`${baseUrl}/api/v1/settings`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(config)
});
},
enterComment() {
const comment = 'This is a test comment';
return this
.waitForElementVisible('@commentBox')
.setValue('@commentBox', comment)
.click('@postButton')
.waitForElementVisible('.comment', 1000);
},
validateComment(comment) {
return this
.assert.equal(comment, '.comment');
}
};
module.exports = {
commands: [embedCommands],
elements: {
commentBox: {
selector: '#commentBox'
},
postButton: {
selector: '#commentBox .coral-plugin-commentbox-button'
}
}
};
+13
View File
@@ -0,0 +1,13 @@
module.exports = {
'@tags': ['app'],
'Base url and Hostname': browser => {
const {baseUrl} = browser.globals;
browser
.url(baseUrl)
.assert.title('Coral Talk')
.waitForElementPresent('body', 1000);
},
after: client => {
client.end();
}
};
+173
View File
@@ -0,0 +1,173 @@
const utils = require('../../utils/e2e-mongoose');
const mocks = require('../mocks');
const mockComment = 'This is a test comment.';
const mockReply = 'This is a test reply';
const mockUser = {
email: `${new Date().getTime()}@test.com`,
name: 'Test User',
pw: 'testtesttest'
};
module.exports = {
'@tags': ['embed-stream', 'comment', 'premodoff', 'premodon'],
before: () => {
utils.before();
},
'User registers and posts a comment with premod off': client => {
client.perform((client, done) => {
mocks.settings({moderation: 'post'})
.then(() => {
//Load Page
client.resizeWindow(1200, 800)
.url(client.globals.baseUrl)
.frame('coralStreamIframe')
//Register and Log In
.waitForElementVisible('#commentBox', 1000)
.waitForElementVisible('#coralSignInButton', 2000)
.click('#coralSignInButton')
.waitForElementVisible('#coralRegister', 1000)
.click('#coralRegister')
.waitForElementVisible('#email', 1000)
.setValue('#email', mockUser.email)
.setValue('#displayName', mockUser.name)
.setValue('#password', mockUser.pw)
.setValue('#confirmPassword', mockUser.pw)
.click('#coralSignUpButton')
.waitForElementVisible('#coralLogInButton', 10000)
.click('#coralLogInButton')
.waitForElementVisible('.coral-plugin-commentbox-button', 4000)
// Post a comment
.setValue('.coral-plugin-commentbox-textarea', mockComment)
.click('.coral-plugin-commentbox-button')
.waitForElementVisible('.comment', 1000)
//Verify that it appears
.assert.containsText('.comment', mockComment);
done();
})
.catch((err) => {
console.log(err);
done();
});
});
},
'User posts a comment with premod on': client => {
client.perform((client, done) => {
mocks.settings({moderation: 'pre'})
.then(() => {
//Load Page
client.url(client.globals.baseUrl)
.frame('coralStreamIframe');
// Post a comment
client.waitForElementVisible('.coral-plugin-commentbox-button', 2000)
.setValue('.coral-plugin-commentbox-textarea', mockComment)
.click('.coral-plugin-commentbox-button')
.waitForElementVisible('#coral-notif', 1000)
//Verify that it appears
.assert.containsText('#coral-notif', 'moderation team');
done();
})
.catch((err) => {
console.log(err);
done();
});
});
},
'User replies to a comment with premod off': client => {
client.perform((client, done) => {
mocks.settings({moderation: 'post'})
.then(() => {
//Load Page
client.resizeWindow(1200, 800)
.url(client.globals.baseUrl)
.frame('coralStreamIframe');
// Post a comment
client.waitForElementVisible('.coral-plugin-commentbox-button', 2000)
.setValue('.coral-plugin-commentbox-textarea', mockComment)
.click('.coral-plugin-commentbox-button')
// Post a reply
.waitForElementVisible('.coral-plugin-replies-reply-button', 5000)
.click('.coral-plugin-replies-reply-button')
.waitForElementVisible('#replyText')
.setValue('#replyText', mockReply)
.click('.coral-plugin-replies-textarea button')
.waitForElementVisible('.reply', 2000)
//Verify that it appears
.assert.containsText('.reply', mockReply);
done();
})
.catch((err) => {
console.log(err);
done();
});
});
},
'User replies to a comment with premod on': client => {
client.perform((client, done) => {
mocks.settings({moderation: 'pre'})
// Add a mock user
.then(() => {
return mocks.users([{
displayName: 'Baby Blue',
email: 'whale@tale.sea',
password: 'krill'
}]);
})
// Add a mock preapproved comment by that user
.then((user) => {
return mocks.comments([{
body: 'Whales are not fish.',
status: 'accepted',
author_id: user.id
}]);
})
.then(() => {
//Load Page
client.resizeWindow(1200, 800)
.url(client.globals.baseUrl)
.frame('coralStreamIframe');
// Post a reply
client.waitForElementVisible('.coral-plugin-replies-reply-button', 5000)
.click('.coral-plugin-replies-reply-button')
.waitForElementVisible('#replyText')
.setValue('#replyText', mockReply)
.click('.coral-plugin-replies-textarea button')
.waitForElementVisible('#coral-notif', 1000)
//Verify that it appears
.assert.containsText('#coral-notif', 'moderation team');
done();
})
.catch((err) => {
console.log(err);
done();
});
});
},
'Total comment count premod on': client => {
client.perform((client, done) => {
client.url(client.globals.baseUrl)
.frame('coralStreamIframe');
// Verify that comment count is correct
client.waitForElementVisible('.coral-plugin-comment-count-text', 2000)
.assert.containsText('.coral-plugin-comment-count-text', '1 Comment');
done();
});
},
after: client => {
utils.after();
client.end();
}
};
+34
View File
@@ -0,0 +1,34 @@
const mongoose = require('../../mongoose');
// Ensure the NODE_ENV is set to 'test',
// this is helpful when you would like to change behavior when testing.
function clearDB() {
// console.log('Clearing DB', mongoose.connection);
for (let i in mongoose.connection.collections) {
// console.log('Clearing', i);
mongoose.connection.collections[i].remove(function() {});
}
}
module.exports = {
before: () => {
clearDB();
},
beforeEach: () => {
if (mongoose.connection.readyState === 0) {
mongoose.on('open', function() {
if (err) {
throw err;
}
return clearDB();
});
} else {
return clearDB();
}
},
after: () => {
clearDB();
mongoose.disconnect();
}
};
+2 -1
View File
@@ -15,6 +15,7 @@
width:500px;
}
</style>
<title><%= title %></title>
</head>
<body>
<main>
@@ -35,7 +36,7 @@
<script type='text/javascript' src='<%= basePath %>/pym.v1.min.js'></script>
<script>
var ready = false;
var pymParent = new pym.Parent('coralStreamEmbed', '/embed/stream', {title: 'Talk Comments'});
var pymParent = new pym.Parent('coralStreamEmbed', '/embed/stream', {title: 'Talk Comments', id:'coralStreamIframe'});
pymParent.onMessage('height', function(height) {document.querySelector('#coralStreamEmbed iframe').height = height + 'px'})
pymParent.onMessage('childReady', function () {
var interval = setInterval(function () {