[IMPROVE] Apps-engine E2E tests (#16781)

* Add some e2e apps tests

* Add apps tests to CI workflow

* Prevent apps server orchestrator from logging during test mode

Co-authored-by: Douglas Gubert <douglas.gubert@gmail.com>
pull/16591/head^2
Marcos Spessatto Defendi 6 years ago committed by GitHub
parent 7f3d147622
commit a3f4236d99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      app/apps/server/orchestrator.js
  2. 8
      mocha_apps.opts
  3. 3
      package.json
  4. 4
      tests/data/apps/apps-data.js
  5. 35
      tests/data/apps/helper.js
  6. 14
      tests/data/chat.helper.js
  7. 8
      tests/data/users.helper.js
  8. 107
      tests/end-to-end/apps/00-installation.js
  9. 111
      tests/end-to-end/apps/01-send-messages.js
  10. 150
      tests/end-to-end/apps/02-send-messages-as-user.js
  11. 44
      tests/end-to-end/apps/03-slash-command-test-simple.js
  12. 47
      tests/end-to-end/apps/04-slash-command-test-with-arguments.js
  13. 45
      tests/end-to-end/apps/apps-uninstall.js

@ -12,6 +12,10 @@ import { AppUploadsConverter } from './converters/uploads';
import { AppVisitorsConverter } from './converters/visitors';
import { AppRealLogsStorage, AppRealStorage } from './storage';
function isTesting() {
return process.env.TEST_MODE === 'true';
}
class AppServerOrchestrator {
constructor() {
@ -97,7 +101,7 @@ class AppServerOrchestrator {
}
isDebugging() {
return settings.get('Apps_Framework_Development_Mode');
return settings.get('Apps_Framework_Development_Mode') && !isTesting();
}
getRocketChatLogger() {

@ -0,0 +1,8 @@
--require babel-mocha-es6-compiler
--require babel-polyfill
--reporter spec
--ui bdd
--timeout 10000
--bail
--file tests/end-to-end/teardown.js
tests/end-to-end/apps/*.js

@ -37,7 +37,8 @@
"testui": "cypress run --project tests",
"testunit": "mocha --opts ./mocha.opts \"`node -e \"console.log(require('./package.json').mocha.tests.join(' '))\"`\"",
"testapi": "mocha --opts ./mocha_api.opts",
"testci": "npm run testapi && npm run testui",
"testapps": "mocha --opts ./mocha_apps.opts",
"testci": "npm run testapi && npm run testapps && npm run testui",
"translation-diff": "node .scripts/translationDiff.js",
"translation-fix-order": "node .scripts/fix-i18n.js",
"version": "node .scripts/version.js",

@ -0,0 +1,4 @@
export const APP_URL = 'https://github.com/RocketChat/Apps.RocketChat.Tester/blob/master/dist/appsrocketchattester_0.0.1.zip?raw=true';
export const APP_NAME = 'Apps.RocketChat.Tester';
export const APP_USERNAME = 'app.appsrocketchattester';
export const apps = (path = '') => `/api/apps${ path }`;

@ -0,0 +1,35 @@
import { request, credentials } from '../api-data';
import { apps, APP_URL, APP_NAME } from './apps-data';
export const getApps = () => new Promise((resolve) => {
request.get(apps())
.set(credentials)
.end((err, res) => {
resolve(res.body.apps);
});
});
export const removeAppById = (id) => new Promise((resolve) => {
request.delete(apps(`/${ id }`))
.set(credentials)
.end(resolve);
});
export const cleanupApps = async () => {
const apps = await getApps();
const testApp = apps.find((app) => app.name === APP_NAME);
if (testApp) {
await removeAppById(testApp.id);
}
};
export const installTestApp = () => new Promise((resolve) => {
request.post(apps())
.set(credentials)
.send({
url: APP_URL,
})
.end((err, res) => {
resolve(res.body.app);
});
});

@ -44,3 +44,17 @@ export const deleteMessage = ({ roomId, msgId }) => {
msgId,
});
};
export const getMessageById = ({ msgId }) => {
if (!msgId) {
throw new Error('"msgId" is required in "getMessageById" test helper');
}
return new Promise((resolve) => {
request.get(api(`chat.getMessage?msgId=${ msgId }`))
.set(credentials)
.end((err, res) => {
resolve(res.body.message);
});
});
};

@ -23,3 +23,11 @@ export const login = (username, password) => new Promise((resolve) => {
resolve(userCredentials);
});
});
export const getUserByUsername = (username) => new Promise((resolve) => {
request.get(api(`users.info?username=${ username }`))
.set(credentials)
.end((err, res) => {
resolve(res.body.user);
});
});

@ -0,0 +1,107 @@
import { expect } from 'chai';
import { getCredentials, request, credentials, api } from '../../data/api-data.js';
import { updatePermission, updateSetting } from '../../data/permissions.helper';
import { APP_URL, apps, APP_USERNAME } from '../../data/apps/apps-data.js';
import { cleanupApps } from '../../data/apps/helper.js';
import { getUserByUsername } from '../../data/users.helper.js';
describe('Apps - Installation', function() {
this.retries(0);
before((done) => getCredentials(done));
before(async () => cleanupApps());
describe('[Installation]', () => {
it('should throw an error when trying to install an app and the apps framework is enabled but the user does not have the permission', (done) => {
updateSetting('Apps_Framework_Development_Mode', true)
.then(() => updatePermission('manage-apps', []))
.then(() => {
request.post(apps())
.set(credentials)
.send({
url: APP_URL,
})
.expect('Content-Type', 'application/json')
.expect(403)
.expect((res) => {
expect(res.body).to.have.a.property('success', false);
expect(res.body.error).to.be.equal('User does not have the permissions required for this action [error-unauthorized]');
})
.end(done);
});
});
it('should throw an error when trying to install an app and the apps framework is disabled', (done) => {
updateSetting('Apps_Framework_Development_Mode', false)
.then(() => updatePermission('manage-apps', ['admin']))
.then(() => {
request.post(apps())
.set(credentials)
.send({
url: APP_URL,
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.a.property('success', false);
expect(res.body.error).to.be.equal('Installation from url is disabled.');
})
.end(done);
});
});
it('should install the app successfully from a URL', (done) => {
updateSetting('Apps_Framework_Development_Mode', true)
.then(() => {
request.post(apps())
.set(credentials)
.send({
url: APP_URL,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
expect(res.body).to.have.a.property('app');
expect(res.body.app).to.have.a.property('id');
expect(res.body.app).to.have.a.property('version');
expect(res.body.app).to.have.a.property('status').and.to.be.equal('auto_enabled');
})
.end(done);
});
});
it('should have created the app user successfully', (done) => {
getUserByUsername(APP_USERNAME)
.then((user) => {
expect(user.username).to.be.equal(APP_USERNAME);
})
.then(done);
});
describe('Slash commands registration', () => {
it('should have created the "test-simple" slash command successfully', (done) => {
request.get(api('commands.get?command=test-simple'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
expect(res.body).to.have.a.property('command');
expect(res.body.command.command).to.be.equal('test-simple');
})
.end(done);
});
it('should have created the "test-with-arguments" slash command successfully', (done) => {
request.get(api('commands.get?command=test-with-arguments'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
expect(res.body).to.have.a.property('command');
expect(res.body.command.command).to.be.equal('test-with-arguments');
})
.end(done);
});
});
});
});

@ -0,0 +1,111 @@
import { expect } from 'chai';
import { getCredentials, request, credentials } from '../../data/api-data.js';
import { apps } from '../../data/apps/apps-data.js';
import { cleanupApps, installTestApp } from '../../data/apps/helper.js';
import { getMessageById } from '../../data/chat.helper.js';
import { createRoom } from '../../data/rooms.helper';
describe('Apps - Send Messages As APP User', function() {
this.retries(0);
let app;
before((done) => getCredentials(done));
before(async () => {
await cleanupApps();
app = await installTestApp();
});
describe('[Send Message as app user]', () => {
it('should return an error when the room is not found', (done) => {
request.post(apps(`/public/${ app.id }/send-message-as-app-user`))
.send({
roomId: 'invalid-room',
})
.set(credentials)
.expect(404)
.expect((err, res) => {
expect(err).to.have.a.property('error');
expect(res).to.be.equal(undefined);
expect(err.error).to.have.a.property('text');
expect(err.error.text).to.be.equal('Room "invalid-room" could not be found');
})
.end(done);
});
describe('Send to a Public Channel', () => {
let publicMessageId;
it('should send a message as app user', (done) => {
request.post(apps(`/public/${ app.id }/send-message-as-app-user`))
.set(credentials)
.send({
roomId: 'GENERAL',
})
.expect(200)
.expect((res) => {
const response = JSON.parse(res.text);
expect(response).to.have.a.property('messageId');
publicMessageId = response.messageId;
})
.end(done);
});
it('should be a valid message', async () => {
const message = await getMessageById({ msgId: publicMessageId });
expect(message.msg).to.be.equal('Executing send-message-as-app-user test endpoint');
});
});
describe('Send to a Private Channel', () => {
let privateMessageId;
it('should send a message as app user', (done) => {
createRoom({
type: 'p',
name: `apps-e2etest-room-${ Date.now() }`,
})
.end((err, createdRoom) => {
request.post(apps(`/public/${ app.id }/send-message-as-app-user`))
.set(credentials)
.send({
roomId: createdRoom.body.group._id,
})
.expect(200)
.expect((res) => {
const response = JSON.parse(res.text);
expect(response).to.have.a.property('messageId');
privateMessageId = response.messageId;
})
.end(done);
});
});
it('should be a valid message', async () => {
const message = await getMessageById({ msgId: privateMessageId });
expect(message.msg).to.be.equal('Executing send-message-as-app-user test endpoint');
});
});
describe('Send to a DM Channel', () => {
let DMMessageId;
it('should send a message as app user', (done) => {
createRoom({
type: 'd',
username: 'rocket.cat',
})
.end((err, createdRoom) => {
request.post(apps(`/public/${ app.id }/send-message-as-app-user`))
.set(credentials)
.send({
roomId: createdRoom.body.room._id,
})
.expect(200)
.expect((res) => {
const response = JSON.parse(res.text);
expect(response).to.have.a.property('messageId');
DMMessageId = response.messageId;
})
.end(done);
});
});
it('should be a valid message', async () => {
const message = await getMessageById({ msgId: DMMessageId });
expect(message.msg).to.be.equal('Executing send-message-as-app-user test endpoint');
});
});
});
});

@ -0,0 +1,150 @@
import { expect } from 'chai';
import { getCredentials, request, credentials } from '../../data/api-data.js';
import { apps } from '../../data/apps/apps-data.js';
import { cleanupApps, installTestApp } from '../../data/apps/helper.js';
import { getMessageById } from '../../data/chat.helper.js';
import { createRoom } from '../../data/rooms.helper';
import { adminUsername, password } from '../../data/user.js';
import { createUser, login } from '../../data/users.helper.js';
describe('Apps - Send Messages As User', function() {
this.retries(0);
let app;
before((done) => getCredentials(done));
before(async () => {
await cleanupApps();
app = await installTestApp();
});
describe('[Send Message as user]', () => {
it('should return an error when the room is not found', (done) => {
request.post(apps(`/public/${ app.id }/send-message-as-user`))
.send({
roomId: 'invalid-room',
})
.set(credentials)
.expect(404)
.expect((err, res) => {
expect(err).to.have.a.property('error');
expect(res).to.be.equal(undefined);
expect(err.error).to.have.a.property('text');
expect(err.error.text).to.be.equal('Room "invalid-room" could not be found');
})
.end(done);
});
it('should return an error when the user is not found', (done) => {
request.post(apps(`/public/${ app.id }/send-message-as-user?userId=invalid-user`))
.send({
roomId: 'GENERAL',
})
.set(credentials)
.expect(404)
.expect((err, res) => {
expect(err).to.have.a.property('error');
expect(res).to.be.equal(undefined);
expect(err.error).to.have.a.property('text');
expect(err.error.text).to.be.equal('User with id "invalid-user" could not be found');
})
.end(done);
});
describe('Send to a Public Channel', () => {
let publicMessageId;
it('should send a message as app user', (done) => {
request.post(apps(`/public/${ app.id }/send-message-as-user?userId=${ adminUsername }`))
.set(credentials)
.send({
roomId: 'GENERAL',
})
.expect(200)
.expect((res) => {
const response = JSON.parse(res.text);
expect(response).to.have.a.property('messageId');
publicMessageId = response.messageId;
})
.end(done);
});
it('should be a valid message', async () => {
const message = await getMessageById({ msgId: publicMessageId });
expect(message.msg).to.be.equal('Executing send-message-as-user test endpoint');
});
});
describe('Send to a Private Channel', () => {
let privateMessageId;
it('should send a message as app user', (done) => {
createRoom({
type: 'p',
name: `apps-e2etest-room-${ Date.now() }`,
})
.end((err, createdRoom) => {
createUser()
.then((createdUser) => {
const user = createdUser;
login(user.username, password).then((credentials) => {
const userCredentials = credentials;
request.post(apps(`/public/${ app.id }/send-message-as-user?userId=${ user._id }`))
.set(userCredentials)
.send({
roomId: createdRoom.body.group._id,
})
.expect(500)
.end(done);
});
});
});
});
it('should send a message as app user', (done) => {
createRoom({
type: 'p',
name: `apps-e2etest-room-${ Date.now() }`,
})
.end((err, createdRoom) => {
request.post(apps(`/public/${ app.id }/send-message-as-user?userId=${ adminUsername }`))
.set(credentials)
.send({
roomId: createdRoom.body.group._id,
})
.expect(200)
.expect((res) => {
const response = JSON.parse(res.text);
expect(response).to.have.a.property('messageId');
privateMessageId = response.messageId;
})
.end(done);
});
});
it('should be a valid message', async () => {
const message = await getMessageById({ msgId: privateMessageId });
expect(message.msg).to.be.equal('Executing send-message-as-user test endpoint');
});
});
describe('Send to a DM Channel', () => {
let DMMessageId;
it('should send a message as app user', (done) => {
createRoom({
type: 'd',
username: 'rocket.cat',
})
.end((err, createdRoom) => {
request.post(apps(`/public/${ app.id }/send-message-as-user?userId=${ adminUsername }`))
.set(credentials)
.send({
roomId: createdRoom.body.room._id,
})
.expect(200)
.expect((res) => {
const response = JSON.parse(res.text);
expect(response).to.have.a.property('messageId');
DMMessageId = response.messageId;
})
.end(done);
});
});
it('should be a valid message', async () => {
const message = await getMessageById({ msgId: DMMessageId });
expect(message.msg).to.be.equal('Executing send-message-as-user test endpoint');
});
});
});
});

@ -0,0 +1,44 @@
import { expect } from 'chai';
import { getCredentials, request, credentials, api } from '../../data/api-data.js';
import { cleanupApps, installTestApp } from '../../data/apps/helper.js';
describe('Apps - Slash Command "test-simple"', function() {
this.retries(0);
before((done) => getCredentials(done));
before(async () => {
await cleanupApps();
await installTestApp();
});
describe('[Slash command "test-simple"]', () => {
it('should execute the slash command successfully', (done) => {
request.post(api('commands.run'))
.send({
roomId: 'GENERAL',
command: 'test-simple',
})
.set(credentials)
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
})
.end(done);
});
it('should have sent the message correctly', (done) => {
request.get(api('chat.search'))
.query({
roomId: 'GENERAL',
searchText: 'Slashcommand \'test-simple\' successfully executed',
})
.set(credentials)
.expect(200)
.expect((res) => {
const message = res.body.messages.find((message) => message.msg === 'Slashcommand \'test-simple\' successfully executed');
expect(message).to.not.be.equal(undefined);
})
.end(done);
});
});
});

@ -0,0 +1,47 @@
import { expect } from 'chai';
import { getCredentials, request, credentials, api } from '../../data/api-data.js';
import { cleanupApps, installTestApp } from '../../data/apps/helper.js';
describe('Apps - Slash Command "test-with-arguments"', function() {
this.retries(0);
before((done) => getCredentials(done));
before(async () => {
await cleanupApps();
await installTestApp();
});
describe('[Slash command "test-with-arguments"]', () => {
const params = 'argument';
it('should execute the slash command successfully', (done) => {
request.post(api('commands.run'))
.send({
roomId: 'GENERAL',
command: 'test-with-arguments',
params,
})
.set(credentials)
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
})
.end(done);
});
it('should have sent the message correctly', (done) => {
const searchText = `Slashcommand \'test-with-arguments\' successfully executed with arguments: "${ params }"`;
request.get(api('chat.search'))
.query({
roomId: 'GENERAL',
searchText,
})
.set(credentials)
.expect(200)
.expect((res) => {
const message = res.body.messages.find((message) => message.msg === searchText);
expect(message).to.not.be.equal(undefined);
})
.end(done);
});
});
});

@ -0,0 +1,45 @@
import { expect } from 'chai';
import { getCredentials, request, credentials } from '../../data/api-data.js';
import { apps } from '../../data/apps/apps-data.js';
import { installTestApp, cleanupApps } from '../../data/apps/helper.js';
describe('Apps - Uninstall', function() {
this.retries(0);
let app;
before((done) => getCredentials(done));
before(async () => {
await cleanupApps();
app = await installTestApp();
});
describe('[Uninstall]', () => {
it('should throw an error when trying to uninstall an invalid app', (done) => {
request.delete(apps('/invalid-id'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(404)
.expect((res) => {
expect(res.body).to.have.a.property('success', false);
expect(res.body.error).to.be.equal('No App found by the id of: invalid-id');
})
.end(done);
});
it('should remove the app successfully', (done) => {
request.delete(apps(`/${ app.id }`))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.a.property('success', true);
expect(res.body).to.have.a.property('app');
expect(res.body.app.id).to.be.equal(app.id);
expect(res.body.app.status).to.be.equal('disabled');
})
.end(done);
});
});
});
Loading…
Cancel
Save