Skip to content

Commit

Permalink
Fix broken links
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonLaster committed May 18, 2024
1 parent bb8beec commit 30acc96
Show file tree
Hide file tree
Showing 15 changed files with 171 additions and 100 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/links.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Check for broken links

on: [deployment_status]

jobs:
check-links:
name: check broken links
if: github.event.deployment_status.state == 'success'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: volta-cli/action@v1
with:
node-version: 20.12.0

- name: Install packages
run: npm install
- name: Install bun
run: npm install -g bun
- name: Links
run: npm run links
env:
BASE_URL: ${{ github.event.deployment_status.target_url }}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"sharp": "0.33.1"
},
"volta": {
"node": "20.12.0"
"node": "20.12.0",
"bun": "1.1.1"
}
}
79 changes: 56 additions & 23 deletions scripts/checkLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,76 @@ import * as fs from 'fs'
import { Glob } from 'bun'
import fetch from 'node-fetch'
import { marked } from 'marked'
import vercelConfig from "../vercel.json"
import vercelConfig from '../vercel.json'


const LOCAL_BASE = 'http://localhost:3000'
const LOCAL_BASE = process.env.BASE_URL || 'http://localhost:3000'

const excludePage = [
'./src/app/test-runners/cypress-io/panel.md',
'./src/app/test-runners/cypress-io/dashboard.md',
'./src/app/test-runners/_archive/jest.md',
]
const excludeUrl = ['https://webreplay.us.auth0.com/login/callback?connection=', '/discord']
const excludeUrl = [
'https://webreplay.us.auth0.com/login/callback?connection=',
'/discord',
]

function isFullUrl(url: string): boolean {
// A regular expression to check if the URL starts with http://, https://, or //
return /^(https?:\/\/|\/\/)/.test(url)
}

async function checkLink(url: string): Promise<boolean> {
let timeout
try {
const response = await fetch(url)
// cancel after 10 seconds
const controller = new AbortController()
timeout = setTimeout(() => controller.abort(), 10_000)

const response = await fetch(url, { signal: controller.signal })
return response.ok // Returns true if the response is 2xx
} catch (error) {
console.error(`Error checking ${url}: ${error}`)
return false
} finally {
clearTimeout(timeout)
}
}

async function checkLinkInFile(
link: string,
filePath: string,
): Promise<boolean> {
if (link.match(/^(mailto|blob)/)) {
return true
}

if (excludeUrl.includes(link)) {
return true
}
const url = isFullUrl(link) ? link : `${LOCAL_BASE}${link}`

const isOk = await checkLink(url)

if (!isOk) {
process.stdout.write('x')
return false
} else {
// write a dot to the same line
process.stdout.write('.')
return true
}
}

async function checkLinksInFile(filePath: string, links: string[]) {
const failedLinks = []
for (const link of links) {
if (link.match(/^(mailto|blob)/)) {
continue
}

if (excludeUrl.includes(link)) {
continue
}
const url = isFullUrl(link) ? link : `${LOCAL_BASE}${link}`

const isOk = await checkLink(url)
const isOk = await checkLinkInFile(link, filePath)
if (!isOk) {
const message = `${filePath} :: ${url} is broken`
console.error(message)
failedLinks.push(message)
failedLinks.push(link)
}
}

return failedLinks
}

Expand Down Expand Up @@ -84,23 +108,32 @@ async function main(): Promise<void> {
console.log(`Checking ${files.length} files...`)

const failedLinks = []
for (const file of files.slice(0, 5)) {
for (const [index, file] of files.entries()) {
const { file: filePath, links } = file
console.log(`${filePath}`)
process.stdout.write(`${index + 1} ${filePath} `)
failedLinks.push(...(await checkLinksInFile(filePath, links)))
process.stdout.write('\n')
}

failedLinks.push(... await checkLinksInFile('vercel.json', (vercelConfig.redirects.map(l => l.destination))))
console.log('Checking links in Vercel.json')
failedLinks.push(
...(await checkLinksInFile(
'vercel.json',
vercelConfig.redirects.map((l) => l.destination),
)),
)

const dedupedFailedLinks = [...new Set(failedLinks)]

if (failedLinks.length > 0) {
console.error('\nThe following links are broken:')
for (const link of failedLinks) {
for (const link of dedupedFailedLinks) {
console.error(link)
}
process.exit(1)
} else {
console.log('All links are working')
console.log('\nAll links are working')
process.exit(0)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/app/comparison/playwright/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Because Replay is simply a browser, you can start recording your tests by adding

The biggest benefit of time travel debugging is the ability to find a line of code and add a retroactive print statement. In the example below, we’ll add a `console.log("gPendingMessages", gPendingMessgages, msg)` on the line where `gPendingMessages.push` is called and see what was in the array and `msg` at the time.

Flaky tests can either come from an assumption in your testing logic or application logic. In both cases, it can be helpful to work backwards from the user visible issue to the root cause with console logs that help you narrow down the timing issue. For more info on print statements, check our our [docs](/browser-devtools/console).
Flaky tests can either come from an assumption in your testing logic or application logic. In both cases, it can be helpful to work backwards from the user visible issue to the root cause with console logs that help you narrow down the timing issue. For more info on print statements, check our our [docs](/replay-devtools/browser-devtools/console).

{% video src="addingAPrintStatement" /%}

Expand Down
8 changes: 4 additions & 4 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ const cards: CardAttributes[] = [
icon: 'inspect',
title: 'Browser DevTools',
content: 'Inspect your application with Browser DevTools after the fact.',
href: '/browser-devtools/elements-panel',
href: '/replay-devtools/browser-devtools/elements-panel',
},
{
icon: 'react',
title: 'Framework DevTools',
content: 'Inspect your application with next level Framework DevTools.',
href: '/framework-devtools/react-panel',
href: '/replay-devtools/framework-devtools/react-panel',
},
{
icon: 'replay',
Expand Down Expand Up @@ -52,7 +52,7 @@ const miniCards: CardAttributes[] = [
icon: 'react',
title: 'React components',
content: 'Inspect React component props, state, and hooks.',
href: '/framework-devtools/react-panel',
href: '/replay-devtools/framework-devtools/react-panel',
},
{
icon: 'folder',
Expand All @@ -65,7 +65,7 @@ const miniCards: CardAttributes[] = [
title: 'Cypress Timeline',
content:
'Debug your test as if it’s running locally with test step details.',
href: '/framework-devtools/cypress-timeline',
href: '/replay-devtools/framework-devtools/cypress-timeline',
},
{
icon: 'analytics',
Expand Down
4 changes: 2 additions & 2 deletions src/app/quickstart/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Recording your application with the Replay browser lets you capture a bug once a

- [Share the replay as a URL with your team so others can inspect it as if they were there when you recorded it.](/time-travel-intro/collaborative-devtools)
- [Debug the replay with `console.log` added in at any point of the recording.](/time-travel-intro/add-console-logs-on-the-fly)
- [Inspect Network requests](/browser-devtools/network-monitor), [React components](/framework-devtools/react-panel), and [DOM elements](browser-devtools/elements-panel) as if the application were running live on your laptop.
- [Inspect Network requests](/replay-devtools/browser-devtools/network-monitor), [React components](/replay-devtools/framework-devtools/react-panel), and [DOM elements](/replay-devtools/browser-devtools/elements-panel) as if the application were running live on your laptop.

The ability to record and deterministically replay runtimes like Chrome is referred to as ["time travel"](/time-travel-intro/why-time-travel).

Expand Down Expand Up @@ -143,7 +143,7 @@ In the interim, if you would perfer downloading a browser directly, you can use

{% accordion-item title="Why do I need to login to Replay?" %}

Replays need to be uploaded so that the browser can be replayed in the Replay Cloud. [How time travel works](/time-travel-intro/how-time-travel-works)
Replays need to be uploaded so that the browser can be replayed in the Replay Cloud. [How time travel works](/time-travel-intro/what-is-time-travel)

{% /accordion-item %}

Expand Down
4 changes: 2 additions & 2 deletions src/app/test-runners/cypress-io/getting-started/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ While this example is fairly exaggerated, it illustrates two main problems of **
Because of this, a flaky test does not feel like an act of higher force, but can be inspected with **a microscopic precision**. Even when your app is updated every millisecond, you can jump to the perfect spot, and see your DOM rendered exactly as it would on that moment.

{% callout title="Learn more" %}
To learn more about elements panel, head over to [Elements panel docs](/browser-devtools/elements-panel) or watch the [Replay Crash course](https://www.youtube.com/watch?v=kgJVauI7Obs).
To learn more about elements panel, head over to [Elements panel docs](/replay-devtools/browser-devtools/elements-panel) or watch the [Replay Crash course](https://www.youtube.com/watch?v=kgJVauI7Obs).
{% /callout %}

{% video src="elementsPanelStopWatch" /%}
Expand All @@ -77,7 +77,7 @@ Because network panel is integrated with the rest of the tools, you’ll get eve
Debugging tests should be a team effort whether that is collaboration between QA and devs or between different dev teams. When facing an API issue, commenting and sharing a replay will save hours of back and forth reporting. Instead of replicating the issue, share the issue exactly the way it happened. Locally or on CI.

{% callout title="Learn more" %}
To learn more about network panel, checkout [Network panel docs](/browser-devtools/elements-panel) or watch the [Replay Crash course](https://www.youtube.com/watch?v=rGKAOG6gZZU).
To learn more about network panel, checkout [Network panel docs](/replay-devtools/browser-devtools/elements-panel) or watch the [Replay Crash course](https://www.youtube.com/watch?v=rGKAOG6gZZU).
{% /callout %}

## Jump to code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ You’re ready to inspect your local test run in Replay DevTools now. You can al
{% quick-link
title="Replay DevTools"
icon="jumptocode"
href="/browser-devtools/console"
href="/replay-devtools/browser-devtools/console"
description="Learn how to use Replay DevTools to debug your tests."
/%}

Expand Down
16 changes: 11 additions & 5 deletions src/app/test-runners/overview/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,32 @@ description: Capture flakes in CI. Investigate failures with browser DevTools. A
---

## Using Replay with your test suite

Replay is a drop-in replacement for the browser you currently use when running your end-to-end tests. Whether you use Playwright, Cypress, or other test runners, you simply swap your current browser with **Replay Browser** and that’s it.

Explained in simplest possible terms, this is how your test script looks when Replay is integrated:

{% icon icon="playwright" class="w-6 h-5 inline-block mr-1 mb-1" /%} Playwright:{% class="font-semibold"%}

```sh
npx playwright test --project replay-chromium
```

{% icon icon="cypress" class="w-6 h-5 inline-block mr-1 mb-1" /%} Cypress:{% class="font-semibold"%}

```sh
npx cypress run --browser replay-chromium
```

### Difference when using Replay Browser
Under the hood, Replay Browser is just Chromium browser, just like Google Chrome, or Microsoft Edge. But as you run your tests, Replay Browser creates a recording of your runtime.

At the first glance, that recording may look like a series of snapshots of your application, but you’ll learn that *a replay* is actually a very different concept. In fact, there are zero snapshots created during recording, which results in a minimal overhead as you run your tests. And yet, the information gathered is infinitely more robust.
Under the hood, Replay Browser is just Chromium browser, just like Google Chrome, or Microsoft Edge. But as you run your tests, Replay Browser creates a recording of your runtime.

At the first glance, that recording may look like a series of snapshots of your application, but you’ll learn that _a replay_ is actually a very different concept. In fact, there are zero snapshots created during recording, which results in a minimal overhead as you run your tests. And yet, the information gathered is infinitely more robust.

### When to use Replay with your tests
There are a [couple of strategies](/ci-workflows/recording-strategies) you can adopt, but generally you can use Replay Browser with every test run on your CI, as there is both short-term and long-term value.

There are a [couple of strategies](/ci-workflows/recording-strategies) you can adopt, but generally you can use Replay Browser with every test run on your CI, as there is both short-term and long-term value.

When a test fails on CI, you don’t need to replicate it locally anymore. A recording captures your test run **exactly** as it happened and will provide you better insight than if you tried to locally reproduce an issue from CI.

Expand All @@ -36,7 +42,7 @@ If you battle with flaky tests, you can [compare a failing and a passing test](h

Replay Devtools work great with your existing test suite. Cypress and Playwright plugins allow you to **rewind or fast forward** to any command from your test run.

The command details panel contains information on passed arguments, returned values and targeted element. Commands are integrated with the rest of DevTools. This means you can jump from a command detail into [Elements panel](/browser-devtools/elements-panel), or inspect API calls in the [Network panel](/browser-devtools/network-monitor).
The command details panel contains information on passed arguments, returned values and targeted element. Commands are integrated with the rest of DevTools. This means you can jump from a command detail into [Elements panel](/replay-devtools/browser-devtools/elements-panel), or inspect API calls in the [Network panel](/replay-devtools/browser-devtools/network-monitor).
{% /basic %}

{% figure
Expand All @@ -52,7 +58,7 @@ The command details panel contains information on passed arguments, returned val

**See what actually happened** when your test clicked, typed or in other way interacted with your website. Jump from a test command right into the function that was called on interaction.

With information on [line hit counts](/browser-devtools/source-viewer#hit-counts) and [jumping through line executions](/browser-devtools/source-viewer#jumping-to-a-line) you’ll be able to narrow down a flake root cause in minutes.
With information on [line hit counts](/replay-devtools/browser-devtools/source-viewer#hit-counts) and [jumping through line executions](/replay-devtools/browser-devtools/source-viewer#jumping-to-a-line) you’ll be able to narrow down a flake root cause in minutes.
{% /basic %}

{% figure
Expand Down
29 changes: 15 additions & 14 deletions src/app/test-runners/playwright/debugging-tests/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ title: Debugging tests
{% /callout %}

## Jump to code

{% twocolumns %}
{% group %}
Replay integrates your Playwright tests with your application, providing a deeper understanding of what happens when a test executes actions `locator.click()`. When a test clicks, you can see which function in your application was called, instead of only seeing the result.

This helps you not only identify test failures but also understand the context and the progression of events leading to those failures. By working backwards from a failure, you can investigate it more thoroughly and address its root cause.
{% /group %}
{% figure
{% figure
src="/images/jump_to_code_playwright.png"
width=800
height=800
Expand All @@ -22,11 +23,12 @@ This helps you not only identify test failures but also understand the context a
{% /twocolumns %}

## Follow the data trace
Every line of code that was executed can be further inspected by adding a console.log. For example, when a test click triggers a function call, you can view the inputs and outcomes of that function. This provides you with a deeper understanding of your application's behavior.

Every line of code that was executed can be further inspected by adding a console.log. For example, when a test click triggers a function call, you can view the inputs and outcomes of that function. This provides you with a deeper understanding of your application's behavior.

When you run your Playwright test, Replay allows you to see which specific lines of code in your application are executed, indicated by hit counts. This feature helps you understand the flow and coverage of your tests within the app. When debugging, you can see which lines of code were executed and which were not. This you helps reveal patterns in your flaky tests.

{% figure
{% figure
src="/images/console_log_playwright.png"
alt="Console output from a print statement"
width=800
Expand All @@ -36,29 +38,31 @@ Console log with hit count on the left, output on the right
{% /figure %}

## Compare failing and passing tests

A great way to narrow down the root casue of a flaky test is to open two replays - one with a passed test and one with the failed one. Usually the recording can give you enough information to notice the moment when these two tests start to diverge.

A test failure usually ends in "element not found" or other similar message, but this is usually not enough. End-to-end tests carry a lot more context which can be gathered by looking at what the test was doing before it failed.

{% figure
{% figure
src="/images/flaky_test_view_playwright.png"
alt="Test suites view of flaky test"
width=800
height=800
/%}

## See your test steps

{% twocolumns %}
{% group %}
The test body feature enables you to view each step of your test as it was executed.
The test body feature enables you to view each step of your test as it was executed.

You can see every locator, assertion, and interaction made by your test script, providing you with an overview of your test run.

The test code frame feature lets you examine your test definition along with its entire call stack.
The test code frame feature lets you examine your test definition along with its entire call stack.

This enables you to jump into each function that was called, providing a detailed view of the execution flow during your test.
{% /group %}
{% figure
{% figure
src="/images/test_code_playwright.png"
alt="Playwright timeline with test code"
width=300
Expand All @@ -67,14 +71,11 @@ This enables you to jump into each function that was called, providing a detaile
{% /twocolumns %}

## React panel
When you view Component props, state, and hooks in the React panel, you’ll see the values which triggered the last render. This is one of those useful features that you didn’t realize you were missing until you have. [Learn more about React panel here](/framework-devtools/react-panel).

## Replay vs. Playwright trace viewer
Replay offers capabilities similar to Playwright’s trace-viewer but with more features and more power. In addition to exploring DOM snapshots, network information, and test steps, Replay allows you to view the source code of the application under test.

This enables a deeper understanding not only of the effects of your tests but also of the flow of your application's logic, providing comprehensive insights into how your application responds during testing. You can read more about these differences in the [comparison article](/comparison/playwright).


When you view Component props, state, and hooks in the React panel, you’ll see the values which triggered the last render. This is one of those useful features that you didn’t realize you were missing until you have. [Learn more about React panel here](/replay-devtools/framework-devtools/react-panel).

## Replay vs. Playwright trace viewer

Replay offers capabilities similar to Playwright’s trace-viewer but with more features and more power. In addition to exploring DOM snapshots, network information, and test steps, Replay allows you to view the source code of the application under test.

This enables a deeper understanding not only of the effects of your tests but also of the flow of your application's logic, providing comprehensive insights into how your application responds during testing. You can read more about these differences in the [comparison article](/comparison/playwright).
Loading

0 comments on commit 30acc96

Please sign in to comment.