自定义命令和“额外数据”最终变为未定义。

huangapple go评论59阅读模式
英文:

Custom command and 'extra data' that ends up as undefined

问题

我正在尝试重写Cypress的within方法,以便为回调函数添加一个额外的参数。

最终,我的目标是能够执行以下操作:
cy.customCommandThatSetsAValue().within((subject, extra) => {})

问题似乎涉及到时间控制...每当我尝试传递一个非硬编码的值时,它最终被传递为undefined。我尝试了多种排列组合,似乎无论我如何在.then()回调内设置变量,当它传递到自定义命令时,它都变成了undefined。

这是我的重写代码:

function within<Subject>(
    originalWithinFn: Cypress.CommandOriginalFnWithSubject<'within', Subject>,
    prevSubject: Subject, 
    optionsOrFn: Partial<Cypress.Loggable> | WithinCallback,
    fnOrUndefined?: WithinCallback,
){
    let fn: WithinCallback;
    let options: Partial<Cypress.Loggable> | undefined;
    if (optionsOrFn instanceof Function && fnOrUndefined === undefined) {
        fn = optionsOrFn;
    } else if (fnOrUndefined instanceof Function) {
        options = optionsOrFn;
        fn = fnOrUndefined;
    } else {
        throw new Error('Invalid arguments provided to cy.within');
    }
    return getMostRecentNavigationShorthand().then(mostRecentShorthand => originalWithinFn(prevSubject, options!, (subject) => fn(subject, mostRecentShorthand)));
}

Cypress.Commands.overwrite('within', within);

customCommandThatSetsAValue()的简化版本如下:

return cy.get('foo').then(() => {mostRecentShorthand = anObject});

以及

function getMostRecentNavigationShorthand() {
    return new Cypress.Promise((resolve, reject) => resolve(mostRecentShorthand));
}

我尝试将within中的返回值更改为:

return cy.then(() => 
    getMostRecentNavigationShorthand()
        .then(mostRecentShorthand => 
            originalWithinFn(prevSubject, options!, (subject) => fn(subject, mostRecentShorthand)
)));

还尝试将cy.then包装在promise周围(或使用它代替promise)。无论我做什么,它最终都在实际执行时变成了undefined。

你有没有想法为什么我一直得到undefined,或者如何修复它?谢谢!

英文:

I'm trying to overwrite the Cypress within method such that there's an extra argument for the callback.

Ultimately, my goal is to be able to go
cy.customCommandThatSetsAValue().within((subject, extra) =&gt; {})

The issue seems to be a matter of timing... whenever I try to pass a non-hardcoded value, it ends up being passed as undefined. I've tried a number of permutations and it seems like somehow even when I set the variable from within a .then() callback, it's undefined when it gets to the custom command.

Here's my override:

function within&lt;Subject&gt;(
    originalWithinFn: Cypress.CommandOriginalFnWithSubject&lt;&#39;within&#39;, Subject&gt;,
    prevSubject: Subject, 
    optionsOrFn: Partial&lt;Cypress.Loggable&gt; | WithinCallback,
    fnOrUndefined?: WithinCallback,
){
    let fn: WithinCallback;
    let options: Partial&lt;Cypress.Loggable&gt; | undefined;
    if (optionsOrFn instanceof Function &amp;&amp; fnOrUndefined === undefined) {
        fn = optionsOrFn;
    } else if (fnOrUndefined instanceof Function) {
        options = optionsOrFn;
        fn = fnOrUndefined;
    } else {
        throw new Error(&#39;Invalid arguments provided to cy.within&#39;);
    }
    return getMostRecentNavigationShorthand().then(mostRecentShorthand =&gt; originalWithinFn(prevSubject, options!, (subject) =&gt; fn(subject, mostRecentShorthand)));
}

Cypress.Commands.overwrite(&#39;within&#39;, within);

A simplified version of customCommandThatSetsAValue() is

return cy.get(&#39;foo&#39;).then(() =&gt; {mostRecentShorthand = anObject});

and

function getMostRecentNavigationShorthand() {
    return new Cypress.Promise((resolve, reject) =&gt; resolve(mostRecentShorthand));
}

I've tried changing the return in within to

return cy.then(() =&gt; 
    getMostRecentNavigationShorthand()
        .then(mostRecentShorthand =&gt; 
            originalWithinFn(prevSubject, options!, (subject) =&gt; fn(subject, mostRecentShorthand)
)));

as well as trying to wrap a cy.then around the promise (or use that instead of a promise). No matter what i do, it still ends up undefined at actual execution time.

Any idea how/why I keep getting undefined or how to fix it? Thanks!

答案1

得分: 3

如果我把所有的代码都放到一个测试中,它会通过。不知道anObject是什么,所以我只是使用了{abc: 123}

let mostRecentShorthand = null

function getMostRecentNavigationShorthand() {
  return new Cypress.Promise((resolve, reject) => resolve(mostRecentShorthand));
}

function within(originalWithinFn, prevSubject, optionsOrFn, fnOrUndefined) {

  // 参数解析

  return getMostRecentNavigationShorthand()
    .then(mostRecentShorthand => {
      return originalWithinFn(prevSubject, options, (subject) => 
        fn(subject, mostRecentShorthand)
      )
    })
}
Cypress.Commands.overwrite('within', within)

Cypress.Commands.add('customCommandThatSetsAValue', () => {
  return cy.get('h1').then(() => {mostRecentShorthand = {abc: 123}})
})

it('gives an extra parameter to within', () => {
  cy.visit('https://example.com');
  cy.customCommandThatSetsAValue().within((subject, extra) => {
    expect(extra).to.deep.eq({abc: 123})
  })
})

你不需要Cypress.Promise块,因为你是同步设置了这个值,立即解析,而且从未拒绝。但这并不会导致额外的参数为undefined。只有当anObject的值为undefined时才会发生这种情况。

英文:

If I put all that code into a test, it passes. Don't know what anObject is, so I just used {abc: 123}.

let mostRecentShorthand = null

function getMostRecentNavigationShorthand() {
  return new Cypress.Promise((resolve, reject) =&gt; resolve(mostRecentShorthand));
}

function within(originalWithinFn, prevSubject, optionsOrFn, fnOrUndefined) {

  // parameter resolving

  return getMostRecentNavigationShorthand()
    .then(mostRecentShorthand =&gt; {
      return originalWithinFn(prevSubject, options, (subject) =&gt; 
        fn(subject, mostRecentShorthand)
      )
    })
}
Cypress.Commands.overwrite(&#39;within&#39;, within)

Cypress.Commands.add(&#39;customCommandThatSetsAValue&#39;, () =&gt; {
  return cy.get(&#39;h1&#39;).then(() =&gt; {mostRecentShorthand = {abc: 123}})
})

it(&#39;gives an extra parameter to within&#39;, () =&gt; {
  cy.visit(&#39;https://example.com&#39;);
  cy.customCommandThatSetsAValue().within((subject, extra) =&gt; {
    expect(extra).to.deep.eq({abc: 123})
  })
})

You would not need the Cypress.Promise block since you set the value synchronously, immediately resolve, and never reject. But it does not cause the extra parameter to be undefined. That would only happen if the value of anObject were undefined.

huangapple
  • 本文由 发表于 2023年7月14日 08:49:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76684066.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定