Create a custom reporter

Use SRF's public API to create your own custom reporter. Use your custom reporter when running Selenium tests remotely, instead of calling SRF's native reporter.

Disable the SRF reporter

Before you create your own custom reporter, disable SRF's native reporter in your test.

To do this, add the reportingEnabled capability to your script, and set the value to false.

For more details, see Reporting capability reference.

Back to top

Create your custom reporter

Create and configure your custom reporter by updating your Selenium script.

Do the following:

  1. Send a POST REST request to the SRF_REPORTER_URL. Include the /api/v1/reporter/reports path and your client ID and secret, as shown in the example below.

    The POST response will contain the reportID definition, shown as obj.session in the example below. Add the SRF_REPORT_ID capability to your script, with this reportID as its value.

  2. Define steps for each of your test steps.

    For each step, send a POST REST request to the SRF URL, with an additional suffix as follows:

    <server-url>/api/v1/reporter/reports/<reportId>/steps

    Include the step details in the body, as described in the table below.

    For example, see Step details example.

    Note: The reported steps will be displayed in the script run results only once a Selenium session is open in this script (after you build a web driver).

  3. Define a request for your report status. Do the following:

    1. Send a PUT REST request to the SRF URL, with an additional suffix, as follows:

      <server-url>/api/v1/reporter/reports/<session-id>

      Where the <session-id> is the value you received in the response to the create session call in the previous step.

    2. Send the expected status in the body of the request, using the following syntax:

      {"status": <status value>;}

      Where the <status value> can be any of the following:

      • completed
      • success
      • failed
      • warning
      • errored
      • cancelled
  4. Add the endReport API to close the session.

    For example:

    Q.nfcall(client["del"].bind(client), "/api/v1/reporter/reports/" + reportID);

For a full code sample, see JavaScript reporter sample with framework

For more details, see the Reports section of the SRF interactive API help.

Back to top

JavaScript reporter sample with framework

The following code sample runs a test on Chrome and Ubuntu in a custom framework, using a custom-built reporter.

var webdriver = require('selenium-webdriver'),
By = webdriver.By;
var HttpsProxyAgent = require('https-proxy-agent');
// integ demo
var srfClientId = "<PLACEHOLDER>";
var srfClientSecret ="<PLACEHOLDER>";
var srfServerUrl = "<PLACEHOLDER>";
var testName;
var MyFramework;
var capabilities = {
browserName: 'chrome',
version: 'latest',
testName: "Custom Reporter Api",
resolution: "1024x768",
platform: "Windows 10",
SRF_CLIENT_ID: srfClientId,
SRF_CLIENT_SECRET: srfClientSecret
};
before((done) => {
MyFramework.start(done);
});
describe('SRF Test', function () {
it('test case ', function (done) {
MyFramework.startTest('test case 1', capabilities, done);
MyFramework.seleniumStep("get", "http://example.com/");;
MyFramework.seleniumStepWithSnapshot("findElement", webdriver.By.partialLinkText("More"));
MyFramework.endTest(done);
});
});
after((done) => {
MyFramework.end(done);
});
(function () {
var clients = require('restify-clients');
var Q = require("q");
var promiseChain;
var driver;
 
MyFramework = {
start:(done) => {
console.log("###~> Starting suite");
MyFramework.lastStatus = "success";
promiseChain = ReporterApi.startReport().then((reportId) => {
return ReporterApi.addStep({ description: "Meaningful description", role: "call-me-as-you-wish-begin" });
}).then(() => {
console.log("Started");
done && done();
});
},
end:(done) => {
promiseChain = promiseChain.then(() => {
return ReporterApi.addStep({ description: "Meaningful description", role: "call-me-as-you-wish-end", status: MyFramework.lastStatus });
}).then(() => {
console.log("<~### Suite ended");
return ReporterApi.endReport().then(() => done && done());
}).catch(err => { console.log ("Error:", err); });
},
startTest: (title, capabilities, done) => {
console.log("###~> Starting test case", title);
capabilities.automaticReport = "off";
MyFramework.lastStatus = "success";
promiseChain = promiseChain.then(() => {
return ReporterApi.addStep({ description: title, role: "test-case-begin" });
}).then(() => {
capabilities.SRF_REPORT_ID = ReporterApi.reportId;
driver = new webdriver.Builder().withCapabilities(capabilities)
.usingServer(srfServerUrl + "/wd/hub")
.usingHttpAgent(new HttpsProxyAgent(process.env.http_proxy))
.build();
 
webdriver.promise.controlFlow().on('uncaughtException', function handleError(e) {
console.error('ERROR: ' + e);
driver.quit().finally(done);
webdriver.promise.controlFlow().removeListener('uncaughtException', handleError);
});
console.log("Test case started");
});
},
endTest: (done) => {
promiseChain = promiseChain
.then(() => {
return driver && driver.quit();
}).then(() => {
return ReporterApi.addStep({ description: "ggg", role: "test-case-end", status: MyFramework.lastStatus });
}).then(() => done && done())
.catch(err => { console.log ("Error:", err); });
},
 
seleniumStep: (method, ...arguments) => {
promiseChain = promiseChain.then(() => {
console.log("---> Selenium step: driver.%s (%s); with no snapshot", method, arguments.join());
return MyFramework._seleniumStep(method, arguments);
});
return promiseChain;
},
 
seleniumStepWithSnapshot: (method, ...arguments) => {
promiseChain = promiseChain.then(() => {
console.log("---> Selenium step: driver.%s (%s); taking snapshot", method, arguments.join());
return driver.takeScreenshot();
}).then((image, err) => {
return MyFramework._seleniumStep(method, arguments, image.toString('base64'));
});
return promiseChain;
},
 
_seleniumStep: (method, argsArray, snapshot) => {
var error;
var startTime;
return Q.when().then(() => { startTime = new Date().getTime(); })
.then(() => {
return driver[method].apply(driver, argsArray);
}).catch((err) => {
error = err;
MyFramework.lastStatus = "failed";
}).then(() => {
var duration = new Date().getTime() - startTime;
return ReporterApi.addStep({
description: "Selenium step: " + method + "(" + argsArray.join() + " )",
status: error ? "failed" : "success",
role: "regular",
snapshot: snapshot,
errors: error ? [ error ] : undefined,
durationMs: duration
});
}).then(() => { console.log("<--- Selenium step ended"); });
}
};
 
var client;
var ReporterApi = {
startReport: () => {
console.log("Starting report on", srfServerUrl);
client = clients.createJsonClient({ url: srfServerUrl });
ReporterApi.currStepIndex = 1;
return ReporterApi._sendRequest("post", "/api/v1/reporter/reports", { clientId: srfClientId, clientSecret: srfClientSecret })
.then((result) => {
console.log("Report started");
ReporterApi.reportId = result.session;
return result.session;
}).catch(err => {console.log("start error:", err); });
},
addStep: (step) => {
console.log("Adding step");
step.index = ReporterApi.currStepIndex++;
return ReporterApi._sendRequest("post", "/api/v1/reporter/reports/" + ReporterApi.reportId + "/steps", step).catch(err => {console.log("add step error:", err); });
},
 
endReport: () => {
console.log("Ending report");
return ReporterApi._sendRequest("del", "/api/v1/reporter/reports/" + ReporterApi.reportId).catch(err => {console.log("end error:", err); });
},
 
_sendRequest: (method, url, body) => {
console.log("Request:", method, url);
return Q.when().then(() => {
if (body)
return Q.nfcall(client[method].bind(client), url, body);
return Q.nfcall(client[method].bind(client), url);
}).catch((err) => { console.log("Error:", err); })
.spread((req, res, obj) => {
console.log('Response: %d -> %j', res && res.statusCode, obj);
return obj;
});
}
};
})();

Back to top

See also: