From b84daf0422cf967f616265b7db82c8ae70f0a8b4 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Thu, 26 Oct 2017 17:30:55 +0200 Subject: [PATCH 01/43] Set resolution to 1600x1200 bs --- nightwatch-browserstack.conf.js | 1 + 1 file changed, 1 insertion(+) diff --git a/nightwatch-browserstack.conf.js b/nightwatch-browserstack.conf.js index 9e8e334c5..ac8f90d27 100644 --- a/nightwatch-browserstack.conf.js +++ b/nightwatch-browserstack.conf.js @@ -26,6 +26,7 @@ const nightwatch_config = { // Disable this, as it makes bs slow and brittle. 'browserstack.networkLogs': false, + 'browserstack.resolution': '1600x1200', } }, chrome: { From ad4a5595f9e8b184c5f798421c8688c3a0f52c05 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 27 Oct 2017 13:19:00 +0200 Subject: [PATCH 02/43] Enable screenshot on failure for bs --- nightwatch-browserstack.conf.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/nightwatch-browserstack.conf.js b/nightwatch-browserstack.conf.js index ac8f90d27..bf0ca2284 100644 --- a/nightwatch-browserstack.conf.js +++ b/nightwatch-browserstack.conf.js @@ -27,7 +27,13 @@ const nightwatch_config = { // Disable this, as it makes bs slow and brittle. 'browserstack.networkLogs': false, 'browserstack.resolution': '1600x1200', - } + }, + screenshots : { + enabled: true, + on_failure: true, + on_error: true, + path: process.env.REPORTS_FOLDER || './test/e2e/reports', + }, }, chrome: { desiredCapabilities: { From 5f5c64870ab9ee43dda0dbdaae875caeccae3b58 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 27 Oct 2017 19:00:48 +0200 Subject: [PATCH 03/43] Stabilize e2e --- scripts/e2e-ci.sh | 3 ++ test/e2e/specs/02_admin.js | 6 ++-- test/e2e/specs/03_embedStream.js | 52 +++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/scripts/e2e-ci.sh b/scripts/e2e-ci.sh index e0e94b4bf..f64223f32 100755 --- a/scripts/e2e-ci.sh +++ b/scripts/e2e-ci.sh @@ -1,5 +1,8 @@ #!/bin/bash +CIRCLE_TEST_REPORTS=${CIRCLE_TEST_REPORTS:-./test/e2e/reports} +CIRCLE_BRANCH=${CIRCLE_BRANCH:-master} + if [[ "${CIRCLE_BRANCH}" == "master" ]]; then exitCode=0 diff --git a/test/e2e/specs/02_admin.js b/test/e2e/specs/02_admin.js index 4a60780bb..4744d2116 100644 --- a/test/e2e/specs/02_admin.js +++ b/test/e2e/specs/02_admin.js @@ -1,9 +1,9 @@ module.exports = { '@tags': ['admin', 'login'], beforeEach: (client) => { - + client.resizeWindow(1024, 800); - }, + }, 'Admin logs in': (client) => { const adminPage = client.page.admin(); const {testData: {admin}} = client.globals; @@ -17,8 +17,6 @@ module.exports = { .waitForElementVisible('@signInButton') .click('@signInButton'); - client.pause(3000); - adminPage .waitForElementVisible('@moderationContainer'); }, diff --git a/test/e2e/specs/03_embedStream.js b/test/e2e/specs/03_embedStream.js index 57f9a8fd2..5381a5558 100644 --- a/test/e2e/specs/03_embedStream.js +++ b/test/e2e/specs/03_embedStream.js @@ -1,3 +1,31 @@ +class SortedWindowHandler { + + constructor(client) { + this.client = client; + this.client.windowHandles((result) => { + this.handles = result.value; + if (this.handles.length > 2) { + throw new Error('SortedWindowHandler must be created before new windows were created.'); + } + }); + } + + windowHandles(callback) { + this.client.windowHandles((result) => { + console.log(result); + this.handles = this.handles.filter((handle) => result.value.includes(handle)); + const remaining = result.value.filter((handle) => !this.handles.includes(handle)); + if (remaining.length === 1) { + this.handles.push(remaining[0]); + } + if (remaining.length > 1) { + throw new Error('Cannot detect new window handle, because more than one windows was created.'); + } + callback(this.handles); + }); + } +} + module.exports = { '@tags': ['embedStream', 'login'], 'creates a new asset': (client) => { @@ -18,16 +46,15 @@ module.exports = { .navigate() .getEmbedSection(); + const windowHandler = new SortedWindowHandler(client); + embed .waitForElementVisible('@signInButton') .click('@signInButton'); - client.pause(3000); - // Focusing on the Login PopUp - client.windowHandles((result) => { - const handle = result.value[1]; - client.switchWindow(handle); + windowHandler.windowHandles((handles) => { + client.switchWindow(handles[1]); }); const login = client.page.login(); @@ -45,10 +72,19 @@ module.exports = { .waitForElementVisible('@loginButton') .click('@loginButton'); + // Give a tiny bit of time to let popup close. + client.pause(50); + + if (client.capabilities.browserName === 'MicrosoftEdge') { + + // More time for edge. + // https://www.browserstack.com/automate/builds/1ceccf4efb4683b7feb890f45a32b5922b40ed3f/sessions/7393dbfda8387e43b6d5851f359b0c07db414973 + client.pause(1000); + } + // Focusing on the Embed Window - client.windowHandles((result) => { - const handle = result.value[0]; - client.switchWindow(handle); + windowHandler.windowHandles((handles) => { + client.switchWindow(handles[0]); }); }, 'user posts a comment': (client) => { From bfe82218ed44b21ffa041f7480875359c3996e22 Mon Sep 17 00:00:00 2001 From: blackcathacker Date: Sun, 29 Oct 2017 18:09:18 -0700 Subject: [PATCH 04/43] Send user an email when they are banned #1050 --- services/email/banned.html.ejs | 1 + services/email/banned.txt.ejs | 1 + services/users.js | 21 ++++++++++++++++++++- test/server/services/users.js | 21 ++++++++++++++++++++- 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 services/email/banned.html.ejs create mode 100644 services/email/banned.txt.ejs diff --git a/services/email/banned.html.ejs b/services/email/banned.html.ejs new file mode 100644 index 000000000..4fd8f191c --- /dev/null +++ b/services/email/banned.html.ejs @@ -0,0 +1 @@ +<%= body.replace(/\n/g, '
') %> diff --git a/services/email/banned.txt.ejs b/services/email/banned.txt.ejs new file mode 100644 index 000000000..b36560ec5 --- /dev/null +++ b/services/email/banned.txt.ejs @@ -0,0 +1 @@ +<%= body %> diff --git a/services/users.js b/services/users.js index 9906ef6c0..2e5c66d40 100644 --- a/services/users.js +++ b/services/users.js @@ -398,7 +398,7 @@ module.exports = class UsersService { // TODO: current updating status behavior is weird. // once a user has been `APPROVED` its status cannot be // changed anymore. - return UserModel.findOneAndUpdate({ + const user = await UserModel.findOneAndUpdate({ id, status: { $ne: 'APPROVED' @@ -410,6 +410,25 @@ module.exports = class UsersService { }, { new: true, }); + + if (status === 'BANNED') { + let localProfile = user.profiles.find((profile) => profile.provider === 'local'); + if (localProfile) { + const options = + { + template: 'banned', // needed to know which template to render! + locals: { // specifies the template locals. + body: 'In accordance with The Coral Project’s community guidelines, your account has been banned. You are now longer allowed to comment, flag or engage with our community.' + }, + subject: '[Talk] Your account has been banned', + to: localProfile.id // This only works if the user has registered via e-mail. + // We may want a standard way to access a user's e-mail address in the future + }; + await MailerService.sendSimple(options); + } + + } + return user; } /** diff --git a/test/server/services/users.js b/test/server/services/users.js index dddd5eda8..b4a15e3ba 100644 --- a/test/server/services/users.js +++ b/test/server/services/users.js @@ -1,8 +1,11 @@ const UsersService = require('../../../services/users'); const SettingsService = require('../../../services/settings'); +const MailerService = require('../../../services/mailer'); const chai = require('chai'); chai.use(require('chai-as-promised')); +const sinon = require('sinon'); +chai.use(require('sinon-chai')); const expect = chai.expect; describe('services.UsersService', () => { @@ -15,7 +18,7 @@ describe('services.UsersService', () => { mockUsers = await UsersService.createLocalUsers([{ email: 'stampi@gmail.com', username: 'Stampi', - password: '1Coral!-' + password: '1Coral!-', }, { email: 'sockmonster@gmail.com', username: 'Sockmonster', @@ -25,6 +28,12 @@ describe('services.UsersService', () => { username: 'Marvel', password: '3Coral!3' }]); + + sinon.spy(MailerService, 'sendSimple'); + }); + + afterEach(() => { + MailerService.sendSimple.restore(); }); describe('#findById()', () => { @@ -149,7 +158,11 @@ describe('services.UsersService', () => { .then(() => UsersService.findById(mockUsers[0].id)) .then((user) => { expect(user).to.have.property('status', 'ACTIVE'); + }) + .then(() => { + expect(MailerService.sendSimple).to.not.have.been.called; }); + }); }); @@ -188,6 +201,12 @@ describe('services.UsersService', () => { .then(() => UsersService.findById(mockUsers[0].id)) .then((user) => { expect(user).to.have.property('status', 'BANNED'); + }) + .then(() => { + expect(MailerService.sendSimple).to.have.been.calledWithMatch({ + template: 'banned', + to: mockUsers[0].profiles[0].id + }); }); }); From 82a332c787f49c624f6d6da9f3453c0d8885ddd9 Mon Sep 17 00:00:00 2001 From: blackcathacker Date: Sun, 29 Oct 2017 19:48:42 -0700 Subject: [PATCH 05/43] disable report button when comment already reported --- client/talk-plugin-flags/components/FlagButton.js | 9 ++++++++- client/talk-plugin-flags/components/styles.css | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/client/talk-plugin-flags/components/FlagButton.js b/client/talk-plugin-flags/components/FlagButton.js index 24c50416a..18db85c03 100644 --- a/client/talk-plugin-flags/components/FlagButton.js +++ b/client/talk-plugin-flags/components/FlagButton.js @@ -158,9 +158,16 @@ export default class FlagButton extends Component {