cloudfoundry-incubator/stratos

View on GitHub
protractor.conf.js

Summary

Maintainability
A
2 hrs
Test Coverage
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const {
  SpecReporter
} = require('jasmine-spec-reporter');

const HtmlReporter = require('stratos-protractor-reporter');
const moment = require('moment');
const skipPlugin = require('./src/test-e2e/skip-plugin.js');
const globby = require('globby');
const timeReporterPlugin = require('./src/test-e2e/time-reporter-plugin.js');
const browserReporterPlugin = require('./src/test-e2e/browser-reporter-plugin.js');
const https = require('https');
const {
  ProtractorBrowserLogReporter
} = require('jasmine-protractor-browser-log-reporter');

// Test report folder name
var timestamp = moment().format('YYYYDDMM-hh.mm.ss');
var reportFolderName = timestamp + '-e2e-report';

const SECRETS_FILE = 'secrets.yaml';

const E2E_REPORT_FOLDER = process.env['E2E_REPORT_FOLDER'] || './e2e-reports/' + reportFolderName;

var fs = require('fs');
var path = require('path');
var yaml = require('js-yaml');
var browserstackHelper = require('./src/test-e2e/browserstack-helper.js');

const secretsPath = path.join(__dirname, SECRETS_FILE);
if (!fs.existsSync(secretsPath)) {
  console.log('No secrets.yaml found at ... ', secretsPath);
  console.log('Please provide a secrets.yaml, see `src/test-e2e/secrets.yaml.example` as reference.');
  process.exit(1);
}

let secrets = {};
try {
  secrets = yaml.safeLoad(fs.readFileSync(secretsPath, 'utf8'));
} catch (e) {
  console.log('Invalid e2e secrets.yaml configuration file');
  console.log(e);
  process.exit(1);
}

// This is the maximum amount of time ALL before/after/it's must execute in
let timeout = 40000;
const checkSuiteGlob = './src/test-e2e/check/*-e2e.spec.ts';

if (process.env.STRATOS_SCRIPTS_TIMEOUT) {
  timeout = parseInt(process.env.STRATOS_SCRIPTS_TIMEOUT);
  console.log('Setting allScriptsTimeout to: ' + timeout);
}

// Allow test report to show relative times of tests
const specReporterCustomProcessors = [];
let showTimesInReport = false;
if (process.env.STRATOS_E2E_LOG_TIME || browserstackHelper.isConfigured()) {
  specReporterCustomProcessors.push(timeReporterPlugin);
  showTimesInReport = true;
}

function safeExcludeSuite(suite) {
  return suite.map(file => file && file[0] !== '!' ? '!' + file : file);
}

const excludeTests = [
  '!./src/test-e2e/login/*-sso-e2e.spec.ts',
  '!' + checkSuiteGlob
];

const fullSuite = globby.sync([
  './src/test-e2e/**/*-e2e.spec.ts',
]);

const longSuite = globby.sync([
  './src/test-e2e/application/application-delete-e2e.spec.ts',
  './src/test-e2e/application/application-deploy-e2e.spec.ts',
  './src/test-e2e/application/application-deploy-local-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/cf-level/cf-users-list-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/org-level/org-users-list-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/space-level/space-users-list-e2e.spec.ts'
]);

const longServicesSuite = globby.sync([
  './src/test-e2e/marketplace/**/*-e2e.spec.ts',
]);

const manageUsersSuite = globby.sync([
  './src/test-e2e/cloud-foundry/manage-users-stepper-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/cf-level/cf-users-removal-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/org-level/org-users-removal-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/space-level/space-users-removal-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/cf-level/cf-invite-config-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/org-level/org-invite-user-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/space-level/space-invite-user-e2e.spec.ts',
  './src/test-e2e/cloud-foundry/manage-users-by-username-stepper-e2e.spec.ts'
]);

const coreSuite = globby.sync([
  './src/test-e2e/check/check-login-e2e.spec.ts',
  './src/test-e2e/endpoints/endpoints-connect-e2e.spec.ts',
  './src/test-e2e/endpoints/endpoints-e2e.spec.ts',
  './src/test-e2e/endpoints/endpoints-register-e2e.spec.ts',
  './src/test-e2e/endpoints/endpoints-unregister-e2e.spec.ts',
  './src/test-e2e/home/home-e2e.spec.ts',
  './src/test-e2e/login/login-e2e.spec.ts',
  './src/test-e2e/login/login-sso-e2e.spec.ts',
  './src/test-e2e/metrics/metrics-registration-e2e.spec.ts',
]);

const autoscalerSuite = globby.sync([
  './src/test-e2e/application/application-autoscaler-e2e.spec.ts',
]);

const cfSummaryAndBelow = globby.sync([
  './src/test-e2e/cloud-foundry/**/*-e2e.spec.ts',
  ...safeExcludeSuite(manageUsersSuite),
  ...safeExcludeSuite(longSuite),
]);

const fullMinusOtherSuites = globby.sync([
  ...fullSuite,
  ...safeExcludeSuite(longSuite),
  ...safeExcludeSuite(longServicesSuite),
  ...safeExcludeSuite(manageUsersSuite),
  ...safeExcludeSuite(coreSuite),
  ...safeExcludeSuite(autoscalerSuite),
  ...safeExcludeSuite(cfSummaryAndBelow),
]);

const config = {
  allScriptsTimeout: timeout,
  // Exclude the dashboard tests from all suites for now
  exclude: [
    './src/test-e2e/dashboard/dashboard-e2e.spec.ts',
  ],
  // Suites - use globby to give us more control over included test specs
  suites: {
    e2e: globby.sync([
      ...fullSuite,
      ...excludeTests
    ]),
    longSuite: globby.sync([
      ...longSuite,
      ...excludeTests
    ]),
    longServicesSuite: globby.sync([
      ...longServicesSuite,
      ...excludeTests
    ]),
    manageUsers: globby.sync([
      ...manageUsersSuite,
      ...excludeTests
    ]),
    core: globby.sync([
      ...coreSuite,
      ...excludeTests
    ]),
    autoscaler: globby.sync([
      ...autoscalerSuite,
      ...excludeTests
    ]),
    cfSummaryAndBelow: globby.sync([
      ...cfSummaryAndBelow,
      ...excludeTests
    ]),
    fullMinusOtherSuites: globby.sync([
      ...fullMinusOtherSuites,
      ...excludeTests
    ]),
    sso: globby.sync([
      ...fullSuite,
      '!./src/test-e2e/login/login-e2e.spec.ts',
      '!' + checkSuiteGlob
    ]),
    check: checkSuiteGlob,
  },
  // Default test suite is the E2E test suite
  suite: 'e2e',
  capabilities: {
    'browserName': 'chrome',
    chromeOptions: {
      useAutomationExtension: false,
      args: ['--no-sandbox', '--disable-dev-shm-usage', '--disable-infobars']
    },
    acceptInsecureCerts: true
  },
  directConnect: true,
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: timeout,
    print: function () { }
  },
  params: secrets,
  plugins: [],
  onPrepare() {
    // https://webdriver.io/docs/api/chromium.html#setnetworkconditions
    // browser.driver.setNetworkConditions({
    //   offline: false,
    //   latency: 2000, // Additional latency (ms).
    //   download_throughput: 500 * 1024 * 1024, // Maximal aggregated download throughput.
    //   upload_throughput: 500 * 1024 * 1024 // Maximal aggregated upload throughput.
    // });

    // Ensuer base URL does NOT end with a /
    if (browser.baseUrl.endsWith('/')) {
      browser.baseUrl = browser.baseUrl.substr(0, browser.baseUrl.length - 1);
    }

    jasmine.getEnv().addReporter(new ProtractorBrowserLogReporter());

    skipPlugin.install(jasmine);
    require('ts-node').register({
      project: 'src/test-e2e/tsconfig.e2e.json'
    });
    jasmine.getEnv().addReporter(new HtmlReporter({
      baseDirectory: E2E_REPORT_FOLDER,
      takeScreenShotsOnlyForFailedSpecs: true,
      docTitle: 'E2E Test Report: ' + timestamp,
      docName: 'index.html',
      logIgnore: [
        /\/auth\/session\/verify - Failed to load resource/g
      ]
    }).getJasmine2Reporter());
    jasmine.getEnv().addReporter(new SpecReporter({
      spec: {
        displayStacktrace: 'raw',
      },
      summary: {
        displayStacktrace: 'raw',
      },
      customProcessors: specReporterCustomProcessors
    }));
    jasmine.getEnv().addReporter(skipPlugin.reporter());
    if (showTimesInReport) {
      browserReporterPlugin.install(jasmine, browser);
      jasmine.getEnv().addReporter(browserReporterPlugin.reporter());
    }

    // Validate that the Github API url that the client will use during e2e tests is responding
    const githubApiUrl = secrets.stratosGitHubApiUrl || 'https://api.github.com';
    const path = '/repos/nwmac/cf-quick-app';
    console.log(`Validating Github API Url Using: '${githubApiUrl + path}'`);

    // This chunk can disappear when we update node to include the version of http that accepts `get(url, option, callback)`
    const hasHttps = githubApiUrl.indexOf('https://') === 0;
    const tempHost = hasHttps ? githubApiUrl.substring(8, githubApiUrl.length) : githubApiUrl;
    const hasPort = tempHost.indexOf(':') >= 0;
    const port = hasPort ? parseInt(tempHost.substring(tempHost.indexOf(':') + 1, tempHost.length)) : hasHttps ? 443 : null;
    const host = hasPort ? tempHost.replace(':' + port, '') : tempHost;

    const options = {
      host,
      port,
      path,
      accept: '*/*',
      method: 'GET',
      // Required by github to avoid 403
      headers: {
        'User-Agent': 'request'
      },
      rejectUnauthorized: false
    };

    var defer = protractor.promise.defer();
    https
      .get(options, (resp) => {
        if (resp.statusCode >= 400) {
          defer.reject('Failed to validate Github API Url. Status Code: ' + resp.statusCode);
        } else {
          defer.fulfill('Validated Github API Url successfully');
        }
      })
      .on("error", (err) => {
        defer.reject('Failed to validate Github API Url: ' + err.message);
      });

    // Print out success, errors fall through
    return defer.promise.then(res => console.log(res));
  }
};
if (process.env['STRATOS_E2E_BASE_URL']) {
  config.baseUrl = process.env['STRATOS_E2E_BASE_URL'];
}

exports.config = config;
// Should we run e2e tests in headless Chrome?
const headless = secrets.headless || process.env['STRATOS_E2E_HEADLESS'];
if (headless) {
  exports.config.capabilities.chromeOptions.args = ['--headless', '--allow-insecure-localhost', '--disable-gpu', '--window-size=1366,768', '--no-sandbox'];
}

// Browserstack support
if (browserstackHelper.isConfigured()) {
  exports.config = browserstackHelper.configure(exports.config);
}