Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: E2E Testing
on:
workflow_dispatch:
pull_request:
branches: [develop]
issue_comment:
types: [created]
jobs:
test-e2e:
# temporary while new e2e environment is not yet created:
# only trigger on workflow_dispatch, maintainer comment, or if PR is from GSOC project mentor or mentee
if: >
github.event_name == 'workflow_dispatch' ||
(
github.event_name == 'pull_request' &&
contains(fromJSON('["Geethegreat", "clairep94"]'), github.event.pull_request.user.login)
) ||
(
github.event.issue.pull_request &&
github.event.comment.body == '/e2e' &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
)
timeout-minutes: 60
runs-on: ubuntu-latest

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a new e2e environment to the github repo?

So that we can add environment: 'e2e' here --> would gate workflow runs on maintainer approval


steps:
- name: Resolve PR head ref
if: github.event_name == 'issue_comment'
id: pr
uses: actions/github-script@v7
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
});
core.setOutput('sha', pr.head.sha);

- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'issue_comment' && steps.pr.outputs.sha || github.ref }}

- name: Set up node
uses: actions/setup-node@v4
with:
node-version: '18.20.x'
cache: 'npm'

- name: Create .env file
run: cp .env.example .env

- name: Start MongoDB
uses: supercharge/mongodb-github-action@1.10.0
with:
mongodb-version: '6.0'

- name: Install dependencies
run: npm ci

- name: Cache Playwright browsers
uses: actions/cache@v4
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ hashFiles('package-lock.json') }}

- name: Install Playwright Browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: npx playwright install --with-deps chromium

- name: Install Playwright deps (OS libraries)
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: npx playwright install-deps chromium

- name: Start app
run: npm start > app.log 2>&1 &

- name: Wait for app to be ready
run: |
npx wait-on@7 http://localhost:8000 --timeout 180000 || {
echo "::error::App failed to become ready at http://localhost:8000 within 180s"
echo "----- app.log -----"
cat app.log
exit 1
}

- name: Run Playwright tests
run: npm run e2e:ci

- name: Upload artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 30
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,11 @@ duplicates.json

coverage

*.tsbuildinfo
*.tsbuildinfo

# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/
60 changes: 60 additions & 0 deletions e2e/editor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { test, expect } from '@playwright/test';

test.describe('editor page', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/');

// initial pageload check to fail fast:
await expect(page.locator('a.skip_link[href="#play-sketch"]')).toHaveText(
'Skip to Play Sketch'
);

// Dismiss cookie banner if it appears
// Note: we do document.querySelectorAll instead of page.locator as workaround due to the buttons on the banner being beyond the viewport
await page.evaluate(() => {
const btn = Array.from(document.querySelectorAll('button')).find((b) =>
/allow essential|allow all/i.test(b.textContent ?? '')
) as HTMLElement | undefined;
btn?.click();
});

// wait for page to fully load with all main IDE components:
await expect(page.locator('#play-sketch')).toBeVisible(); // play button
await expect(page.locator('iframe[title="sketch preview"]')).toBeVisible(); // sketch preview
await expect(page.locator('.preview-console')).toBeVisible(); // editor console
await expect(page.locator('.editor-holder')).toBeVisible(); // editor -- NOTE: .editor-holder .CodeMirror cannot be found on CI for some reason, so we are using .editor-holder instead.
});

test('can run sketch code written in the editor', async ({ page }) => {
const newCode = [
'function setup() {',
' createCanvas(400, 400);',
'}',
'',
'function draw() {',
' background(220);',
" console.log('hi from sketch');",
' noLoop();',
'}'
].join(''); // Purposely joining without '\n' to avoid triggering the autocomplete with keyboard.type & creating extra brackets

// Find editor text area, clear default code & type in the new code
const editor = page.locator('.editor-holder');
await editor.click();
await page.keyboard.press('ControlOrMeta+A');
await page.keyboard.type(newCode, { delay: 5 }); // Purposely using .type instead of .insert (.insert does not work with the redux state management)

// Click Play
await page.locator('#play-sketch').click({ force: true });

// Wait for the sketch iframe src to confirm the sketch actually started
await expect(
page.locator('iframe[title="sketch preview"]')
).toHaveAttribute('src', /8002/, { timeout: 10_000 });

// Assert console output
await expect(
page.locator('.preview-console__messages')
).toContainText('hi from sketch', { timeout: 15_000 });
});
});
11 changes: 11 additions & 0 deletions e2e/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"lib": ["ES2022", "dom"],
"types": ["node"]
},
"include": ["./**/*", "../playwright.config.ts"],
"exclude": ["../node_modules"]
}
77 changes: 76 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"build:client": "cross-env NODE_ENV=production webpack --config webpack/config.prod.js",
"build:server": "cross-env NODE_ENV=production webpack --config webpack/config.server.js",
"build:examples": "cross-env NODE_ENV=production webpack --config webpack/config.examples.js",
"e2e": "npx playwright test --ui",
"e2e:headed": "npx playwright test --headed",
"e2e:ci": "npx playwright test",
"test": "NODE_ENV=test jest",
"test:watch": "NODE_ENV=test jest --watch",
"test:ci": "npm run lint && npm run test",
Expand Down Expand Up @@ -121,6 +124,7 @@
"@babel/preset-env": "^7.14.7",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.27.1",
"@playwright/test": "^1.61.1",
"@storybook/addon-actions": "^7.6.8",
"@storybook/addon-docs": "^7.6.8",
"@storybook/addon-essentials": "^7.6.8",
Expand Down
Loading
Loading