Skip to content

Commit

Permalink
Merge pull request #1 from author-more/test/add-testing-setup
Browse files Browse the repository at this point in the history
Add testing setup
  • Loading branch information
Belar authored Aug 4, 2024
2 parents 46a4a2b + 43b5cc4 commit 94a01e4
Show file tree
Hide file tree
Showing 11 changed files with 270 additions and 4 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Generate data
run: npm run generate-data
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run tests
run: npm run test
# - uses: actions/upload-artifact@v4
# if: always()
# with:
# name: playwright-report
# path: playwright-report/
# retention-days: 30
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ dist-ssr

# Plugin data
/data/icons/*
!/data/icons/.gitkeep
!/data/icons/.gitkeep

# Test files
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
9 changes: 8 additions & 1 deletion bin/generateIconSets.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { iconPackages } from "./config";
import { getFilesByExtension, writeToJSONFile, readFile } from "./files";

type Icon = {
svg: {
attributes: string;
elements: string;
};
};

iconPackages.forEach(({ id, iconsDir }: (typeof iconPackages)[number]) => {
const files = getFilesByExtension(iconsDir, ".svg");

const icons = {};
const icons: Record<string, Icon> = {};
for (const file of files) {
const svg = readFile(iconsDir, file);

Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>All Icons</title>
</head>
<body>
<div id="root"></div>
Expand Down
60 changes: 60 additions & 0 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"build": "tsc -b && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"format": "prettier . --write",
"test": "playwright test",
"preview": "vite preview",
"generate-data": "tsx ./bin/generateIconSets.ts"
},
Expand All @@ -20,6 +21,7 @@
},
"devDependencies": {
"@penpot/plugin-types": "^0.10.0",
"@playwright/test": "^1.45.3",
"@types/node": "^22.0.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
Expand Down
78 changes: 78 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { defineConfig, devices } from "@playwright/test";

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// dotenv.config({ path: path.resolve(__dirname, '.env') });

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},

/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},

{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
},

{
name: "webkit",
use: { ...devices["Desktop Safari"] },
},

/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],

/* Run your local dev server before starting the tests */
webServer: {
command: "npm run build && npm run preview",
port: 4173,
reuseExistingServer: !process.env.CI,
},
});
21 changes: 21 additions & 0 deletions tests/app.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { test, expect } from "@playwright/test";

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

test("opens", async ({ page }) => {
await expect(page).toHaveTitle(/All Icons/);
});

test("lists icons from multiple libraries", async ({ page }) => {
for (const libraryName of ["Lucide", "Iconoir"]) {
const title = page.getByRole("heading", { name: libraryName });
await expect(title).toBeVisible();
}

const iconButtons = page.getByRole("button", { name: /(Insert icon:).*/ });
expect(await iconButtons.count()).toBeGreaterThan(1);
});
});
39 changes: 39 additions & 0 deletions tests/icon.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { test, expect } from "@playwright/test";

type PluginUIEvent = {
type: string;
content: Record<string, unknown>;
};

const testIcon = {
name: "pickaxe",
svg: '<svg class="lucide lucide-pickaxe" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.531 12.469 6.619 20.38a1 1 0 1 1-3-3l7.912-7.912" /> <path d="M15.686 4.314A12.5 12.5 0 0 0 5.461 2.958 1 1 0 0 0 5.58 4.71a22 22 0 0 1 6.318 3.393" /> <path d="M17.7 3.7a1 1 0 0 0-1.4 0l-4.6 4.6a1 1 0 0 0 0 1.4l2.6 2.6a1 1 0 0 0 1.4 0l4.6-4.6a1 1 0 0 0 0-1.4z" /> <path d="M19.686 8.314a12.501 12.501 0 0 1 1.356 10.225 1 1 0 0 1-1.751-.119 22 22 0 0 0-3.393-6.319" /></svg>',
};

test.describe("icon", () => {
test("inserts an icon into a project", async ({ page }) => {
const eventLog: PluginUIEvent[] = [];

await page.exposeFunction("logEvent", (data: PluginUIEvent) =>
eventLog.push(data),
);
await page.addInitScript(() => {
// @ts-expect-error - TS doesn't know about logCall method.
const mockPostMessage = (data: PluginUIEvent) => logEvent(data);
window.parent.postMessage = mockPostMessage;
});

await page.goto("/");

const iconButton = page.getByRole("button", {
name: `Insert icon: ${testIcon.name}`,
});
await iconButton.click();

expect(eventLog.length).toEqual(1);
expect(eventLog[0]).toEqual({
type: "insert-icon",
content: testIcon,
});
});
});
24 changes: 24 additions & 0 deletions tests/search.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { test, expect } from "@playwright/test";

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

test("has phrase input", async ({ page }) => {
const input = page.getByLabel("Search icon");
await expect(input).toBeVisible();
});

test("filters icons by phrase", async ({ page }) => {
const iconButtons = page.getByRole("button", { name: /(Insert icon:).*/ });

expect(await iconButtons.count()).toBeGreaterThan(1);

const input = page.getByLabel("Search icon");
await input.fill("pickaxe");

expect(await iconButtons.count()).toEqual(1);
expect(await iconButtons.textContent()).toContain("Insert icon: pickaxe");
});
});
2 changes: 1 addition & 1 deletion tsconfig.node.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"strict": true,
"noEmit": true
},
"include": ["vite.config.ts", "bin"]
"include": ["vite.config.ts", "bin", "playwright.config.ts", "tests"]
}

0 comments on commit 94a01e4

Please sign in to comment.