Hi, I am using Specflow and extentReport. How do I print the pending steps to my extent report? - specflow

I used the following code but the pending steps are not shown in the extent report. Is there a way to get the pending steps printed in the extent report?Thanks.
Code 1:
if (ScenarioContext.Current.ScenarioExecutionStatus.ToString() == "StepDefinitionPending")
{
if (stepType == "Given")
scenarioName.CreateNode<Given>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
else if (stepType == "When")
scenarioName.CreateNode<When>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
else if (stepType == "Then")
scenarioName.CreateNode<Then>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
}
I also tried this code below, but is getting null pointer exception:
Code 2:
PropertyInfo pInfo = typeof(ScenarioContext).GetProperty("TestStatus", BindingFlags.Instance | BindingFlags.NonPublic);//Getting Null value in PropertyInfo
MethodInfo getter = pInfo.GetGetMethod(nonPublic: true);
object TestResult = getter.Invoke(ScenarioContext.Current, null);
if (TestResult.ToString() == "StepDefinitionPending")
{
if (stepType == "Given")
{
scenario.CreateNode<Given>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
}
else if (stepType == "When")
{
scenario.CreateNode<When>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
}
else if (stepType == "Then")
{
scenario.CreateNode<Then>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
}
}

Try below code.
var pendingDef = ScenarioContext.Current.ScenarioExecutionStatus.ToString();
if (pendingDef == "StepDefinitionPending")
{
if (stepType == "Given")
scenario.CreateNode<Given>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
else if (stepType == "When")
scenario.CreateNode<When>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
else if (stepType == "Then")
scenario.CreateNode<Then>(ScenarioStepContext.Current.StepInfo.Text).Skip("Step Definition Pending");
}

Replace TestStatus with ScenarioExecutionStatus in your Hooks class:
PropertyInfo pInfo = typeof(ScenarioContext).GetProperty("ScenarioExecutionStatus",BindingFlags.Instance |BindingFlags.NonPublic);
MethodInfo getter = pInfo.GetGetMethod(nonPublic: true);
object TestResult = getter.Invoke(ScenarioContext.Current, null);
Because, Specflow has changed the internals of the class.

Related

How to print only the value of an enum?

enum Move { rock, paper, scissors }
var playerMove = Move.rock;
print('Player played :${playerMove.name}'); <--- this line here gives me an error
print('AI played :${aiMove.name}'); <--- this line works perfectly though
this is the error code:
Unhandled exception:
NoSuchMethodError: Class 'Move' has no instance getter 'name'.
Receiver: Instance of 'Move'
Tried calling: name
import 'dart:io';
import 'dart:math';
enum Move { rock, paper, scissors }
void main() {
while (true) {
final rng = Random();
stdout.write('Rock, paper, scissors (r,p,s): ');
final input = stdin.readLineSync();
if (input == 'r' || input == 'p' || input == 's') {
var playerMove;
if (input == 'r') {
playerMove = Move.rock;
} else if (input == 'p') {
playerMove = Move.paper;
} else {
playerMove = Move.scissors;
}
var random = rng.nextInt(3);
var aiMove = Move.values[random];
print('Input: $input');
print('Player played :${playerMove.name}');
print('AI played :${aiMove.name}');
if (playerMove == aiMove) {
print("It's a draw");
} else if (playerMove == Move.paper && aiMove == Move.rock ||
playerMove == Move.rock && aiMove == Move.scissors ||
playerMove == Move.scissors && aiMove == Move.paper) {
print('Player win');
} else {
print('You lose');
}
} else if (input == 'q') {
break;
} else {
print('Invalid input');
}
}
}
.name is an extension on enum. Dart extensions are static: they are compile-time syntactic sugar, and they therefore require that the object's type be known at compilation time.
You have code:
var playerMove;
if (input == 'r') {
playerMove = Move.rock;
}
...
var playerMove; does not specify a type for the variable, and there is no initializer to infer its type from. It therefore is implicitly declared as dynamic, and extensions on enum will not be applied to it.
You can fix it by specifying an explicit type:
Move playerMove;

Application crash while accessing data element of linked list when data is NULL

I am using following code to traverse through linked list in objective c
const MSList *calls = linphone_core_get_calls(LC);
if (calls == NULL)
{
[self dismissCtrl];
//how to check current is which screen is on
// while ((currentView == CallView.compositeViewDescription) ||
// (currentView == CallIncomingView.compositeViewDescription) ||
// (currentView == CallOutgoingView.compositeViewDescription)) {
// [self popCurrentView];
// }
} else {
linphone_call_resume((LinphoneCall *)calls->data);
while (calls)
{
if(calls->data != NULL && calls->data != nil && calls->data != (__bridge void *)((id)[NSNull null]))
{
//crash
if (linphone_call_get_state((LinphoneCall *)calls->data) == LinphoneCallIncomingReceived ||
linphone_call_get_state((LinphoneCall *)calls->data) == LinphoneCallIncomingEarlyMedia) {
[self displayIncomingCall:(LinphoneCall *)calls->data];
break;
}
}
calls = calls->next;
}
Application is crashing when entire list is not null but its data,previous or next value is NULL. I have added code to check if data is NULL but if it(data) is NULL, then i will not be able to access it and in condition itself application is crashing. How to prevent this ? I have attached screen-shot for where application is crashing and what is the value that list contains at that time.
if (calls == NULL) {
[self dismissCtrl];
//how to check current is which screen is on
// while ((currentView == CallView.compositeViewDescription) ||
// (currentView == CallIncomingView.compositeViewDescription) ||
// (currentView == CallOutgoingView.compositeViewDescription)) {
// [self popCurrentView];
// }
}
else
{
size_t count = bctbx_list_size(calls);
linphone_call_resume((LinphoneCall *)calls->data);
int i = 0;
while (calls )
{
if(i < count)
{
if ( calls->data == (__bridge void *)((id)[NSNull null]) || calls->data == NULL || calls->data == nil )
{
return;
}
LinphoneCall *objCall = (LinphoneCall *)calls->data;
LinphoneCallState state = (objCall != NULL) ? linphone_call_get_state(call) : 0;
if (state == LinphoneCallIncomingReceived ||
state == LinphoneCallIncomingEarlyMedia)
{
[self displayIncomingCall:(LinphoneCall *)calls->data];
break;
}
//calls ? calls->data : NULL
// calls = calls ? calls->next : NULL;
calls = calls->next;
i = i+1;
}
else
{
break;
}
}

IONIC/AngularJs on IOS - wrong innerWidth and innerHeight when changing screen orientation

It's my first time asking a question on stackoverflow, so i'll try to be as specific as I can. Thanks for your help.
Currently I'm developing an application for Androïd and IOS with Angular/IONIC solution.
Actually I've developed a service using cordova-plugin-screen-orientation 1.4.2 version plugin to change the orientation of my screen for some views. In fact, that work perfectly on both OS. But I also need when it's done, to catch the width and height of my device.
So there is my problem. On Android everything works, but on IOS, it looks like when I change the orientation I catch always the old values. (if I change for a landscape, I catch the previous portrait orientation values).
I tried different algorythm like the more simple : change the orientation and when it's done catch the values.
Currently I'm trying with a watcher, for the same result.
Here is my code :
class WindowService extends Service {
constructor($resource,$config, $window, Watcher) {
'ngInject';
super();
this.orientations = {
1:"portrait",
2:"landscape"
}
//imported library
this.md = new MobileDetect($window.navigator.userAgent);
// if it's a tablet Android, md.tablet() != null && md.os() == 'AndroidOS'
// if it's an iPad md.tablet() == 'iPad'
// if it's an iPhone md.mobile() == 'iPhone'
// if it's an Android phone, md.phone() != null && md.os() == 'AndroidOS'
console.log("md > ", this.md.mobile());
this.maxHeight = "100vh";
this.maxWidth = "100vw";
if (this.isAndroid()){
this.maxHeight = $window.innerHeight + "px";
this.maxWidth = $window.innerWidth + "px";
this.maxHeightWatcher = Watcher.watch(() => $window.innerHeight, innerHeight => {
this.maxHeight = $window.innerHeight + "px";
this.maxWidth = $window.innerWidth + "px";
});
}
}
setOrientation(){
this.invoke(($window) => {
if ($window.screen.unlockOrientation){
$window.screen.unlockOrientation();
if ((this.md.phone() != null && this.md.os() == 'AndroidOS') || this.md.mobile() == 'iPhone'){
$window.screen.lockOrientation('portrait');
}else if ((this.md.tablet() != null && this.md.os() == 'AndroidOS') || this.md.tablet() == 'iPad'){
$window.screen.lockOrientation('landscape');
}else {
$window.screen.lockOrientation('landscape');
}
}
});
}
//THIS S THE FUNCTION I CALL
changeOrientation(orientationId){
this.invoke(($window) => {
this.lockScreenOrientation($window, orientationId).then(res => {
console.log("changeOrientation > ", res);
}).catch(err => {
console.log("changeOrientation > ", err);
});
});
}
lockScreenOrientation($window, orientationId){
if (this.orientations[orientationId] != undefined){
if (this.orientations[orientationId] != $window.screen.orientation){
if ($window.screen.unlockOrientation){
$window.screen.unlockOrientation();
console.log("lockOrientation > ", $window.screen.lockOrientation(this.orientations[orientationId]));
return Promise.resolve(this.orientations[orientationId]);
}else{
return Promise.reject("[ERROR] cordova-plugin-screen-orientation hadn't been loaded.")
}
}else{
return Promise.resolve(this.orientations[orientationId]);
}
}else{
return Promise.reject("[ERROR] The orientation specified is Unknown.")
}
}
getDevice(){
if ((this.md.phone() != null && this.md.os() == 'AndroidOS')){
return "Android Smartphone";
}else if (this.md.mobile() == 'iPhone'){
return "iPhone";
}else if ((this.md.tablet() != null && this.md.os() == 'AndroidOS')){
return "Android Tablet";
}else if (this.md.tablet() == 'iPad'){
return "iPad";
}else
return "Unknown";
}
isSmartphone(){
if ((this.md.phone() != null && this.md.os() == 'AndroidOS') || this.md.mobile() == 'iPhone'){
return true;
}
return false;
}
isTablet(){
if ((this.md.tablet() != null && this.md.os() == 'AndroidOS') || this.md.tablet() == 'iPad')
return true;
return false;
}
isIOS() {
if (this.md.mobile() == 'iPhone' || this.md.tablet() == 'iPad')
return true;
return false;
}
isAndroid() {
if ((this.md.phone() != null && this.md.os() == 'AndroidOS')
|| (this.md.tablet() != null && this.md.os() == 'AndroidOS'))
return true;
return false;
}
getMaxHeight(){
return this.maxHeight;
}
getMaxWidth(){
return this.maxWidth;
}
}
Service.register(WindowService);
<ion-side-menu-content drag-content="false" ng-controller="HeaderController" style="height:{{view.maxHeight}};width: {{view.maxWidth}};">
....
</ion-side-menu-content>
The class Watcher is just an little extension of the basic watcher of angular. It works the same way.
[edit] Sorry I forgot to specify something : as you can see in the js code, in the constructor method, if it's IOS I just put 100vh fr the height and 100vw for the width. And I have the same result : the change from portrait to landscape keep the portrait size values.

Tic tac toe programming iOS

For some reason the function the checkForWin is returning always a NO.
Because of that I am not able to retrieve the winner.
Else if suggest a different logic to judge winner
I am using this function every time user puts up a symbol
-(BOOL) checkForWin{
NSLog(#"yes");
// HORIZONTAL WINS
if((s1.image == s2.image) & (s2.image == s3.image) & (s1.image != NULL))
{
return YES;
}
else if((s4.image == s5.image) & (s5.image == s6.image) & (s4.image != NULL))
{
return YES;
}
else if((s7.image == s8.image) & (s8.image == s9.image) & (s7.image != NULL))
{
return YES;
}
// VERTICAL WINS
else if((s1.image == s4.image) & (s4.image == s7.image) & (s1.image != NULL))
{
return YES;
}
else if((s2.image == s5.image) & (s5.image == s8.image) & (s2.image != NULL))
{
return YES;
}
else if((s3.image == s6.image) & (s6.image == s9.image) & (s3.image != NULL))
{
return YES;
}
// DIAGONAL WINS
else if((s1.image == s5.image) & (s5.image == s9.image) & (s1.image != NULL))
{
return YES;
}
else if((s3.image == s5.image) & (s5.image == s7.image) & (s3.image != NULL))
{
return YES;
}
//right now return 1 becuase we havn't implemented this yet
else{
return NO;
}
}
-(void)displayWinner{
if([self checkForWin] == YES){
if(playerToken==1){
lbl2.text =#"X is the WINNER";
} else {
lbl2.text =#"O is the WINNER";
}
}
}
Maybe you can write
if([s1.image isEqual:s2.image2]){
}
this code instead of this control statement
if((s1.image == s2.image) & (s2.image == s3.image) & (s1.image != NULL))
{
return YES;
}
The answer by Yılmaz Gürsoy is probably correct.
The reason, is that you are comparing the references to the images, and not the image data. The references are probably not the same, while the data probably is.
He is suggesting that you compare the data instead of the references.
In my oppinion though, you should actually add a member to the s# object, containing a tristate value. could be an integer.
/**
s.x is avalue indicating which image is shown (x, O, or empty)
x > 0 means 'X'
x == 0 means 'O'
x < 0 means empty
**/
and then set it when you assign the image. and check against that.
otherwise you will be wasting time comparing data, to get the exact same end result.

Including the max and offset criteria inside GORM criteriaBuilder returns an error

Can I make this code shorter?
if(count == null && from = null) {
creditAdviceList = CreditAdvice.findAll {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
}
else if(count != null && from == null) {
creditAdviceList = CreditAdvice.findAll(max: count) {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
}
else if(count == null && from != null) {
creditAdviceList = CreditAdvice.findAll(offset: from) {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
}
else if(count != null && from != null) {
creditAdviceList = CreditAdvice.findAll(max: count, offset: from) {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
}
You see, its a series if statement for each possible scenario. Imagine if one would to use also order and cache in the parameter- there will be basically 16 unique if statements!
I've tried this [more] shorter code:
creditAdviceList = CreditAdvice.findAll {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
if(count != null) {
maxResults(count)
}
if(from != null) {
firstResult(from)
}
}
But it gives me an error:
...No signature of method: grails.gorm.DetachedCriteria.maxResults() is applicable for argument types: (java.lang.Integer)...
I tried to convert offset to int, Integer, String, etc. I also omit the if statement inside the criteria, but the same error message occur.
findAll with a closure passed is using a DetachedCriteria internally, which is not the same as the result you would get from createCriteria mentioned in the docs. If groovy would find "something close" enough, it would tell you in the error message. The easiest way to deal with your max/from demands would be with simply with a map (which is the first argument passed). E.g.:
def qcfg = [:]
if (count) {
qcfg.count = count
}
if (from) {
qcfg.offset = from
}
creditAdviceList = CreditAdvice.findAll(qcfg) { ... }
mix, match, extract, shorten as you see fit
As far as I see, the only difference is the pagination options. If my eyes are not tricking me, yes, you can:
Map paginationArgs = [max: count, offset: from].findAll {
it.value != null
}
List<CreditAdvice> creditAdviceList = CreditAdvice.findAll(paginationArgs) {
ilike('id', "%$idFilter%")
.....
ilike('statusCode', statusCodeFilter)
}
You can style it differently, but basically you can build the pagination arguments first, and pass them to the findAll. No duplicated code, clearer responsability of the conditions. To clarify, I'm adding all the options and then filtering them to exclude the ones that are null.

Resources