【问题标题】:Failed conversion the IF/Else condition to Ramda Cond将 IF/Else 条件转换为 Ramda Cond 失败
【发布时间】:2019-04-15 01:42:09
【问题描述】:

使用 Ramda 进行 E2E。我不知道如何使用 Ramda Cond 转换简单的 IF 条件。

使用 If 的代码:

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

我不想要 else,因为我希望只有在存在约束时才会执行操作。

到目前为止,我已经使用约束完成了这项工作,但它不起作用:

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

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

在某些情况下,我不想通过约束。然后条件根本不应该执行。但它总是被执行并抛出错误:无法读取未定义的属性“isPresent”。

【问题讨论】:

    标签: javascript e2e-testing ramda.js angularjs-e2e


    【解决方案1】:

    我认为这里可能存在一些混淆(除了 customcommander 正确指出的constraint 的类型。)

    Ramda 试图提供的功能之一是允许我们使用 表达式 而不是 语句 进行编程。尤其是控制流语句。但是一个看起来像这样的声明:

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

    已经有了标准的表达形式:

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

    Ramda 并没有真正尝试提供替代方案。但是还有另一种方式我们可以尝试使用if

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

    在这里,当使用函数时,Ramda 提供了一种方便的速记:

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

    (如果你只是想在测试失败的情况下返回val,你可以使用简写:

       const foo = when(test, bar)
    

    或者如果你想在测试成功时val,你可以这样做

       const foo = unless(test, baz)
    

    )

    虽然将代码转换成可能更具表现力

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

    这不是重点。 ifElse 的基本原理是在创建可重用函数ifElse(test, bar, baz) 时使用它。 (cond 也一样,只是提供了一系列条件结果对,而不是一个 if 和一个 else。)

    请注意其中的一个重要特征:测试函数、如果为真则运行的函数以及如果为假则运行的函数都具有相同的签名。如果其中一个接受三个参数,那么它们都应该接受三个参数。虽然测试应该返回一个布尔值,但其他两个可以有任何返回类型,但每个应该具有与另一个相同的返回类型。

    所以可以使用 thunk,当您尝试使用 () => constraintElement.click() 时,这主要是对 Ramda 功能的滥用。它可能对你的代码没有任何好处。


    目前还不清楚您要如何处理从if 语句到ifElsecond 的转换。请随时为您的问题添加更新,更全面地解释您要做什么,以及您要通过此转换解决什么问题,有人可能会提供一些帮助。但请确保您澄清 constraintconstraintElement 是什么以及 waitForElementToBeClickable 解析到什么。现在它相当混乱。

    【讨论】:

      【解决方案2】:

      通过查看您的示例,您似乎将constraint 用作字符串和对象,这可能会导致不必要的混淆。我知道您可以在对象上实现 toString() 方法,但我不确定当您与外部库集成时它是否总是能很好地发挥作用

      const obj = {
        toString: () => 'burrito',
        order: () => '?'
      };
      
      obj + '' === 'burrito' // true
      obj === 'burrito' // false
      
      equals('burrito', obj + '') // true
      equals('burrito', obj) // false
      

      我建议您在进行检查之前将对象转换为字符串:

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

      如果你不需要“else”分支,你可以考虑使用when

      const execute = when(check, invoker(0, 'order'))
      execute(obj); // "?"
      execute({}); // {}
      

      【讨论】:

      • 我没有得到解决方案。但是我已经更新了我的问题。我仅将约束用作字符串。
      • 只是在您的第一个代码示例中,您执行constraint == 'required',然后几行之后您执行await constraint.click();。这就是我将变量同时作为字符串和对象处理的意思。你有一个完整的可重现的例子来分享吗?
      • 那太好了。我尝试了很多次,但都失败了。如果字符串中有某些内容,我只想执行一段代码,即(约束 == 'required')。如果它是空的,什么也不做。 R.Cond 真的搞砸了我的大脑。
      • 如果您只需要一个分支,则不需要R.cond。请改用R.when
      • 哦……那我看看吧。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 2013-05-01
      相关资源
      最近更新 更多