diff --git a/app/modules/projects/transfer/transfer-project.jade b/app/modules/projects/transfer/transfer-project.jade index a3b0326e..4fac79aa 100644 --- a/app/modules/projects/transfer/transfer-project.jade +++ b/app/modules/projects/transfer/transfer-project.jade @@ -52,7 +52,7 @@ ) .transfer-project-options - a.button.button-gray( + a.button.button-gray.e2e-transfer-reject( ng-click="vm.transferReject(vm.token, vm.reason, $event)" href="#" title="{{'ADMIN.PROJECT_TRANSFER.REJECT' | translate}}" @@ -60,7 +60,7 @@ tg-loading="vm.loadingReject" ) - a.button.button-green( + a.button.button-green.e2e-transfer-accept( ng-click="vm.transferAccept(vm.token, vm.reason, $event)" href="#" title="{{'ADMIN.PROJECT_TRANSFER.ACCEPT' | translate}}" diff --git a/conf.e2e.js b/conf.e2e.js index 89cd1da2..c3151a09 100644 --- a/conf.e2e.js +++ b/conf.e2e.js @@ -44,7 +44,9 @@ exports.config = { projectHome: "e2e/suites/project-home.e2e.js", search: "e2e/suites/search.e2e.js", team: "e2e/suites/team.e2e.js", - discover: "e2e/suites/discover/*.e2e.js" + discover: "e2e/suites/discover/*.e2e.js", + transferProject: "e2e/suites/transfer-project.e2e.js", + compileModules: "app/modules/compile-modules/**/*.e2e.js" }, onPrepare: function() { // disable by default because performance problems on IE @@ -99,6 +101,10 @@ exports.config = { // }; // browser.addMockModule('trackMouse', trackMouse); + var argv = require('minimist')(process.argv.slice(2)); + + browser.params.glob.back = argv.back; + require('./e2e/capabilities.js'); browser.get(browser.params.glob.host); diff --git a/e2e/suites/transfer-project.e2e.js b/e2e/suites/transfer-project.e2e.js new file mode 100644 index 00000000..22b15d4b --- /dev/null +++ b/e2e/suites/transfer-project.e2e.js @@ -0,0 +1,89 @@ +var utils = require('../utils'); +var adminHelper = require('../helpers/project-detail-helper'); + +var chai = require('chai'); +var chaiAsPromised = require('chai-as-promised'); + +chai.use(chaiAsPromised); +var expect = chai.expect; + +describe('transfer project', () => { + before(async () => { + await utils.common.createProject(['user5@taigaio.demo']); + + await utils.nav + .init() + .admin() + .go(); + + adminHelper.changeOwner(); + + let lb = adminHelper.getChangeOwnerLb(); + + await lb.waitOpen(); + + lb.search('Alicia Flores'); + lb.select(0); + lb.addComment('text'); + + lb.send(); + + let changeOwnerSuccessLb = adminHelper.changeOwnerSuccessLb(); + + await utils.lightbox.open(changeOwnerSuccessLb); + + changeOwnerSuccessLb.$('.button-green').click(); + + await utils.lightbox.close(changeOwnerSuccessLb); + + await utils.common.logout(); + await utils.common.login('user5', '123123'); + }); + + it('reject', async () => { + let token = await utils.common.getTransferProjectToken('admin-aaa', 'user5'); + + browser.get(browser.params.glob.host + 'project/admin-aaa/transfer/' + token); + + await utils.common.waitLoader(); + + utils.common.takeScreenshot('transfer-project', 'step1'); + + $('.e2e-transfer-reject').click(); + + let notificationSuccess = await utils.notifications.success.open(); + + expect(notificationSuccess).to.be.true; + }); + + it('accept', async () => { + let token = await utils.common.getTransferProjectToken('admin-aaa', 'user5'); + + browser.get(browser.params.glob.host + 'project/admin-aaa/transfer/' + token); + + await utils.common.waitLoader(); + + $('.e2e-transfer-accept').click(); + + let notificationSuccess = await utils.notifications.success.open(); + + expect(notificationSuccess).to.be.true; + }); + + it('restriction page', async () => { + await utils.common.setUserLimits('user5', { + max_private_projects: 0, + max_memberships_private_projects: 0, + max_public_projects: 0, + max_memberships_public_projects: 0 + }); + + let token = await utils.common.getTransferProjectToken('admin-aaa', 'user5'); + + browser.get(browser.params.glob.host + 'project/admin-aaa/transfer/' + token); + + await utils.common.waitLoader(); + + utils.common.takeScreenshot('transfer-project', 'error'); + }); +}); diff --git a/e2e/taiga_back_cli.py b/e2e/taiga_back_cli.py new file mode 100644 index 00000000..90cef097 --- /dev/null +++ b/e2e/taiga_back_cli.py @@ -0,0 +1,64 @@ +""" +This script assumes: + - Your taiga-back virtualenv is activated + - click is installed in that virtualenv (pip install click) +""" + +import os +import django +import click +import sys + +def _configure_environment(taiga_back_path): + sys.stderr = open('/dev/null', 'w') + sys.path.append(taiga_back_path) + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") + django.setup() + globals()["taiga"] = __import__("taiga") + from django.conf import settings + settings.EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' + +@click.group() +def cli(): + pass + +@cli.command() +@click.argument("taiga_back_path", nargs=1, type=click.STRING) +@click.argument("project", nargs=1, type=click.STRING) +@click.argument("user", nargs=1, type=click.STRING) +@click.option("--reason", type=click.STRING, help="Postal code of the customer (5 digits)") +def transfer_token(taiga_back_path, project, user, reason): + """ + Generates the transfer token for the specified project and user (the reason parameter is optional).\n + As first argument you must specify the taiga-path. + """ + _configure_environment(taiga_back_path) + project = taiga.projects.models.Project.objects.get(slug=project) + user = taiga.users.models.User.objects.get(username=user) + taiga.projects.services.start_project_transfer(project, user, reason) + print(project.transfer_token) + + +@cli.command() +@click.argument("taiga_back_path", nargs=1, type=click.STRING) +@click.argument("user", nargs=1, type=click.STRING) +@click.option("--max_private_projects", type=click.STRING, help="Max number of private projects") +@click.option("--max_memberships_private_projects", type=click.STRING, help="Max number of memberships in private projects") +@click.option("--max_public_projects", type=click.STRING, help="Max number of public projects") +@click.option("--max_memberships_public_projects", type=click.STRING, help="Max number of memberships in public projects") +def update_user_limits(taiga_back_path, user, max_private_projects, max_memberships_private_projects, max_public_projects, max_memberships_public_projects): + """ + Updates the user project limits for user.\n + As first argument you must specify the taiga-path. + """ + _configure_environment(taiga_back_path) + user = taiga.users.models.User.objects.get(username=user) + user.max_private_projects = max_private_projects + user.max_memberships_private_projects = max_memberships_private_projects + user.max_public_projects = max_public_projects + user.max_memberships_public_projects = max_memberships_public_projects + user.save() + + +if __name__ == "__main__": + cli() diff --git a/e2e/utils/common.js b/e2e/utils/common.js index 30eef62b..39a6bdbb 100644 --- a/e2e/utils/common.js +++ b/e2e/utils/common.js @@ -482,3 +482,33 @@ common.createProject = async function(members = []) { await newMemberLightbox.waitClose(); } }; + +common.getTransferProjectToken = function(projectSlug, username) { + let execSync = require('child_process').execSync; + + let cliPath = path.resolve(process.cwd(), 'e2e', 'taiga_back_cli.py'); + + let result = execSync(`python ${cliPath} transfer_token ${browser.params.glob.back} ${projectSlug} ${username}`); + + return result.toString(); +}; + + +/* +max_private_projects +max_memberships_private_projects +max_public_projects +max_memberships_public_projects +*/ +common.setUserLimits = function(username, restrictions) { + let execSync = require('child_process').execSync; + + let cliPath = path.resolve(process.cwd(), 'e2e', 'taiga_back_cli.py'); + let params = ''; + + for (let restrictionKey in restrictions) { + params += `--${restrictionKey}=${restrictions[restrictionKey]} `; + } + + execSync(`python ${cliPath} update_user_limits ${browser.params.glob.back} ${username} ${params}`); +}; diff --git a/gulpfile.js b/gulpfile.js index 4d1ef7f6..350a09a4 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -220,6 +220,7 @@ gulp.task("copy-index", function() { gulp.task("template-cache", function() { return gulp.src(paths.htmlPartials) + .pipe(gulpif(isDeploy, replace(/e2e-([a-z\-]+)/g, ''))) .pipe(templateCache({standalone: true})) .pipe(gulpif(isDeploy, uglify())) .pipe(gulp.dest(paths.distVersion + "js/")) diff --git a/run-e2e.js b/run-e2e.js index e7f005f7..ffb1b9c8 100644 --- a/run-e2e.js +++ b/run-e2e.js @@ -3,8 +3,9 @@ var child_process = require('child_process'); var inquirer = require("inquirer"); var Promise = require('bluebird'); -// npm run e2e -- -s userStories, auth +// npm run e2e -- --s userStories, auth +var taigaBackPath = ''; var suites = [ 'auth', 'public', @@ -34,7 +35,7 @@ function backup() { } function launchProtractor(suit) { - child_process.spawnSync('protractor', ['conf.e2e.js', '--suite=' + suit], {stdio: "inherit"}); + child_process.spawnSync('protractor', ['conf.e2e.js', '--suite=' + suit, '--back=' + taigaBackPath], {stdio: "inherit"}); } function restoreBackup() { @@ -86,4 +87,18 @@ async function launch () { } } -launch(); +if (argv.b) { + taigaBackPath = argv.b; + launch(); +} else { + inquirer.prompt([ + { + type: 'string', + name: 'back', + message: 'Taiga back path' + } + ], function (answer) { + taigaBackPath = answer.back; + launch(); + }); +}