Search code examples
javascriptseleniumjasmineprotractorreportportal

Jasmine/Selenium get file name and path of current test being run


I'm using jenkins and use a mixture of jasmine, selenium and report portal to run automated tests of my website to make sure it is running as expected.

In my .env file I can set which suite I want to test, so it could be all the tests or just a specific portion.

When I run all the tests it looks for the file like so:

all: buildTestPaths('uiTests/**/*.js'),

the buildTestPaths function:

const buildTestPaths = (subdirectoryMask) => [
    `tests/scenarios/${testPath}/${subdirectoryMask}`,
];

My protractor.conf.js file is set up like so:

/* eslint-disable no-undef */
const ReportportalAgent = require('agent-js-jasmine');
const { SpecReporter } = require('jasmine-spec-reporter');
const suiteSettings = require('./suiteSettings');
const settings = require('./settings');
const logger = require('./tests/helpers/logger');


const nodeReduceCount = 5;
let isBrowserOpen = false;

exports.config = {
    framework: 'jasmine',
    seleniumAddress: settings.seleniumHubHost,
    capabilities: {
        'shardTestFiles': true,
        'maxInstances': Math.max(settings.countOfStreams - nodeReduceCount, 1),
        'browserName': settings.browser,
        'loggingPrefs': {
            performance: 'INFO',
        },
        'moz:firefoxOptions': getFirefoxOptions(),
        'goog:chromeOptions': getChromeOptions(),
    },
    suites: [
        suiteSettings.suite,
    ],
    jasmineNodeOpts: {
        defaultTimeoutInterval: settings.jasmineTimeout,
        isVerbose: false,
        includeStackTrace: true,
        realtimeFailure: false,
    },
    onPrepare: async () => {
        const jasmineEnv = jasmine.getEnv();
        const capabilities = await browser.getCapabilities();
        global.consoleReporter = [];

        console.log(capabilities);

        if (!settings.useReportPortal) {
            registerReporter(jasmineEnv);
        } else {
            registerConsoleReporter(jasmineEnv);
        }

        jasmineEnv.beforeEach(async () => {
            await console.log(jasmine.getEnv().currentSpec.description);

            jasmine.DEFAULT_TIMEOUT_INTERVAL = settings.jasmineTimeout;

            if (isBrowserOpen) {
                browser.restart();
            }

            await browser.driver.manage().window().setSize(settings.viewPort.width, settings.viewPort.height);

            isBrowserOpen = true;

            await logger.logMessage(`Opening Link ${settings.newPlanUrl()}`);

            if (suiteSettings.currentSuite === 'criticalTests') {
                process.env.RUN_WITH_SERVICE_WORKER = true;
            } else {
                process.env.RUN_WITH_SERVICE_WORKER = false;
            }

            await browser.waitForAngularEnabled(false);
            await browser.get(settings.newPlanUrl());
        });
    },
};

function registerReporter(jasmineEnv) {
    jasmineEnv.addReporter(new SpecReporter({
        spec: {
            displayStacktrace: true,
        },
    }));

    const config = {
        id: browser.params.id,
        ...settings.reportPortal,
    };
    const agent = new ReportportalAgent(config);
    const reporter = agent.getJasmineReporter();

    jasmineEnv.afterAll(async (done) => {
        await agent.getPromiseFinishAllItems(agent.tempLaunchId);

        done();
    });

    global.reporter = reporter;
    jasmineEnv.addReporter(reporter);

    return agent;
}

function registerConsoleReporter(jasmineEnv) {
    jasmineEnv.afterEach(async () => {
        await browser.takeScreenshot().then((png) => {
            const testSuite = settings.currentSuite;
            const date = new Date();
            const currentDay = `(Time-${date.getHours()}-${date.getMinutes()}-${date.getSeconds()})`;
            logger.writeScreenShot(png, `screenshots/${currentDay}_${testSuite}.png`);
        });
    });
    jasmineEnv.afterAll(async () => {
        await console.log('\n---------------------------------');
        await console.log('Test Results');
        await global.consoleReporter.forEach((testResult) => {
            console.log(testResult);
        });
        await console.log('---------------------------------');
    });
}

function getFirefoxOptions() {
    const options = {};

    if (settings.headless) {
        options.args = ['--headless'];
    }

    return options;
}

function getChromeOptions() {
    const options = {
        args: [
            '--disable-gpu',
            '--no-sandbox',
            '--disable-extensions',
            '--disable-dev-shm-usage',
            '--disable-infobars',
        ],
    };

    if (settings.headless) {
        options.args.push('--headless');

        options.perfLoggingPrefs = {
            enableNetwork: true,
        };
    }

    return options;
}

What I'm trying to do is log the specs of the current test being run, i.e. file name and the path of the test when I'm running 'all', however I'm really not sure how to go about this. Is there something I can put in the:

     jasmineEnv.beforeEach(async () => {

function so that it will log these specs of the test it is currently running?

TIA for any assistance

Edit:

So I've noticed when running my tests it will sometimes log the test path, I couldn't figure out where it was coming from. I discovered that it comes from a file within my node modules, called taskLogger.js from within protractor

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const os = require("os");
const logger_1 = require("./logger");
let logger = new logger_1.Logger('testLogger');
class TaskLogger {
    /**
     * Log output such that metadata are appended.
     * Calling log(data) will not flush to console until you call flush()
     *
     * @constructor
     * @param {object} task Task that is being reported.
     * @param {number} pid PID of process running the task.
     */
    constructor(task, pid) {
        this.task = task;
        this.pid = pid;
        this.buffer = '';
        this.insertTag = true;
        this.logHeader_();
    }
    /**
     * Log the header for the current task including information such as
     * PID, browser name/version, task Id, specs being run.
     *
     * @private
     */
    logHeader_() {
        let output = 'PID: ' + this.pid + os.EOL;
        if (this.task.specs.length === 1) {
            output += 'Specs: ' + this.task.specs.toString() + os.EOL + os.EOL;
        }
        this.log(output);
    }
    /**
     * Prints the contents of the buffer without clearing it.
     */
    peek() {
        if (this.buffer) {
            // Flush buffer if nonempty
            logger.info(os.EOL + '------------------------------------' + os.EOL);
            logger.info(this.buffer);
            logger.info(os.EOL);
        }
    }
    /**
     * Flushes the buffer to stdout.
     */
    flush() {
        if (this.buffer) {
            this.peek();
            this.buffer = '';
        }
    }
    /**
     * Log the data in the argument such that metadata are appended.
     * The data will be saved to a buffer until flush() is called.
     *
     * @param {string} data
     */
    log(data) {
        let tag = '[';
        let capabilities = this.task.capabilities;
        tag += (capabilities.logName) ? capabilities.logName :
            (capabilities.browserName) ? capabilities.browserName : '';
        tag += (capabilities.version) ? (' ' + capabilities.version) : '';
        tag += (capabilities.platform) ? (' ' + capabilities.platform) : '';
        tag += (capabilities.logName && capabilities.count < 2) ? '' : ' #' + this.task.taskId;
        tag += '] ';
        data = data.toString();
        for (let i = 0; i < data.length; i++) {
            if (this.insertTag) {
                this.insertTag = false;
                // This ensures that the '\x1B[0m' appears before the tag, so that
                // data remains correct when color is not processed.
                // See https://github.com/angular/protractor/pull/1216
                if (data[i] === '\x1B' && data.substring(i, i + 4) === '\x1B[0m') {
                    this.buffer += ('\x1B[0m' + tag);
                    i += 3;
                    continue;
                }
                this.buffer += tag;
            }
            if (data[i] === '\n') {
                this.insertTag = true;
            }
            this.buffer += data[i];
        }
    }
}
exports.TaskLogger = TaskLogger;

it has a d.ts file that goes with it:

export declare class TaskLogger {
    private task;
    private pid;
    private buffer;
    private insertTag;
    /**
     * Log output such that metadata are appended.
     * Calling log(data) will not flush to console until you call flush()
     *
     * @constructor
     * @param {object} task Task that is being reported.
     * @param {number} pid PID of process running the task.
     */
    constructor(task: any, pid: number);
    /**
     * Log the header for the current task including information such as
     * PID, browser name/version, task Id, specs being run.
     *
     * @private
     */
    private logHeader_();
    /**
     * Prints the contents of the buffer without clearing it.
     */
    peek(): void;
    /**
     * Flushes the buffer to stdout.
     */
    flush(): void;
    /**
     * Log the data in the argument such that metadata are appended.
     * The data will be saved to a buffer until flush() is called.
     *
     * @param {string} data
     */
    log(data: string): void;
}

So the main bit of interest to me is:

output += 'Specs: ' + this.task.specs.toString() + os.EOL + os.EOL;

is there a way I can use this in my jasmineEnv.beforeEach function within my protractor.conf.js file?


Solution

  • Just add these 2 lines to your onPrepare

    let config = await browser.getProcessedConfig()
            console.log(config.specs)
    

    Note, onPrepare must be async in order to use await in it

    Also you may need to filter the array of specs, as jasmine also registers some internal files that it runs