0

Working on an E2E using Ramda. I'm not getting how to convert a simple IF condition using Ramda Cond.

Code using If :

if (constraint == 'required') {
  // then only do something
  await waitForElementToBeClickable(constraintElement);
  await constraint.click();
}

I don't want the else because I want the action to happen only if the constraint is present.

I've done this so far using constraint but it's not working :

await waitForElementToBeClickable(cond([
  [equals('required'), always(constraintElement)],
])(constraint), this.browser);

const constraintCheck = cond([
  [equals('required'), () => constraintElement.click()],
]);
await constraintCheck(constraint);

In some cases, I do not want to pass the constraint. Then the Condition should not execute at all. But it is always getting executed and throwing the error : Cannot read property 'isPresent' of Undefined.

pkdq
  • 191
  • 1
  • 14

2 Answers2

1

I think perhaps there's some confusion here (beyond what customcommander rightly points out about the type of constraint.)

One of the features Ramda tries to offer is to allow us to program with expressions rather than statements. Especially concerning are control-flow statements. But a statement that looks like this:

let foo
if (condition) {
  foo = 'bar'
} else {
  foo = 'baz'
}

already has a standard expression form:

const foo = condition ? 'bar' : 'baz'

Ramda does not really try to offer an alternative to this. But there is another way we might try to use if:

let foo
if (test(val)) {
  foo = bar(val)
} else {
  foo = baz(val)
}

Here, when working with functions, Ramda offers a convenient shorthand:

const getFoo = ifElse(test, bar, baz)
// ... later
const foo = getFoo(val)

(And if you just want to return val in the case the test fails, you can use the shorthand:

   const foo = when(test, bar)

Or if you want val when the test succeeds, you can do

   const foo = unless(test, baz)

)

While it might be slightly more expressive to turn the code into

const foo = ifElse(test, bar, baz)(val)

That's not the main point. The rationale for ifElse is to use it in creating the reusable function ifElse(test, bar, baz). (cond is just the same, just offering a sequence of condition-consequent pairs instead of one if and one else.)

Note one important feature to this: the test function, the function to run if it's true, and the one to run if it's false all have the same signature. If one of them takes three parameters, then they all should accept three parameters. And while the test should return a boolean, the other two can have any return type, but each should have the same return type as the other.

So one can use a thunk, as you try with () => constraintElement.click(), it is mostly a misuse of the Ramda feature. It probably gains you nothing in your code.


It's still not clear what you're trying to do with the conversion from an if statement to ifElse or cond. Please feel free to add an update to your question explaining more fully what you're trying to do, and what problem you're trying to solve with this conversion, someone will probably be able to offer some help. But make sure you clarify what constraint and constraintElement are and what waitForElementToBeClickable resolves to. Right now it's fairly confusing.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
0

By looking at your example, it seems that you use constraint both as a string and an object which may cause unnecessary confusion. I know you can implement a toString() method on an object but I'm not sure if that always plays nicely when you integrate with external libraries

const obj = {
  toString: () => 'burrito',
  order: () => ''
};

obj + '' === 'burrito' // true
obj === 'burrito' // false

equals('burrito', obj + '') // true
equals('burrito', obj) // false

I would suggest that you convert your object into a string before you make the check:

const check = pipe(
  toString,
  equals('burrito')
);

check(obj); // true

Then if you don't need an "else" branch, you could consider using when.

const execute = when(check, invoker(0, 'order'))
execute(obj); // ""
execute({}); // {}
customcommander
  • 17,580
  • 5
  • 58
  • 84
  • I did not get the solution. But I've updated my question though. I'm using the constraint only as a string. – pkdq Nov 12 '18 at 12:50
  • It's just that in your first code sample, you do `constraint == 'required'` then a few lines later you do `await constraint.click();`. That's what I mean by handling a variable both as a string and an object. Do you a complete reproducible example to share? – customcommander Nov 12 '18 at 12:56
  • That would be great. I tried many times but failed. I just want to execute a block of code if there is something in the string i.e (constraint == 'required'). If its empty just do nothing. R.Cond is really messing up with my brain. – pkdq Nov 12 '18 at 13:31
  • You don't need `R.cond` if you only need one branch. Use `R.when` instead. – customcommander Nov 12 '18 at 13:33
  • Oh... let me have a look at it then. – pkdq Nov 12 '18 at 13:34