Skip to content

Commit

Permalink
Merge pull request #261 from azmy60/e2e-setup
Browse files Browse the repository at this point in the history
  • Loading branch information
thetarnav authored Nov 1, 2023
2 parents a5ff664 + 359dfd3 commit d8ae33e
Show file tree
Hide file tree
Showing 18 changed files with 377 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/lovely-fans-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'solid-devtools': patch
---

Add E2E tests
13 changes: 13 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ jobs:
- name: Install dependencies
run: pnpm install --no-frozen-lockfile --ignore-scripts

- name: Install Playwright browser and dependencies
run: npx playwright install --with-deps chromium

- name: Lint
run: pnpm lint

Expand All @@ -36,3 +39,13 @@ jobs:
run: pnpm run build-test
env:
CI: true

- name: Run Playwright tests
run: pnpm test:e2e

- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ Thumbs.db

packages/extension/dist.zip
**/vite.config.ts.timestamp-*.*

/test-results/
/playwright-report/
/playwright/.cache/
6 changes: 5 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ If this is your first time pulling the repository onto a local branch, then run

You should reinstall the dependencies and rebuild the packages whenever you pull from the main branch. This is because the dependencies and packages may have changed. If you experience any issues, try removing the `node_modules` folder (`rm -Force -Recurse .\node_modules\` or `rm -rf node_modules/`) and repeating the steps above.

The code if formatted with prettier. You can use it if you want, or not, it's up to you because the code get's formatted automatically by a github action. If you want to use it, you can run `pnpm format` to format the code.
The code is formatted with prettier. You can use it if you want, or not, it's up to you because the code get's formatted automatically by a github action. If you want to use it, you can run `pnpm format` to format the code.

If you want to run the E2E tests, you need to install the dependencies by running `npx playwright --with-deps chromium`, then run `pnpm test:e2e`.

## Operating System

Expand Down Expand Up @@ -46,6 +48,8 @@ Important if you want to work on the chrome extension. _(The script may fail som

#### `pnpm test` — Runs all the tests

#### `pnpm test:e2e` - Runs all the E2E tests

#### `pnpm typecheck` — Runs the typecheck

#### `pnpm lint` — Lints code with eslint
Expand Down
104 changes: 104 additions & 0 deletions e2e/fixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { FrameLocator, Locator, Page, test as base, chromium } from '@playwright/test'
import assert from 'assert'
import path from 'path'

export const test = base.extend<{
page: Page
sdtFrame: FrameLocator | Locator
search: Locator
}>({
context: async ({ baseURL }, use, testInfo) => {
if (testInfo.project.name.includes('Overlay')) {
const context = await chromium.launchPersistentContext('', { baseURL })
await use(context)
await context.close()
return
}

const pathToExtension = path.resolve(__dirname, '../packages/extension/dist/')
const context = await chromium.launchPersistentContext('', {
args: [
'--headless=new',
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
],
devtools: true, // will open devtools when new tab is opened
baseURL,
})

const page = context.pages().find(page => page.url().includes('about:blank'))
assert(page)
const devtoolsPanel = context
.pages()
.find(page => page.url().includes('devtools://devtools/bundled/devtools_app.html'))
assert(devtoolsPanel)

// Since we can only initiate DevTools by opening a new tab, we need to go to
// the sandbox in a new tab by clicking a link.
await page.evaluate(baseURL => {
const a = document.createElement('a')
a.href = baseURL
a.target = '_blank'
a.innerText = 'open new tab'
document.body.appendChild(a)
}, baseURL!)

const pagePromise = context.waitForEvent('page')
await page.getByText('open new tab').click()
const newPage = await pagePromise
// wait for the new page to be interactive
await newPage.getByRole('button').first().click({ trial: true })

await devtoolsPanel.close()
await page.close()

await use(context)

await context.close()
},
baseURL: async ({}, use, testInfo) => {
await use(testInfo.project.use.baseURL)
},
page: async ({ context, baseURL }, use, testInfo) => {
if (testInfo.project.name.includes('Overlay')) {
const page = context.pages()[0]!
await page.goto('/')
await use(page)
return
}

const page = context.pages().find(page => page.url().includes(baseURL!))
assert(page)
await use(page)
},
sdtFrame: async ({ context, page }, use, testInfo) => {
let sdtFrame: FrameLocator | Locator

if (testInfo.project.name.includes('Overlay')) {
sdtFrame = page.getByTestId('solid-devtools-overlay')
} else {
const devtoolsPanel = context
.pages()
.find(page => page.url().includes('devtools://devtools/bundled/devtools_app.html'))
assert(devtoolsPanel)

// Undock the devtools into a separate window so we can see the `solid` tab.
await devtoolsPanel.getByLabel('Customize and control DevTools').click()
await devtoolsPanel.getByLabel('Undock into separate window').click()
await devtoolsPanel.getByText('Solid').click()

// Somehow the window is not sized properly, causes half of the viewport
// to be hidden. Interacting with elements outside the window area
// wouldn't work.
await devtoolsPanel.setViewportSize({ width: 640, height: 660 })

sdtFrame = devtoolsPanel.frameLocator('[src^="chrome-extension://"][src$="index.html"]')
}

await sdtFrame.getByText('Root').first().waitFor() // Wait for all tree nodes to be visible
await use(sdtFrame)
},
search: async ({ sdtFrame }, use) => {
await use(sdtFrame.getByPlaceholder('Search'))
},
})
73 changes: 73 additions & 0 deletions e2e/node-tree.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { expect } from '@playwright/test'
import { test } from './fixtures'

test('Search node in tree view', async ({ sdtFrame, search }) => {
const selectedNode = sdtFrame.getByRole('treeitem', { selected: true })
await search.fill('Theme')

// Press enter to select the matching node
await search.press('Enter')
await expect(selectedNode).toHaveText(/ThemeProvider/)

// Press enter to go to the next matching node
await search.press('Enter')
await expect(selectedNode).toHaveText(/ThemeExample/)
})

test('Picking node using locator', async ({ sdtFrame, page }) => {
const selectedNode = sdtFrame.getByRole('treeitem', { selected: true })
const zeroIsEven = page.getByText('0 is even!')

await sdtFrame.getByTitle('Select an element in the page to inspect it').click()

await zeroIsEven.hover()
await zeroIsEven.click()

await expect(selectedNode).toHaveText(/Bold/)
})

test('Reflected signal in Inspector', async ({ sdtFrame, page }) => {
await sdtFrame.getByText('App').click()

const count = sdtFrame.getByLabel('count', { exact: true })
const countButton = page.getByText('Count: 0').first()

await expect(count).toHaveText(/0/)
await countButton.click()
await expect(count).toHaveText(/1/)
})

test('Reflected memos in Inspector', async ({ sdtFrame, page, search }) => {
const todoInput = page.getByPlaceholder('enter todo and click +')
const todoButton = page.getByText('+')
const newTitle = sdtFrame.getByLabel('newTitle', { exact: true })
const signal = sdtFrame.getByLabel('valuesInASignal signal')
const values = signal.getByLabel('values', { exact: true })
const title = signal.getByLabel('title', { exact: true })
const done = signal.getByLabel('done', { exact: true })

await search.fill('Todos')
await search.press('Enter')

await signal.getByLabel(/Expand or collapse/).click()
await expect(values).toHaveText(/Empty Array/)
await expect(newTitle).toBeEmpty()

await todoInput.fill('Buy groceries')
await expect(newTitle).toHaveText(/Buy groceries/)
await todoButton.click()
await expect(newTitle).toBeEmpty()

await expect(values).toHaveText('Array [1]')

await signal.getByLabel('Expand or collapse values', { exact: true }).click()
await signal.getByLabel('Expand or collapse 0').click()

await expect(title).toHaveText(/Buy groceries/)
await expect(done).toBeChecked({ checked: false })
await page
.getByRole('checkbox')
.and(page.getByLabel(/Buy groceries/))
.check()
await expect(done).toBeChecked()
})
2 changes: 1 addition & 1 deletion examples/sandbox/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div id="root" class="prose p-6"></div>

<script src="/src/index.tsx" type="module"></script>
</body>
Expand Down
1 change: 1 addition & 0 deletions examples/sandbox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"devDependencies": {
"@babel/plugin-syntax-typescript": "^7.22.5",
"@unocss/preset-typography": "^0.54.1",
"solid-devtools": "workspace:^",
"unocss": "^0.53.6",
"vite-plugin-inspect": "^0.7.33"
Expand Down
1 change: 1 addition & 0 deletions examples/sandbox/src/Todos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const Todo: Component<{
type="checkbox"
checked={props.done}
onChange={e => props.onCheck(e.currentTarget.checked)}
aria-label={props.title}
/>
<input
type="text"
Expand Down
5 changes: 4 additions & 1 deletion examples/sandbox/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import devtools from 'solid-devtools/vite'
import { presetTypography } from 'unocss'
import Unocss from 'unocss/vite'
import { defineConfig } from 'vite'
import Inspect from 'vite-plugin-inspect'
Expand All @@ -20,7 +21,9 @@ export default defineConfig(mode => {
},
}),
solid({ hot: true, dev: true }),
Unocss(),
Unocss({
presets: [presetTypography()],
}),
Inspect(),
],
define: {
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"sandbox:ext": "pnpm -dir examples/sandbox run dev:ext",
"build": "turbo run build --filter=./packages/*",
"test": "turbo run test --filter=./packages/*",
"test:e2e": "cross-env PW_CHROMIUM_ATTACH_TO_OTHER=1 playwright test -c playwright.config.ts",
"typecheck": "turbo run typecheck --filter=./packages/*",
"build-test": "turbo run build test typecheck --filter=./packages/*",
"format": "prettier -w ./{packages,examples}/**/*.{js,ts,json,css,tsx,jsx} --ignore-path .gitignore",
Expand All @@ -24,6 +25,7 @@
"devDependencies": {
"@changesets/cli": "^2.26.2",
"@nothing-but/utils": "~0.3.2",
"@playwright/test": "^1.36.1",
"@total-typescript/ts-reset": "^0.4.2",
"@types/node": "^18.16.16",
"@typescript-eslint/eslint-plugin": "^6.2.0",
Expand Down
Loading

0 comments on commit d8ae33e

Please sign in to comment.