playwright test and framework for network stuff (#2480)
* playwright test and framework for network bullshit chrome protocol docs for params you can send https://chromedevtools.github.io/devtools-protocol/1-3/Network/#method-emulateNetworkConditions Signed-off-by: Jess Frazelle <github@jessfraz.com> * fmt Signed-off-by: Jess Frazelle <github@jessfraz.com> * skip on webkit Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
		@ -59,7 +59,7 @@ test.beforeEach(async ({ context, page }) => {
 | 
			
		||||
test.setTimeout(60000)
 | 
			
		||||
 | 
			
		||||
test('Basic sketch', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
@ -145,7 +145,7 @@ test('Basic sketch', async ({ page }) => {
 | 
			
		||||
 | 
			
		||||
test('Can moving camera', async ({ page, context }) => {
 | 
			
		||||
  test.skip(process.platform === 'darwin', 'Can moving camera')
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
  await u.waitForAuthSkipAppStart()
 | 
			
		||||
@ -269,7 +269,7 @@ test('Can moving camera', async ({ page, context }) => {
 | 
			
		||||
test('if you click the format button it formats your code', async ({
 | 
			
		||||
  page,
 | 
			
		||||
}) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1000, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
 | 
			
		||||
@ -300,7 +300,7 @@ test('if you click the format button it formats your code', async ({
 | 
			
		||||
test('if you use the format keyboard binding it formats your code', async ({
 | 
			
		||||
  page,
 | 
			
		||||
}) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async () => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
@ -358,7 +358,7 @@ test('ensure the Zoo logo is not a link in browser app', async ({ page }) => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('if you write invalid kcl you get inlined errors', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1000, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
 | 
			
		||||
@ -425,7 +425,7 @@ test('if you write invalid kcl you get inlined errors', async ({ page }) => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('error with 2 source ranges gets 2 diagnostics', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async () => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
@ -501,7 +501,7 @@ fn squareHole = (l, w) => {
 | 
			
		||||
test('if your kcl gets an error from the engine it is inlined', async ({
 | 
			
		||||
  page,
 | 
			
		||||
}) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async () => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
@ -549,7 +549,7 @@ angle: 90
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('executes on load', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async () => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
@ -585,7 +585,7 @@ test('executes on load', async ({ page }) => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('re-executes', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async () => {
 | 
			
		||||
    localStorage.setItem('persistCode', `const myVar = 5`)
 | 
			
		||||
  })
 | 
			
		||||
@ -619,7 +619,7 @@ const sketchOnPlaneAndBackSideTest = async (
 | 
			
		||||
  plane: string,
 | 
			
		||||
  clickCoords: { x: number; y: number }
 | 
			
		||||
) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
@ -696,7 +696,7 @@ test.describe('Can create sketches on all planes and their back sides', () => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Auto complete works', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  // const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  const lspStartPromise = page.waitForEvent('console', async (message) => {
 | 
			
		||||
@ -766,7 +766,7 @@ test('Auto complete works', async ({ page }) => {
 | 
			
		||||
test('Stored settings are validated and fall back to defaults', async ({
 | 
			
		||||
  page,
 | 
			
		||||
}) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
 | 
			
		||||
  // Override beforeEach test setup
 | 
			
		||||
  // with corrupted settings
 | 
			
		||||
@ -974,7 +974,7 @@ test('Project and user settings can be reset', async ({ page }) => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Click through each onboarding step', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
 | 
			
		||||
  // Override beforeEach test setup
 | 
			
		||||
  await page.addInitScript(
 | 
			
		||||
@ -1013,7 +1013,7 @@ test('Click through each onboarding step', async ({ page }) => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Onboarding redirects and code updating', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
 | 
			
		||||
  // Override beforeEach test setup
 | 
			
		||||
  await page.addInitScript(
 | 
			
		||||
@ -1060,7 +1060,7 @@ test('Selections work on fresh and edited sketch', async ({ page }) => {
 | 
			
		||||
  // tests mapping works on fresh sketch and edited sketch
 | 
			
		||||
  // tests using hovers which is the same as selections, because if
 | 
			
		||||
  // source ranges are wrong, hovers won't work
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
@ -1350,7 +1350,7 @@ test.describe('Command bar tests', () => {
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const u = getUtils(page)
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
    await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
    await page.goto('/')
 | 
			
		||||
    await u.waitForAuthSkipAppStart()
 | 
			
		||||
@ -1423,7 +1423,7 @@ const part001 = startSketchOn('XZ')
 | 
			
		||||
 | 
			
		||||
test('Can add multiple sketches', async ({ page }) => {
 | 
			
		||||
  test.skip(process.platform === 'darwin', 'Can add multiple sketches')
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
@ -1566,7 +1566,7 @@ const part002 = startSketchOn('${plane}')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('ProgramMemory can be serialised', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async () => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
@ -1605,7 +1605,7 @@ test('ProgramMemory can be serialised', async ({ page }) => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Hovering over 3d features highlights code', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
@ -1673,7 +1673,7 @@ test('Hovering over 3d features highlights code', async ({ page }) => {
 | 
			
		||||
test("Various pipe expressions should and shouldn't allow edit and or extrude", async ({
 | 
			
		||||
  page,
 | 
			
		||||
}) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  const selectionsSnippets = {
 | 
			
		||||
    extrudeAndEditBlocked: '|> startProfileAt([10.81, 32.99], %)',
 | 
			
		||||
    extrudeAndEditBlockedInFunction: '|> startProfileAt(pos, %)',
 | 
			
		||||
@ -1780,7 +1780,7 @@ fn yohey = (pos) => {
 | 
			
		||||
test('Deselecting line tool should mean nothing happens on click', async ({
 | 
			
		||||
  page,
 | 
			
		||||
}) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
  await u.waitForAuthSkipAppStart()
 | 
			
		||||
@ -1846,7 +1846,7 @@ test('multi-sketch file shows multiple Edit Sketch buttons', async ({
 | 
			
		||||
  page,
 | 
			
		||||
  context,
 | 
			
		||||
}) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  const selectionsSnippets = {
 | 
			
		||||
    startProfileAt1:
 | 
			
		||||
      '|> startProfileAt([-width / 4 + screwRadius, height / 2], %)',
 | 
			
		||||
@ -1925,7 +1925,7 @@ const part002 = startSketchOn('-XZ')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Can edit segments by dragging their handles', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async () => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
@ -2001,7 +2001,7 @@ const doSnapAtDifferentScales = async (
 | 
			
		||||
  scale = 1,
 | 
			
		||||
  fudge = 0
 | 
			
		||||
) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
  await u.waitForAuthSkipAppStart()
 | 
			
		||||
@ -2088,7 +2088,7 @@ test.describe('Snap to close works (at any scale)', () => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Sketch on face', async ({ page }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.addInitScript(async () => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
@ -2236,7 +2236,7 @@ test('Can code mod a line length', async ({ page }) => {
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
@ -2281,7 +2281,7 @@ test('Extrude from command bar selects extrude line after', async ({
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
  await u.waitForAuthSkipAppStart()
 | 
			
		||||
@ -2327,7 +2327,7 @@ test('Basic default modeling and sketch hotkeys work', async ({ page }) => {
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  // Wait for the app to be ready for use
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
  await u.waitForAuthSkipAppStart()
 | 
			
		||||
@ -2405,3 +2405,64 @@ test('Basic default modeling and sketch hotkeys work', async ({ page }) => {
 | 
			
		||||
  await codePaneButton.click()
 | 
			
		||||
  await expect(page.locator('.cm-content')).toContainText('extrude(')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('simulate network down and network little widget', async ({ page }) => {
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
  await u.waitForAuthSkipAppStart()
 | 
			
		||||
 | 
			
		||||
  const networkWidget = page.locator('[data-testid="network-toggle"]')
 | 
			
		||||
  await expect(networkWidget).toBeVisible()
 | 
			
		||||
  await networkWidget.hover()
 | 
			
		||||
 | 
			
		||||
  const networkPopover = page.locator('[data-testid="network-popover"]')
 | 
			
		||||
  await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
  // Expect the network to be up
 | 
			
		||||
  await expect(page.getByText('Network Health (Connected)')).toBeVisible()
 | 
			
		||||
 | 
			
		||||
  // Click the network widget
 | 
			
		||||
  await networkWidget.click()
 | 
			
		||||
 | 
			
		||||
  // Check the modal opened.
 | 
			
		||||
  await expect(networkPopover).toBeVisible()
 | 
			
		||||
 | 
			
		||||
  // Click off the modal.
 | 
			
		||||
  await page.mouse.click(100, 100)
 | 
			
		||||
  await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
  // Turn off the network
 | 
			
		||||
  await u.emulateNetworkConditions({
 | 
			
		||||
    offline: true,
 | 
			
		||||
    // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
    latency: 0,
 | 
			
		||||
    downloadThroughput: -1,
 | 
			
		||||
    uploadThroughput: -1,
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  // Expect the network to be down
 | 
			
		||||
  await expect(page.getByText('Network Health (Offline)')).toBeVisible()
 | 
			
		||||
 | 
			
		||||
  // Click the network widget
 | 
			
		||||
  await networkWidget.click()
 | 
			
		||||
 | 
			
		||||
  // Check the modal opened.
 | 
			
		||||
  await expect(networkPopover).toBeVisible()
 | 
			
		||||
 | 
			
		||||
  // Click off the modal.
 | 
			
		||||
  await page.mouse.click(100, 100)
 | 
			
		||||
  await expect(networkPopover).not.toBeVisible()
 | 
			
		||||
 | 
			
		||||
  // Turn back on the network
 | 
			
		||||
  await u.emulateNetworkConditions({
 | 
			
		||||
    offline: false,
 | 
			
		||||
    // values of 0 remove any active throttling. crbug.com/456324#c9
 | 
			
		||||
    latency: 0,
 | 
			
		||||
    downloadThroughput: -1,
 | 
			
		||||
    uploadThroughput: -1,
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  // Expect the network to be up
 | 
			
		||||
  await expect(page.getByText('Network Health (Connected)')).toBeVisible()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ test.setTimeout(60_000)
 | 
			
		||||
test('exports of each format should work', async ({ page, context }) => {
 | 
			
		||||
  // FYI this test doesn't work with only engine running locally
 | 
			
		||||
  // And you will need to have the KittyCAD CLI installed
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await context.addInitScript(async () => {
 | 
			
		||||
    ;(window as any).playwrightSkipFilePicker = true
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
@ -369,7 +369,7 @@ const extrudeDefaultPlane = async (context: any, page: any, plane: string) => {
 | 
			
		||||
    localStorage.setItem('persistCode', code)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
  await u.waitForAuthSkipAppStart()
 | 
			
		||||
@ -424,7 +424,7 @@ test.describe('extrude on default planes should be stable', () => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Draft segments should look right', async ({ page, context }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
@ -483,7 +483,7 @@ test('Draft segments should look right', async ({ page, context }) => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Draft rectangles should look right', async ({ page, context }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
  const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
  await page.goto('/')
 | 
			
		||||
@ -530,7 +530,7 @@ test('Draft rectangles should look right', async ({ page, context }) => {
 | 
			
		||||
 | 
			
		||||
test.describe('Client side scene scale should match engine scale', () => {
 | 
			
		||||
  test('Inch scale', async ({ page }) => {
 | 
			
		||||
    const u = getUtils(page)
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
    await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
    const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
    await page.goto('/')
 | 
			
		||||
@ -633,7 +633,7 @@ test.describe('Client side scene scale should match engine scale', () => {
 | 
			
		||||
        }),
 | 
			
		||||
      }
 | 
			
		||||
    )
 | 
			
		||||
    const u = getUtils(page)
 | 
			
		||||
    const u = await getUtils(page)
 | 
			
		||||
    await page.setViewportSize({ width: 1200, height: 500 })
 | 
			
		||||
    const PUR = 400 / 37.5 //pixeltoUnitRatio
 | 
			
		||||
    await page.goto('/')
 | 
			
		||||
@ -719,7 +719,7 @@ test.describe('Client side scene scale should match engine scale', () => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Sketch on face with none z-up', async ({ page, context }) => {
 | 
			
		||||
  const u = getUtils(page)
 | 
			
		||||
  const u = await getUtils(page)
 | 
			
		||||
  await context.addInitScript(async (KCL_DEFAULT_LENGTH) => {
 | 
			
		||||
    localStorage.setItem(
 | 
			
		||||
      'persistCode',
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,9 @@
 | 
			
		||||
import { expect, Page } from '@playwright/test'
 | 
			
		||||
import { test, expect, Page } from '@playwright/test'
 | 
			
		||||
import { EngineCommand } from '../../src/lang/std/engineConnection'
 | 
			
		||||
import fsp from 'fs/promises'
 | 
			
		||||
import pixelMatch from 'pixelmatch'
 | 
			
		||||
import { PNG } from 'pngjs'
 | 
			
		||||
import { Protocol } from 'playwright-core/types/protocol'
 | 
			
		||||
 | 
			
		||||
async function waitForPageLoad(page: Page) {
 | 
			
		||||
  // wait for 'Loading stream...' spinner
 | 
			
		||||
@ -93,7 +94,12 @@ async function waitForCmdReceive(page: Page, commandType: string) {
 | 
			
		||||
    .waitFor()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getUtils(page: Page) {
 | 
			
		||||
export async function getUtils(page: Page) {
 | 
			
		||||
  const cdpSession =
 | 
			
		||||
    process.platform === 'darwin'
 | 
			
		||||
      ? null
 | 
			
		||||
      : await page.context().newCDPSession(page)
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    waitForAuthSkipAppStart: () => waitForPageLoad(page),
 | 
			
		||||
    removeCurrentCode: () => removeCurrentCode(page),
 | 
			
		||||
@ -180,6 +186,17 @@ export function getUtils(page: Page) {
 | 
			
		||||
          }
 | 
			
		||||
        }, 50)
 | 
			
		||||
      }),
 | 
			
		||||
    emulateNetworkConditions: async (
 | 
			
		||||
      networkOptions: Protocol.Network.emulateNetworkConditionsParameters
 | 
			
		||||
    ) => {
 | 
			
		||||
      // Skip on non-Chromium browsers, since we need to use the CDP.
 | 
			
		||||
      test.skip(
 | 
			
		||||
        cdpSession === null,
 | 
			
		||||
        'Network emulation is only supported in Chromium'
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      cdpSession?.send('Network.emulateNetworkConditions', networkOptions)
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -231,7 +231,10 @@ export const NetworkHealthIndicator = () => {
 | 
			
		||||
          Network Health ({NETWORK_HEALTH_TEXT[overallState]})
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
      </Popover.Button>
 | 
			
		||||
      <Popover.Panel className="absolute right-0 left-auto bottom-full mb-1 w-64 flex flex-col gap-1 align-stretch bg-chalkboard-10 dark:bg-chalkboard-90 rounded shadow-lg border border-solid border-chalkboard-20/50 dark:border-chalkboard-80/50 text-sm">
 | 
			
		||||
      <Popover.Panel
 | 
			
		||||
        className="absolute right-0 left-auto bottom-full mb-1 w-64 flex flex-col gap-1 align-stretch bg-chalkboard-10 dark:bg-chalkboard-90 rounded shadow-lg border border-solid border-chalkboard-20/50 dark:border-chalkboard-80/50 text-sm"
 | 
			
		||||
        data-testid="network-popover"
 | 
			
		||||
      >
 | 
			
		||||
        <div
 | 
			
		||||
          className={`flex items-center justify-between p-2 rounded-t-sm ${overallConnectionStateColor[overallState].bg} ${overallConnectionStateColor[overallState].icon}`}
 | 
			
		||||
        >
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user