Source: RallyLogger.js

/**
 * Created by 212392192 on 7/22/16.
 *
 * A util to help query and update rally using rally-node
 */

(function(){

    var rally = require('rally');
    queryUtils = rally.util.query;
    refUtils = rally.util.ref;
    logger = require('./Logger.js');
    rallylog = require("./RallyLog.js");
    var apiKey;
    if (process.env.apiKey != undefined) {
        apiKey = process.env.apiKey;
        rallylog.info('apikey is ' + "\'" + apiKey + "\'");
    }
    else {
        rallylog.info('no apiKey defined');
        return;
    }

    if (process.env.method != undefined)
        var method = process.env.method;
    else
        var method = "Automated";   // default workspace
    var project = process.env.project;
    var ws = process.env.rallyworkspace
    var proxy = process.env.rallyProxy;
    var baseUrl = 'https://rally1.rallydev.com/slm/webservice/v2.0/';
    var type;
    if(process.env.type != undefined){
        type = process.env.type.trim();
        if( ((type != 'Acceptance') && (type != 'Functional') && (type != 'Performance') && (type != 'Regression') &&
            (type != 'Usability') && (type != 'User Interface'))){
            console.log('Typo in the .env file type= : setting Type to default value "Acceptance"');
            rallylog.info('Typo in the .env file type= ' + "\'" + type + "\'" + ' setting Type to default value "Acceptance"');
            type = "Acceptance"
        }
    } else {
        type = 'Acceptance'
    }

    restApi = rally({
        apiKey: apiKey, //preferred, required if no user/pass, defaults to process.env.RALLY_API_KEY
        apiVersion: 'v2.0', //this is the default and may be omitted
        server: 'https://rally1.rallydev.com',  //this is the default and may be omitted
        requestOptions: {
            headers: {
                'X-RallyIntegrationName': 'Rally Result Logger for ProUI',  //while optional, it is good practice to
                'X-RallyIntegrationVendor': 'GE Digital',             //provide this header information
                'X-RallyIntegrationVersion': '1.0'
            },
            proxy: proxy
        }
    });
    /**
     * RallyLogger
     */
    var RallyLogger = function () {
        return {
            /**
             * Get the rally object ref in form of '/[Object]/12345678', e.g. '/testfolder/59651570691'
             * @param objType     The object type.  e.g. 'project', 'testfodler', 'testcase' etc.
             * @param objName     The name of the object, e.g. 'QE Automation Engineering'
             * @param project/ws  The project/workspace specified in .env  i.e. 'GE Digital'/'QE Automation Engineering'
             * @param callback  The object reference of the requested object if found or 'NOT_FOUND' otherwise.
             */
            getObjectRef: function(objType, objName, project, ws, callback) {
                //by object name
                if(objName == '') {
                    console.log('No workspace/project provided - using default');
                    logger.info('No workspace/project provided - using default');
                    callback('');
                } else {
                    var qr = queryUtils.where('name', '=', objName);
                    restApi.query({
                        type: objType, //the type to query
                        start: 1, //the 1-based start index, defaults to 1
                        pageSize: 200, //the page size (1-200, defaults to 200)
                        limit: Infinity, //the maximum number of results to return- enables auto paging
                        fetch: ['FormattedID', 'Name', 'TestCases', 'ObjectID', 'LastResult', 'RevisionHistory', 'Steps'],
                        query: qr,
                        scope: {
                            workspace: ws,
                            project: project
                        }
                    }, function (error, result) {
                        if (error) {
                            console.log(error);
                            throw error;
                        } else {
                            //console.log(result.Results);
                            var last_run = false;
                            var test_case_result_id = 0;
                            var revision_history_ref = '';
                            var obj = JSON.parse(JSON.stringify(result.Results));
                            if (obj.length > 0) {
                                if (obj[0].LastResult != undefined) {
                                    if (obj[0].LastResult == null) {
                                        last_run = false;
                                    } else {
                                        last_run = true;
                                        test_case_result_id = obj[0].LastResult._ref;
                                        test_case_result_id = test_case_result_id.split('/');
                                        test_case_result_id = test_case_result_id[7];
                                    }
                                } else {
                                    last_run = false;
                                }
                                if (obj[0].RevisionHistory != undefined) {
                                    revision_history_ref = obj[0].RevisionHistory._ref;
                                }
                                // if(obj[0].Steps != undefined) {
                                //     if (obj[0].Steps.Count > 0){
                                //         //console.log('test case has ' + obj[0].Steps.Count + ' steps');
                                //     } else {
                                //         //console.log('test case has no steps');
                                //     }
                                // }
                                var myref = obj[0]._ref; var id = result.Results[0].ObjectID; var ref = refUtils.getRelative(myref)
                                callback({ref:ref, id:id, last_run:last_run, test_case_result_id:test_case_result_id, revision_history_ref:revision_history_ref});
                            } else {
                                callback('NOT_FOUND');
                            }
                        }
                    });
                }
            },
            /**
             * Get the rally User permissions (workspace/projects able to edit), and owner ID information
             * @param type     The object type - only 2 used: 'workspace' and 'project'
             * @param object   The name of the object, e.g. 'QE Automation Engineering'
             * @param callback  The object reference of the requested object if found or 'NOT_FOUND' otherwise.
             */
            UserPermissions: function(type, object, callback) {
                var proj_ref='';
                var ws_ref = '';
                restApi.query({
                    type: 'userpermission', //the type to query
                    start: 1, //the 1-based start index, defaults to 1
                    pageSize: 200, //the page size (1-200, defaults to 200)
                    limit: Infinity, //the maximum number of results to return- enables auto paging
                    fetch: ['Workspace', 'Name', 'Project', 'ObjectID', 'User'], //the fields to retrieve
                    scope: {
                    }
                }, function (error, result) {
                    if (error) {
                        console.error(error);
                        callback(error);
                    } else {
                        var obj = JSON.parse(JSON.stringify(result.Results));
                        if (obj.length > 0) {
                            var myref = obj[0].User._ref;
                            var ref = refUtils.getRelative(myref);
                            var owner_id = obj[0].User.ObjectID;
                            for(var i=0; i < obj.length; i++) {
                                if(type == 'workspace') {
                                    if(obj[i].Workspace.Name == object){
                                        //console.log('found workspace - user has permissions');
                                        ws_ref = obj[i].Workspace._ref;
                                        ws_ref = refUtils.getRelative(ws_ref);
                                        break;
                                    }
                                } else if(type == 'project') {
                                    if(obj[i].Project != undefined) {
                                        if (obj[i].Project.Name == object) {
                                            //console.log('found project - user has permissions');
                                            proj_ref = obj[i].Project._ref;
                                            proj_ref = refUtils.getRelative(proj_ref);
                                            break;
                                        }
                                    }
                                }
                            }
                            if((i == obj.length) && (object != '')) {
                                callback('NOT_FOUND');
                            } else {
                                callback({owner_id:owner_id, wsRef:ws_ref, projRef:proj_ref});
                            }
                        } else {
                            callback('NOT_FOUND');
                        }
                    }
                });
            },
            /**
             * Get a rally user story and test set reference
             * @param USTS   the user story. e.g. 'US6400' or testset e.g. 'TS20'
             * @param ws/proj          the workspace and project the user story belongs to
             * @param callback    the user story ref in the form of '/hierarchicalrequirement/1234567889'
             */
            getUSTSRef: function (USTS, ws, proj, type, callback) {
                if(USTS == '') {
                    callback({id: ''});
                } else {
                    var qr = queryUtils.where('FormattedID', '=', USTS);
                    restApi.query({
                        type: type,
                        start: 1, //the 1-based start index, defaults to 1
                        pageSize: 200, //the page size (1-200, defaults to 200)
                        limit: Infinity, //the maximum number of results to return- enables auto paging
                        fetch: ['Name', 'ObjectID'],//, 'ScheduleState', 'PlanEstimate', 'Iteration'],
                        query: qr,
                        scope: {
                            workspace: ws,
                            project: proj
                        }
                    }, function (error, result) {
                        if (error) {
                            console.log(error);
                            throw error;
                        } else {
                            //console.log('query USTS' + result.Results);
                            var obj = JSON.parse(JSON.stringify(result.Results));
                            if(obj.length > 0) {
                                var myref = obj[0]._ref;
                                var ref = refUtils.getRelative(myref);
                                var id = obj[0].ObjectID;
                                //console.log('USTS ref: ' + refUtils.getRelative(myref));
                                callback({ref: ref, id: id});
                            } else {
                                ref = ''; id='';
                                callback({ref: ref, id: id});
                            }

                        }
                    });
                }
            },
            /**
             * Create a test folder
             * @param name test folder name from feature file
             * @param ws   the workspace
             * @param proj the project
             * @param callback  returns the objectID of the newly created test folder
             */
            createTestPlan: function (name, ws, proj, callback) {
                restApi.create({
                    type: 'testfolder', //the type to create
                    data: {
                        Name: name,
                    },
                    fetch: ['FormattedID', 'ObjectID'],  //the fields to be returned on the created object
                    scope: {
                        workspace: ws,
                        project: proj
                    },
                    requestOptions: {} //optional additional options to pass through to request
                }, function (error, result) {
                    if (error) {
                        console.log(error);
                        throw error;
                    } else {
                        //console.log('created test plan: ' + result.Results);
                        var testfolderRef = refUtils.getRelative(JSON.parse(JSON.stringify(result.Object)));
                        var id = result.Object.ObjectID
                        //console.log("new test folder ref" + testfolderRef);
                        callback({id: id});

                    }
                });
            },
            /**
             * Create a testcase
             * @param opts - contains kObject (duration),
             * and tcObject (parent folder id, description, name, user story, owner), and error
             * @param ws/project workspace and project of the test case
             * @param callback  returns the testcase ObjectID
             */
            createTestcase: function (opts, ws, project, callback) {
                //console.log('inside create test case function');
                if (opts.kObj.duration == undefined) {
                    opts.kObj.duration = 0;
                }
                if (opts.tcObj.glb_folder_id == null) {
                    opts.tcObj.glb_folder_id = 0;
                }
                if (opts.tcObj.test_case_description == "") {
                    opts.tcObj.stepsArray = opts.tcObj.stepsArray.toString().split('"').join('');
                    opts.tcObj.test_case_description = "N/A<br>" + opts.tcObj.stepsArray;
                } else {
                    opts.tcObj.stepsArray = opts.tcObj.stepsArray.toString().split('"').join('');
                    opts.tcObj.test_case_description = opts.tcObj.test_case_description + "<br>" + opts.tcObj.stepsArray;
                }
                restApi.create({
                    type: 'testcase', //the type to create
                    data: {
                        Name: opts.tcObj.test_case_name,
                        Description: opts.tcObj.test_case_description,
                        Method: method,
                        TestFolder: opts.tcObj.glb_folder_id,
                        WorkProduct: opts.tcObj.User_Story,
                        Owner: opts.tcObj.owner,
                        Notes: opts.error,
                        Type: type
                    },
                    fetch: ['FormattedID', 'ObjectID'],
                    scope: {
                        workspace: ws,
                        project: project
                    }
                }, function (error, result) {
                    if (error) {
                        console.log('error: ' + error);
                        //throw error;
                        callback({id: ''});
                    } else {
                        //console.log("created test case: " + JSON.parse(JSON.stringify(result.Object)));
                        var testcaseRef = refUtils.getRelative(JSON.parse(JSON.stringify(result.Object)));
                        opts.tcObj.glb_test_case_id = result.Object.ObjectID;
                        //console.log("new testcase ref" + testcaseRef);
                        callback({id: opts.tcObj.glb_test_case_id});
                    }
                });
            },
            /**
             * Create a testcase result of a given testcase.
             * @param opts     - contains duration, status, testcase ID, buildnumber
             * @param ws/proj  - workspace and project IDs
             * @param callback - returns id off the test case result created
             */
            createTestcaseResult: function (opts, ws, proj, callback) {
                if((opts.resp.duration == undefined) || (opts.resp.duration == 'undefined')
                    || (opts.resp.duration == null) || (opts.resp.duration == NaN) || (opts.resp.duration == 'NaN')) {
                    opts.resp.duration = 0;
                } else if (opts.resp.duration > 9999999999) {
                    opts.resp.duration = 9999999999;
                }
                if (opts.resp.status == 'passed') {
                    opts.resp.status = 'Pass';
                } else if (opts.resp.status == "failed") {
                    opts.resp.status = 'Fail';
                } else if (opts.resp.status == "skipped") {
                    opts.resp.status = 'Inconclusive';
                    duration = 0;
                }
                restApi.create({
                    type: 'testcaseresult', //the type to create
                    data: {
                        TestCase: opts.tcObj.glb_test_case_id,
                        Build: opts.tcObj.build_num,
                        Duration: opts.resp.duration,
                        Verdict: opts.resp.status,
                        Date: (new Date).toISOString(),
                        TestSet: opts.resp.id
                    },
                    fetch: ['ObjectID'],  //the fields to be returned on the created object
                    scope: {
                        workspace: ws,
                        project: proj
                    }
                }, function (error, result) {
                    if (error) {
                        console.log(error);
                        throw error;
                    } else {
                        //console.log(result.Object);
                        var id = result.Object.ObjectID;
                        callback({id:id});
                    }
                });
            },
            /**
             * Update the result of a given testcase.
             * @param opts
             * @param ws
             * @param callback
             */
            updateTestCaseResult: function(opts, ws, proj, callback) {
                if (opts.resp.duration == undefined) {
                    opts.resp.duration = 0;
                }
                if ((opts.resp.duration != undefined) && (opts.resp.duration > 9999999999)) {
                    opts.resp.duration = 9999999999;
                }
                if (opts.resp.status == 'passed') {
                    opts.resp.status = 'Pass';
                } else if (opts.resp.status == "failed") {
                    opts.resp.status = 'Fail';
                } else if (opts.resp.status == "skipped") {
                    opts.resp.status = 'Inconclusive';
                    opts.resp.duration = 0;
                }
                restApi.update({
                    ref: '/testcaseresult/' + opts.tcObj.glb_test_result_id,
                    data: {
                        Build: opts.tcObj.build_num,
                        Duration: opts.resp.duration,
                        Verdict: opts.resp.status,
                        Date: (new Date).toISOString(),
                        TestCase:opts.tcObj.resp.ref,
                        TestSet: opts.resp.id
                    },
                    fetch: [],  //the fields to be returned on the created object
                    scope: {
                        workspace: ws,
                        project: proj
                    },
                    requestOptions: {} //optional additional options to pass through to request
                }, function (error, result) {
                    if (error) {
                        console.log(error);
                    } else {
                        //console.log(result.Object);
                        callback();
                    }
                });
            },
            /**
             * Update the testcase of a given testcase.
             * @param opts
             * @param ws
             * @param callback
             */
            updateTestCase: function (opts, ws, proj, callback) {
                if (opts.tcObj.test_case_description == "") {
                    opts.tcObj.stepsArray = opts.tcObj.stepsArray.toString().split('"').join('');
                    opts.tcObj.test_case_description = "N/A<br>" + opts.tcObj.stepsArray;
                } else {
                    opts.tcObj.stepsArray = opts.tcObj.stepsArray.toString().split('"').join('');
                    opts.tcObj.test_case_description = opts.tcObj.test_case_description + "<br>" + opts.tcObj.stepsArray;
                }
                var request = require('request-promise');
                restApi.update({
                    ref: opts.tcObj.resp.ref, //the type to create
                    data: {
                        WorkProduct: opts.resp.id,
                        Method: method,
                        Owner: opts.owner,
                        Notes: opts.error,
                        Type: type,
                        Description: opts.tcObj.test_case_description
                    },
                    fetch: ['FormattedID', 'Project'],  //the fields to be returned on the created object
                    scope: {
                        workspace: ws,
                        project: proj
                    }
                }, function (error, result) {
                    if (error) {
                        console.log(error);
                        callback( error );
                    } else {
                        //console.log(result.Object);
                        callback();
                    }
                });
            },
            /**
             * Update Test Set to add test case
             * @param tcObj             object w/  User_Story, resp, j, test_case_name, test_case_description, glb_folder_id,
             * build_num, testset, glb_test_case_id, glb_test_result_id, last_run, glb_i_length, glb_j_length
             * @param resp              resonse from query TestSet
             * @param callback          callback on error and http response
             */
            updateTestSet: function(tcObj, resp, callbck){
                var request = require('request-promise');
                var to_return;
                if(resp.id == ''){
                    to_return = {
                        id:'', status:resp.status, duration:resp.duration, glb_test_case_id:resp.glb_test_case_id,
                        glb_folder_id:tcObj.glb_folder_id, json:resp.json, i:resp.i, j:resp.j, k:k
                    };
                    callbck(to_return);
                } else {
                    to_return = {
                        id: resp.id, status: resp.status, duration: resp.duration,
                        glb_test_case_id: resp.glb_test_case_id, glb_folder_id: tcObj.glb_folder_id, json: resp.json,
                        i: resp.i, j: resp.j, k: k
                    };
                    var options = {
                        method: 'POST',
                        url: 'https://rally1.rallydev.com/slm/webservice/v2.x/TestSet/' + resp.id + '/TestCases/add?fetch=true',
                        headers: {zsessionid: apiKey},
                        proxy: proxy,
                        body: '{"CollectionItems":[{"_ref":"/testcase/' + tcObj.glb_test_case_id + '"}]}'
                    };
                    request(options)
                        .then(function (body, error) {
                            //console.log('updated test set: ' + body);
                            callbck(to_return);
                        });
                }
            }
        }
    };
    module.exports = new RallyLogger();
})();