mirror of
https://github.com/wassname/talk.git
synced 2026-07-05 04:14:04 +08:00
Merge pull request #249 from coralproject/e2e-env-fix
E2E environment fix
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
const program = require('commander');
|
||||
const pkg = require('../package.json');
|
||||
const dotenv = require('dotenv');
|
||||
const util = require('../util');
|
||||
|
||||
//==============================================================================
|
||||
// Setting up the program command line arguments.
|
||||
@@ -15,6 +16,7 @@ const dotenv = require('dotenv');
|
||||
program
|
||||
.version(pkg.version)
|
||||
.option('-c, --config [path]', 'Specify the configuration file to load')
|
||||
.option('--pid [path]', 'Specify a path to output the current PID to')
|
||||
.parse(process.argv);
|
||||
|
||||
if (program.config) {
|
||||
@@ -27,6 +29,11 @@ if (program.config) {
|
||||
}
|
||||
}
|
||||
|
||||
// If the `--pid` flag is used, put the current pid there.
|
||||
if (program.pid) {
|
||||
util.pid(program.pid);
|
||||
}
|
||||
|
||||
// Perform rewrites to the runtime environment variables based on the contents
|
||||
// of the process.env.REWRITE_ENV if it exists. This is done here as it is the
|
||||
// entrypoint for the entire application.
|
||||
@@ -43,4 +50,15 @@ program
|
||||
// If there is no command listed, output help.
|
||||
if (!process.argv.slice(2).length) {
|
||||
program.outputHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// The ensures that the child process that is created here is always cleaned up
|
||||
// properly when the parent process dies.
|
||||
util.onshutdown([
|
||||
(signal) => {
|
||||
if ((program.runningCommand.killed === false) && (program.runningCommand.exitCode === null)) {
|
||||
program.runningCommand.kill(signal);
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -21,6 +21,8 @@ test:
|
||||
override:
|
||||
# Run the tests using the junit reporter.
|
||||
- MOCHA_FILE=$CIRCLE_TEST_REPORTS/junit/test-results.xml NPM_PACKAGE_CONFIG_MOCHA_REPORTER=mocha-junit-reporter npm run test
|
||||
# Run the e2e test suite
|
||||
- E2E_REPORT_PATH=$CIRCLE_TEST_REPORTS/e2e npm run e2e
|
||||
|
||||
deployment:
|
||||
release:
|
||||
|
||||
@@ -8,10 +8,10 @@ import SuspendUserModal from './SuspendUserModal';
|
||||
|
||||
// Each action has different meaning and configuration
|
||||
const menuOptionsMap = {
|
||||
'reject': {status: 'rejected', icon: 'close', key: 'r'},
|
||||
'approve': {status: 'accepted', icon: 'done', key: 't'},
|
||||
'flag': {status: 'flagged', icon: 'flag', filter: 'Untouched'},
|
||||
'ban': {status: 'banned', icon: 'not interested'}
|
||||
'reject': {status: 'REJECTED', icon: 'close', key: 'r'},
|
||||
'approve': {status: 'ACCEPTED', icon: 'done', key: 't'},
|
||||
'flag': {status: 'FLAGGED', icon: 'flag', filter: 'Untouched'},
|
||||
'ban': {status: 'BANNED', icon: 'not interested'}
|
||||
};
|
||||
|
||||
// Renders a comment list and allow performing actions
|
||||
@@ -135,9 +135,9 @@ export default class ModerationList extends React.Component {
|
||||
} else if (action.item_type === 'USERS') {
|
||||
|
||||
// If a user bio or name is rejected, bring up a dialog before suspending them.
|
||||
if (menuOption === 'rejected') {
|
||||
if (menuOption === 'REJECTED') {
|
||||
this.setState({suspendUserModal: action});
|
||||
} else if (menuOption === 'accepted') {
|
||||
} else if (menuOption === 'ACCEPTED') {
|
||||
this.props.userStatusUpdate('ACTIVE', action.item_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class Comment extends React.Component {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="comment"
|
||||
className={parentId ? 'reply' : 'comment'}
|
||||
id={`c_${comment.id}`}
|
||||
style={{marginLeft: depth * 30}}>
|
||||
<hr aria-hidden={true} />
|
||||
|
||||
@@ -2,6 +2,7 @@ fragment commentView on Comment {
|
||||
id
|
||||
body
|
||||
created_at
|
||||
status
|
||||
user {
|
||||
id
|
||||
name: displayName
|
||||
|
||||
@@ -75,8 +75,6 @@ class CommentBox extends Component {
|
||||
} else if (postedComment.status === 'PREMOD') {
|
||||
addNotification('success', lang.t('comment-post-notif-premod'));
|
||||
} else {
|
||||
|
||||
// appendItemArray(parent_id || id, related, commentId, !parent_id, parent_type);
|
||||
addNotification('success', 'Your comment has been posted.');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
const name = 'coral-plugin-replies';
|
||||
const name = 'coral-plugin-content';
|
||||
|
||||
const Content = ({body, styles}) => {
|
||||
const textbreaks = body.split('\n');
|
||||
|
||||
+11
-10
@@ -1,16 +1,21 @@
|
||||
require('babel-core/register');
|
||||
|
||||
let E2E_REPORT_PATH = './test/e2e/reports';
|
||||
if (process.env.E2E_REPORT_PATH && process.env.E2E_REPORT_PATH.length > 0) {
|
||||
E2E_REPORT_PATH = process.env.E2E_REPORT_PATH;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
'src_folders': './tests/e2e/tests',
|
||||
'output_folder': './tests/e2e/reports',
|
||||
'page_objects_path': './tests/e2e/pages',
|
||||
'globals_path': './tests/e2e/globals',
|
||||
'src_folders': './test/e2e/tests',
|
||||
'output_folder': E2E_REPORT_PATH,
|
||||
'page_objects_path': './test/e2e/pages',
|
||||
'globals_path': './test/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',
|
||||
'log_path': E2E_REPORT_PATH,
|
||||
'host': '127.0.0.1',
|
||||
'port': 6666,
|
||||
'cli_args': {
|
||||
@@ -36,7 +41,7 @@ module.exports = {
|
||||
'enabled': true,
|
||||
'on_failure': true,
|
||||
'on_error': true,
|
||||
'path': './tests/e2e/reports'
|
||||
'path': E2E_REPORT_PATH
|
||||
},
|
||||
'exclude': [
|
||||
'./tests/e2e/tests/EmbedStreamTests.js'
|
||||
@@ -47,7 +52,3 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// "chromeOptions" : {
|
||||
// "args" : ["start-fullscreen"]
|
||||
// }
|
||||
|
||||
+2
-1
@@ -14,6 +14,7 @@
|
||||
"test-cover": "TEST_MODE=unit NODE_ENV=test istanbul cover _mocha --report text --check-coverage -- -R spec",
|
||||
"pree2e": "NODE_ENV=test scripts/pree2e.sh",
|
||||
"e2e": "NODE_ENV=test nightwatch",
|
||||
"poste2e": "NODE_ENV=test scripts/poste2e.sh",
|
||||
"embed-start": "NODE_ENV=development npm run build && ./bin/cli serve --jobs",
|
||||
"postinstall": "npm run build"
|
||||
},
|
||||
@@ -153,7 +154,7 @@
|
||||
"redux-mock-store": "^1.2.1",
|
||||
"redux-thunk": "^2.1.0",
|
||||
"regenerator": "^0.8.46",
|
||||
"selenium-standalone": "latest",
|
||||
"selenium-standalone": "^5.11.2",
|
||||
"style-loader": "^0.13.1",
|
||||
"supertest": "^2.0.1",
|
||||
"timeago.js": "^2.0.3",
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
# If there is a PID file from the e2e tests...
|
||||
if [ -e /tmp/talk-e2e.pid ]
|
||||
then
|
||||
|
||||
# Then kill the running talk server.
|
||||
kill $(cat /tmp/talk-e2e.pid)
|
||||
|
||||
fi
|
||||
+9
-5
@@ -1,15 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# install selenium
|
||||
selenium-standalone install
|
||||
selenium-standalone install --config=./selenium.config.js
|
||||
|
||||
#Init settings
|
||||
./bin/cli settings init
|
||||
|
||||
# Creating Admin Test User
|
||||
./bin/cli-users create --flag_mode --email "admin@test.com" --password "test" --name "Admin Test User" --role "admin"
|
||||
./bin/cli users create --flag_mode --email "admin@test.com" --password "testtest" --name "AdminTestUser" --role "ADMIN"
|
||||
|
||||
# Creating Moderator Test User
|
||||
./bin/cli-users create --flag_mode --email "moderator@test.com" --password "test" --name "Moderator Test User" --role "moderator"
|
||||
./bin/cli users create --flag_mode --email "moderator@test.com" --password "testtest" --name "ModeratorTestUser" --role "MODERATOR"
|
||||
|
||||
# Creating Commenter Test User
|
||||
./bin/cli-users create --flag_mode --email "commenter@test.com" --password "test" --name "commenter@test.com"
|
||||
./bin/cli users create --flag_mode --email "commenter@test.com" --password "testtest" --name "CommenterTestUser"
|
||||
|
||||
npm start &
|
||||
# Start the server and write the PID to a file to be killed later.
|
||||
./bin/cli --pid /tmp/talk-e2e.pid serve --jobs &
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
drivers: {
|
||||
chrome: {
|
||||
version: '2.25',
|
||||
arch: process.arch,
|
||||
baseURL: 'https://chromedriver.storage.googleapis.com'
|
||||
},
|
||||
},
|
||||
};
|
||||
+3
-3
@@ -4,15 +4,15 @@ module.exports = {
|
||||
users: {
|
||||
admin: {
|
||||
email: 'admin@test.com',
|
||||
pass: 'test'
|
||||
pass: 'testtest'
|
||||
},
|
||||
moderator: {
|
||||
email: 'moderator@test.com',
|
||||
pass: 'test'
|
||||
pass: 'testtest'
|
||||
},
|
||||
commenter: {
|
||||
email: 'commenter@test.com',
|
||||
pass: 'test'
|
||||
pass: 'testtest'
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
+7
-6
@@ -1,8 +1,8 @@
|
||||
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 Comments = require('../../services/comments');
|
||||
const Users = require('../../services/users');
|
||||
const Actions = require('../../services/actions');
|
||||
const Assets = require('../../services/assets');
|
||||
const Settings = require('../../services/settings');
|
||||
const globals = require('./globals');
|
||||
|
||||
/* Create an array of comments */
|
||||
@@ -22,4 +22,5 @@ module.exports.users = (users) => Users.createLocalUsers(users);
|
||||
module.exports.actions = (actions) => Actions.create(actions);
|
||||
|
||||
/* Update a setting */
|
||||
module.exports.settings = (setting) => Settings.init().then(() => Settings.updateSettings(setting));
|
||||
module.exports.settings = (setting) => Settings.init().then(() =>
|
||||
Settings.update(setting));
|
||||
|
||||
@@ -10,7 +10,8 @@ const embedStreamCommands = {
|
||||
return this
|
||||
.waitForElementVisible('@moderationList')
|
||||
.waitForElementVisible('@approveButton')
|
||||
.click('@approveButton');
|
||||
.click('@approveButton')
|
||||
.waitForElementNotPresent('@approveButton');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -127,10 +127,10 @@ module.exports = {
|
||||
selector: '.comment .coral-plugin-flags-popup'
|
||||
},
|
||||
flagCommentOption: {
|
||||
selector: '.comment .coral-plugin-flags-popup .coral-plugin-flags-popup-radio-label[for="comments"]'
|
||||
selector: '.comment .coral-plugin-flags-popup .coral-plugin-flags-popup-radio-label[for="COMMENTS"]'
|
||||
},
|
||||
flagUsernameOption: {
|
||||
selector: '.comment .coral-plugin-flags-popup .coral-plugin-flags-popup-radio-label[for="user"]'
|
||||
selector: '.comment .coral-plugin-flags-popup .coral-plugin-flags-popup-radio-label[for="USERS"]'
|
||||
},
|
||||
flagOtherOption: {
|
||||
selector: '.comment .coral-plugin-flags-popup .coral-plugin-flags-popup-radio-label[for="other"]'
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
const mocks = require('../mocks');
|
||||
|
||||
module.exports = {
|
||||
'@tags': ['embedStream'],
|
||||
before: client => {
|
||||
const embedStreamPage = client.page.embedStreamPage();
|
||||
embedStreamPage
|
||||
.navigate()
|
||||
.ready();
|
||||
client.perform((client, done) => {
|
||||
mocks.settings({moderation: 'PRE'})
|
||||
.then(() => {
|
||||
const embedStreamPage = client.page.embedStreamPage();
|
||||
embedStreamPage
|
||||
.navigate()
|
||||
.ready();
|
||||
done();
|
||||
});
|
||||
});
|
||||
},
|
||||
'Login as commenter': client => {
|
||||
const embedStreamPage = client.page.embedStreamPage();
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
const mongoose = require('../../helpers/mongoose');
|
||||
const mocks = require('../mocks');
|
||||
|
||||
const mockComment = 'This is a test comment.';
|
||||
const mockComment = 'I read the comments';
|
||||
const mockReply = 'This is a test reply';
|
||||
const mockUser = {
|
||||
email: `${new Date().getTime()}@test.com`,
|
||||
name: 'Test User',
|
||||
pw: 'testtesttest'
|
||||
name: 'testuser',
|
||||
pw: 'testtest'
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
@@ -29,7 +29,6 @@ module.exports = {
|
||||
.frame('coralStreamIframe')
|
||||
|
||||
// Register and Log In
|
||||
.waitForElementVisible('#commentBox', 1000)
|
||||
.waitForElementVisible('#coralSignInButton', 2000)
|
||||
.click('#coralSignInButton')
|
||||
.waitForElementVisible('#coralRegister', 1000)
|
||||
@@ -47,10 +46,10 @@ module.exports = {
|
||||
// Post a comment
|
||||
.setValue('.coral-plugin-commentbox-textarea', mockComment)
|
||||
.click('.coral-plugin-commentbox-button')
|
||||
.waitForElementVisible('.comment', 1000)
|
||||
.waitForElementVisible('.coral-plugin-content-text', 1000)
|
||||
|
||||
// Verify that it appears
|
||||
.assert.containsText('.comment', mockComment);
|
||||
.assert.containsText('.coral-plugin-content-text', mockComment);
|
||||
done();
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -104,8 +103,8 @@ module.exports = {
|
||||
.click('.coral-plugin-replies-reply-button')
|
||||
.waitForElementVisible('#replyText')
|
||||
.setValue('#replyText', mockReply)
|
||||
.click('.coral-plugin-replies-textarea button')
|
||||
.waitForElementVisible('.reply', 2000)
|
||||
.click('.coral-plugin-replies-textarea .coral-plugin-commentbox-button')
|
||||
.waitForElementVisible('.reply', 20000)
|
||||
|
||||
// Verify that it appears
|
||||
.assert.containsText('.reply', mockReply);
|
||||
@@ -122,22 +121,18 @@ module.exports = {
|
||||
mocks.settings({moderation: 'PRE'})
|
||||
|
||||
// Add a mock user
|
||||
.then(() => {
|
||||
return mocks.users([{
|
||||
displayName: 'Baby Blue',
|
||||
email: 'whale@tale.sea',
|
||||
password: 'krill'
|
||||
}]);
|
||||
})
|
||||
.then(() => 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((user) => mocks.comments([{
|
||||
body: 'Whales are not fish.',
|
||||
status: 'accepted',
|
||||
author_id: user.id
|
||||
}]))
|
||||
.then(() => {
|
||||
|
||||
// Load Page
|
||||
@@ -170,7 +165,7 @@ module.exports = {
|
||||
|
||||
// Verify that comment count is correct
|
||||
client.waitForElementVisible('.coral-plugin-comment-count-text', 2000)
|
||||
.assert.containsText('.coral-plugin-comment-count-text', '1 Comment');
|
||||
.assert.containsText('.coral-plugin-comment-count-text', '4 Comments');
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
const uuid = require('uuid');
|
||||
|
||||
module.exports = {
|
||||
'@tags': ['signup', 'visitor'],
|
||||
before: client => {
|
||||
@@ -14,8 +12,8 @@ module.exports = {
|
||||
|
||||
embedStreamPage
|
||||
.signUp({
|
||||
email: `visitor_${uuid.v4()}@test.com`,
|
||||
displayName: 'Visitor',
|
||||
email: `visitor_${Date.now()}@test.com`,
|
||||
displayName: `visitor${Date.now()}`,
|
||||
pass: 'testtest'
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
const debug = require('debug')('talk:util');
|
||||
const fs = require('fs');
|
||||
|
||||
const util = module.exports = {};
|
||||
|
||||
/**
|
||||
@@ -11,10 +14,16 @@ util.toshutdown = [];
|
||||
* Calls all the shutdown functions and then ends the process.
|
||||
* @param {Number} [defaultCode=0] default return code upon sucesfull shutdown.
|
||||
*/
|
||||
util.shutdown = (defaultCode = 0) => {
|
||||
util.shutdown = (defaultCode = 0, signal = null) => {
|
||||
|
||||
if (signal) {
|
||||
debug(`Reached ${signal} signal`);
|
||||
}
|
||||
|
||||
Promise
|
||||
.all(util.toshutdown.map((func) => func ? func() : null).filter((func) => func))
|
||||
.all(util.toshutdown.map((func) => func ? func(signal) : null).filter((func) => func))
|
||||
.then(() => {
|
||||
debug('Shutdown complete, now exiting');
|
||||
process.exit(defaultCode);
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -32,13 +41,52 @@ util.shutdown = (defaultCode = 0) => {
|
||||
*/
|
||||
util.onshutdown = (jobs) => {
|
||||
|
||||
debug(`${jobs.length} jobs registered`);
|
||||
|
||||
// Add the new jobs to shutdown to the object reference.
|
||||
util.toshutdown = util.toshutdown.concat(jobs);
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a PID file to be maintained for the lifespan of the process.
|
||||
* @param {String} path path to the PID file to create
|
||||
*/
|
||||
util.pid = (path) => {
|
||||
if (!/\//.test(path)) {
|
||||
if (!/\.pid/.test(path)) {
|
||||
path += '.pid';
|
||||
}
|
||||
path = `/tmp/${path}`;
|
||||
}
|
||||
|
||||
const pid = `${process.pid.toString()}\n`;
|
||||
|
||||
fs.writeFile(path, pid, (err) => {
|
||||
if (err) {
|
||||
console.error(`Can't write PID file: ${err}`);
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Add the cleanup for the fs onto the shutdown.
|
||||
util.onshutdown([
|
||||
() => new Promise((resolve, reject) => {
|
||||
|
||||
// Remove the pid file.
|
||||
fs.unlink(path, (err) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
return resolve();
|
||||
});
|
||||
})
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
// Attach to the SIGTERM + SIGINT handles to ensure a clean shutdown in the
|
||||
// event that we have an external event. SIGUSR2 is called when the app is asked
|
||||
// to be 'killed', same procedure here.
|
||||
process.on('SIGTERM', () => util.shutdown());
|
||||
process.on('SIGINT', () => util.shutdown());
|
||||
process.once('SIGUSR2', () => util.shutdown());
|
||||
process.on('SIGTERM', () => util.shutdown(0, 'SIGTERM'));
|
||||
process.on('SIGINT', () => util.shutdown(0, 'SIGINT'));
|
||||
process.once('SIGUSR2', () => util.shutdown(0, 'SIGUSR2'));
|
||||
|
||||
Reference in New Issue
Block a user