<p dir="auto">Right now <code class="notranslate">test.step</code> resolves to <code class="notranslate">undefined</code>.</p>
<p dir="auto">It would be great if it resolved to the value the callback resolves to, so we could have tests like this:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="test('test something', async ({ pageObject, page }) =&gt; {
  await pageObject.navigateTo();
  
  const link = await test.step('is able to retrieve a link', async () =&gt; {
    const link = await pageObject.getLink();
    
    // tests...
    expect(link).toBe(blabla);
    
    return link;
  });
  
  await test.step('link is accessible', async () =&gt; {
    await page.goto(link)
    // tests...
    expect(page.locator('#my-element')).toBeVisible();
  });
})"><pre class="notranslate"><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s">'test something'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> pageObject<span class="pl-kos">,</span> page <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">await</span> <span class="pl-s1">pageObject</span><span class="pl-kos">.</span><span class="pl-en">navigateTo</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  
  <span class="pl-k">const</span> <span class="pl-s1">link</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">test</span><span class="pl-kos">.</span><span class="pl-en">step</span><span class="pl-kos">(</span><span class="pl-s">'is able to retrieve a link'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-s1">link</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">pageObject</span><span class="pl-kos">.</span><span class="pl-en">getLink</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    
    <span class="pl-c">// tests...</span>
    <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-s1">link</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toBe</span><span class="pl-kos">(</span><span class="pl-s1">blabla</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    
    <span class="pl-k">return</span> <span class="pl-s1">link</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  
  <span class="pl-k">await</span> <span class="pl-s1">test</span><span class="pl-kos">.</span><span class="pl-en">step</span><span class="pl-kos">(</span><span class="pl-s">'link is accessible'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s1">link</span><span class="pl-kos">)</span>
    <span class="pl-c">// tests...</span>
    <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">locator</span><span class="pl-kos">(</span><span class="pl-s">'#my-element'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toBeVisible</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">Right now the workaround is to have <code class="notranslate">let</code> variables before the step (notice the <code class="notranslate">!</code> to avoid type errors):</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="test('test something', async ({ pageObject, page }) =&gt; {
  await pageObject.navigateTo();
  
  let link!: string
  await test.step('is able to retrieve a link', async () =&gt; {
    link = await pageObject.getLink();
    
    // tests...
    expect(link).toBe(blabla);
  });
  
  await test.step('link is accessible', async () =&gt; {
    await page.goto(link)
    // tests...
    expect(page.locator('#my-element')).toBeVisible();
  });
})"><pre class="notranslate"><span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s">'test something'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">{</span> pageObject<span class="pl-kos">,</span> page <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
  <span class="pl-k">await</span> <span class="pl-s1">pageObject</span><span class="pl-kos">.</span><span class="pl-en">navigateTo</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  
  <span class="pl-k">let</span> <span class="pl-s1">link</span><span class="pl-c1">!</span>: <span class="pl-smi">string</span>
  <span class="pl-k">await</span> <span class="pl-s1">test</span><span class="pl-kos">.</span><span class="pl-en">step</span><span class="pl-kos">(</span><span class="pl-s">'is able to retrieve a link'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-s1">link</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">pageObject</span><span class="pl-kos">.</span><span class="pl-en">getLink</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    
    <span class="pl-c">// tests...</span>
    <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-s1">link</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toBe</span><span class="pl-kos">(</span><span class="pl-s1">blabla</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  
  <span class="pl-k">await</span> <span class="pl-s1">test</span><span class="pl-kos">.</span><span class="pl-en">step</span><span class="pl-kos">(</span><span class="pl-s">'link is accessible'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s1">link</span><span class="pl-kos">)</span>
    <span class="pl-c">// tests...</span>
    <span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">locator</span><span class="pl-kos">(</span><span class="pl-s">'#my-element'</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toBeVisible</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">I'm free to work on this if it is something that would be accepted in the library.</p>
<p dir="auto">It would be useful to be able to return a value from a test step and use it in a subsequent step.<br>
This way we could avoid mutable state (<code class="notranslate">let</code>).</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="    const invitationLink = await test.step('Create invitation link', async () =&gt; {
      await page.goto('create-invitation-link');
      …
      return await page.locator('#link').getAttribute('href');
    });

    await test.step('Accept invitation', async () =&gt; {
      await page.goto(invitationLink);
    });"><pre class="notranslate">    <span class="pl-k">const</span> <span class="pl-s1">invitationLink</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">test</span><span class="pl-kos">.</span><span class="pl-en">step</span><span class="pl-kos">(</span><span class="pl-s">'Create invitation link'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s">'create-invitation-link'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
      <span class="pl-s1">…</span>
      <span class="pl-k">return</span> <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">locator</span><span class="pl-kos">(</span><span class="pl-s">'#link'</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">getAttribute</span><span class="pl-kos">(</span><span class="pl-s">'href'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

    <span class="pl-k">await</span> <span class="pl-s1">test</span><span class="pl-kos">.</span><span class="pl-en">step</span><span class="pl-kos">(</span><span class="pl-s">'Accept invitation'</span><span class="pl-kos">,</span> <span class="pl-k">async</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
      <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s1">invitationLink</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">The <code class="notranslate">test.step</code> method would probably need a generic signature:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="step&lt;A&gt;(title: string, body: () =&gt; Promise&lt;A&gt;): Promise&lt;A&gt;;"><pre class="notranslate"><span class="pl-s1">step</span><span class="pl-c1">&lt;</span><span class="pl-smi">A</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">title</span>: <span class="pl-smi">string</span><span class="pl-kos">,</span> <span class="pl-s1">body</span>: <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">A</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span>: <span class="pl-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">A</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span></pre></div>