AI-powered adeno-associated virus (AAV) vector design for gene therapy including capsid engineering, promoter selection, and tropism optimization.
日本語の概要は準備中です。原文の説明を表示しています。
Playwright automation, Chrome DevTools debugging, and browser interaction testing. Use for E2E/unit tests, capturing screenshots, inspecting network/console logs, or validating user flows in web applications.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Comprehensive toolkit for testing and debugging web applications using Playwright automation and Chrome DevTools.
Use symptom -> action triggers: when one matches, apply this skill and verify with the protocol below.
Playwright Testing:
Chrome DevTools Debugging:
import { test, expect, Page, Browser } from '@playwright/test';
// Navigate to URLs
await page.goto('https://example.com');
await page.waitForLoadState('networkidle');
// Click buttons and links
await page.click('#submit-button');
await page.click('text=Continue');
// Fill form fields
await page.fill('#email', 'user@example.com');
await page.fill('#password', 'securepassword');
// Select dropdowns
await page.selectOption('#country', 'United States');
// Handle dialogs and alerts
page.on('dialog', async dialog => {
await dialog.accept(); // or dialog.dismiss()
});
test('complete checkout flow', async ({ page }) => {
// Add to cart
await page.goto('/products');
await page.click('text=Add to Cart');
// Navigate to cart
await page.goto('/cart');
// Verify item in cart
await expect(page.locator('.cart-item')).toHaveCount(1);
// Checkout
await page.click('text=Checkout');
await page.fill('#email', 'test@example.com');
await page.fill('#shipping-address', '123 Main St');
await page.click('text=Place Order');
// Verify success
await expect(page.locator('.success-message')).toBeVisible();
});
test('form validation', async ({ page }) => {
await page.goto('/register');
// Submit empty form - should show errors
await page.click('text=Submit');
// Check error messages
await expect(page.locator('.error-email')).toBeVisible();
await expect(page.locator('.error-password')).toBeVisible();
// Fill valid data
await page.fill('#email', 'valid@example.com');
await page.fill('#password', 'securePass123!');
await page.click('text=Submit');
// Verify no errors and success
await expect(page.locator('.error-email')).not.toBeVisible();
await expect(page.locator('.success-message')).toBeVisible();
});
test.describe('Responsive Design', () => {
const viewports = [
{ name: 'Mobile', width: 375, height: 667 },
{ name: 'Tablet', width: 768, height: 1024 },
{ name: 'Desktop', width: 1280, height: 720 },
];
viewports.forEach(({ name, width, height }) => {
test(`layout on ${name} (${width}x${height})`, async ({ page }) => {
await page.setViewportSize({ width, height });
await page.goto('/');
// Check navigation is visible and accessible
const nav = page.locator('nav');
await expect(nav).toBeVisible();
// On mobile, check hamburger menu is present
if (width < 768) {
await expect(page.locator('.mobile-menu-toggle')).toBeVisible();
} else {
await expect(page.locator('.mobile-menu-toggle')).not.toBeVisible();
}
// Screenshot for comparison
await page.screenshot({
path: `screenshots/${name.toLowerCase()}-layout.png`,
fullPage: true,
});
});
});
});
test('console errors and warnings', async ({ page, context }) => {
const errors: string[] = [];
// Listen for console errors
page.on('console', msg => {
if (msg.type() === 'error') {
errors.push(msg.text());
}
});
await page.goto('/');
// Assertions
expect(errors).toEqual([]);
});
test('network requests monitoring', async ({ page }) => {
const requests: string[] = [];
page.on('request', request => {
requests.push(request.url());
});
await page.goto('/');
// Verify API calls
const apiRequests = requests.filter(url => url.includes('/api/'));
expect(apiRequests.length).toBeGreaterThan(0);
// Verify no 404s
const failedResponses: any[] = [];
page.on('response', response => {
if (response.status() === 404) {
failedResponses.push(response.url());
}
});
await page.click('a[href="/about"]');
expect(failedResponses).toEqual([]);
});
test('basic accessibility checks', async ({ page }) => {
// Check heading hierarchy
const headings = await page.locator('h1, h2, h3').all();
expect(headings[0]).toHaveText('Main Heading'); // h1 should be first
// Check images have alt text
const imagesWithoutAlt = await page.locator('img:not([alt])').count();
expect(imagesWithoutAlt).toBe(0);
// Check form labels
const inputs = await page.locator('input, select, textarea').all();
for (const input of inputs) {
const hasLabel = await input.evaluate(el => {
return el.labels.length > 0 || el.getAttribute('aria-label');
});
expect(hasLabel).toBeTruthy();
}
// Check keyboard navigation
await page.keyboard.press('Tab');
const focusedElement = await page.evaluate(() => document.activeElement?.tagName);
expect(['INPUT', 'BUTTON', 'A']).toContain(focusedElement);
});
import { compareScreenshots } from './visual-utils';
test('visual regression - home page', async ({ page }) => {
await page.goto('/');
// Wait for all images and fonts to load
await page.waitForLoadState('networkidle');
await page.waitForTimeout(1000);
// Take screenshot
const screenshot = await page.screenshot({
fullPage: true,
});
// Compare with baseline
const diff = await compareScreenshots(screenshot, 'baseline/home.png');
expect(diff.pixelDifference).toBeLessThan(100); // Threshold
});
// Open new page
await chrome.newPage();
// Navigate to URL
await chrome.navigatePage('https://example.com');
// Reload current page
await chrome.navigatePage({ action: 'reload' });
// Navigate history
await chrome.navigatePage({ action: 'back' });
await chrome.navigatePage({ action: 'forward' });
// List all open pages
const pages = await chrome.listPages();
await chrome.selectPage(pages[0].id);
// Close specific page
await chrome.closePage('page-id-here');
// Wait for text to appear
await chrome.waitFor('Welcome to the site');
// Take snapshot to get element IDs
const snapshot = await chrome.takeSnapshot();
// Find element by uid
const submitButton = snapshot.elements.find(el => el.text === 'Submit');
// Click element
await chrome.click(submitButton.uid);
// Fill single field
await chrome.fill(inputUid, 'value@example.com');
// Fill multiple fields at once
await chrome.fillForm([
{ uid: emailInputUid, value: 'test@example.com' },
{ uid: passwordInputUid, value: 'password123' },
{ uid: nameInputUid, value: 'John Doe' },
]);
// Hover over element
await chrome.hover(buttonUid);
// Press keyboard shortcuts
await chrome.pressKey('Enter');
await chrome.pressKey('Control+C');
// Drag and drop
await chrome.drag(sourceUid, targetUid);
// Handle browser dialogs
await chrome.handleDialog('accept');
await chrome.handleDialog('dismiss');
// Get accessibility tree (best for finding elements)
const snapshot = await chrome.takeSnapshot();
// Take visual screenshot
const screenshot = await chrome.takeScreenshot();
// List all console messages
const messages = await chrome.listConsoleMessages();
// Get messages by level
const errors = await chrome.listConsoleMessages('error');
const warnings = await chrome.listConsoleMessages('warning');
// Get specific message details
const message = await chrome.getConsoleMessage(messageId);
// Evaluate JavaScript in page context
const result = await chrome.evaluateScript('document.title');
const userInfo = await chrome.evaluateScript(`
JSON.parse(localStorage.getItem('user'))
`);
// List network requests
const requests = await chrome.listNetworkRequests();
// Get failed requests
const failedRequests = requests.filter(req =>
req.status >= 400 || req.status === 0
);
// Get specific request details
const requestDetails = await chrome.getNetworkRequest(requestId);
// Resize viewport
await chrome.resizePage({ width: 375, height: 667 }); // Mobile
// Emulate network conditions
await chrome.emulate({
network: 'offline' // 'slow-3g', 'fast-3g', 'online'
});
// Emulate geolocation
await chrome.emulate({
geolocation: { lat: 40.7128, lon: -74.0060 }
});
// Start performance trace
await chrome.performanceStartTrace({ reload: true });
// Stop trace after navigation
await chrome.waitFor('Page loaded');
const trace = await chrome.performanceStopTrace();
// Get insights
const insights = await chrome.performanceAnalyzeInsight();
console.log('LCP:', insights.largestContentfulPaint);
console.log('CLS:', insights.cumulativeLayoutShift);
Always prefer snapshot over screenshot for finding elements:
// 1. Get current page structure
const snapshot = await chrome.takeSnapshot();
// 2. Find the target element by its uid
const element = snapshot.elements.find(el => el.text === 'Continue');
// 3. Use the uid for interaction
await chrome.click(element.uid);
When a page is failing, check both console and network:
// 1. Check console messages for JavaScript errors
const errors = await chrome.listConsoleMessages('error');
console.log('JavaScript Errors:', errors);
// 2. Check network requests for failures
const requests = await chrome.listNetworkRequests();
const failed = requests.filter(r => r.status >= 400);
console.log('Failed Requests:', failed);
// 3. Check specific values via JavaScript
const apiResponse = await chrome.evaluateScript(`
window.lastApiResponse
`);
console.log('Last API Response:', apiResponse);
Identify why a page is slow:
// 1. Start performance trace with reload
await chrome.performanceStartTrace({ reload: true, autoStop: true });
// 2. Wait for trace to complete
const timeout = 10000;
await new Promise(resolve => setTimeout(resolve, timeout));
// 3. Get performance insights
const insights = await chrome.performanceAnalyzeInsight();
console.log('Performance Issues:', insights.issues);
console.log('LCP:', insights.largestContentfulPaint);
console.log('CLS:', insights.cumulativeLayoutShift);
console.log('FID:', insights.firstInputDelay);
// 4. Identify bottlenecks
if (insights.largestContentfulPaint > 2500) {
console.warn('LCP is slow - consider optimizing images and CSS');
}
if (insights.cumulativeLayoutShift > 0.1) {
console.warn('CLS is high - avoid layout shifts');
}
test.describe('User Authentication', () => {
test.beforeEach(async ({ page }) => {
// Setup: login fresh each test
await page.goto('/login');
});
test('successful login with valid credentials', async ({ page }) => {
await test.step('Enter credentials', async () => {
await page.fill('#email', 'valid@example.com');
await page.fill('#password', 'correct-password');
});
await test.step('Submit form', async () => {
await page.click('text=Login');
});
await test.step('Verify redirected to dashboard', async () => {
await expect(page).toHaveURL('/dashboard');
});
});
test('shows error for invalid credentials', async ({ page }) => {
await page.fill('#email', 'invalid@example.com');
await page.fill('#password', 'wrong-password');
await page.click('text=Login');
await expect(page.locator('.error-message')).toBeVisible();
await expect(page).toHaveURL('/login');
});
});
// pages/LoginPage.ts
export class LoginPage {
constructor(private page: Page) {}
async goto() {
await this.page.goto('/login');
}
async login(email: string, password: string) {
await this.page.fill('#email', email);
await this.page.fill('#password', password);
await this.page.click('text=Login');
}
async getErrorMessage() {
return await this.page.locator('.error-message').textContent();
}
assertVisible() {
expect(this.page.locator('h1')).toHaveText('Login');
}
}
// Tests
test('login flow', async ({ page }) => {
const loginPage = new LoginPage(page);
loginPage.goto();
await loginPage.login('user@example.com', 'password');
await expect(page).toHaveURL('/dashboard');
});
// playwright.config.ts
export default defineConfig({
workers: process.env.CI ? 2 : 4, // Parallel execution
projects: [
{
name: 'chromium',
use: { browserName: 'chromium' },
},
{
name: 'firefox',
use: { browserName: 'firefox' },
},
{
name: 'webkit',
use: { browserName: 'webkit' },
},
],
});
| Task | Playwright | Chrome DevTools |
|---|---|---|
| Browser Automation | Yes | Yes |
| Page Navigation | page.goto() | navigate_page() |
| Click Elements | page.click() | click(uid) |
| Fill Forms | page.fill() | fill(uid, value) |
| Screenshots | page.screenshot() | take_screenshot() |
| Console Logs | page.on('console') | list_console_messages() |
| Network Requests | page.on('request') | list_network_requests() |
| JavaScript Eval | page.evaluate() | evaluate_script() |
| Viewport Resize | page.setViewportSize() | resize_page() |
| Performance | Trace API | performance_* tools |
| Device Emulation | deviceDescriptor | emulate() |
# Run Playwright tests
npx playwright test
# Run tests with UI (helps debugging)
npx playwright test --ui
# Run tests in headed mode (watch browser)
npx playwright test --headed
# Debug specific test
npx playwright test tests/login.spec.ts --debug
# Generate codegen from browser actions
npx playwright codegen https://example.com
Before claiming "skill applied successfully":
This skill is written to stay usable across GitHub Copilot, Claude Code, and Codex.
$CODEX_HOME/skills/web-testing and restart Codex after major changes.Preferred MCP Server: Playwright MCP
SKILL.md, bundled references or scripts, and manual verification. Show the exact commands, evidence, and final checks you used before concluding."npx playwright test, headed mode, or codegen) and browser devtools when MCP browser tools are unavailable.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
AI-powered adeno-associated virus (AAV) vector design for gene therapy including capsid engineering, promoter selection, and tropism optimization.
日本語の概要は準備中です。原文の説明を表示しています。
Improve the clarity and voice of AI-assisted academic writing (papers, theses, rebuttals) and
日本語の概要は準備中です。原文の説明を表示しています。
12-agent academic paper writing pipeline. 11 modes (full/plan/outline/revision/revision-coach/abstract/lit-review/format-convert/citation-check/disclosure/rebuttal-audit). 6 paper types, 5 citation formats, bilingual abstracts, LaTeX/DOCX-via-Pandoc/PDF output. Style Calibration + Writing Quality Check + Anti-Patterns with IRON RULE markers. Triggers: write paper, academic paper, guide my paper, parse reviews, audit my rebuttal, check my response draft, AI disclosure, 寫論文, 學術論文, 引導我寫論文, 審查意見, 評估回覆, 논문 작성, 초록 작성, 논문 수정, 논문 계획을 도와줘, 심사 의견 반영, 답변서 점검, AI 사용 고지.
日本語の概要は準備中です。原文の説明を表示しています。
Systematic writing framework for philosophy and interdisciplinary academic papers from optimized outline to submission-ready manuscript. Use when users want to: (1) write a paper from a detailed outline, (2) ensure quality control during writing, (3) maintain consistency across chapters, (4) prepare a submission-ready manuscript, or (5) systematically execute a planned paper. Triggered by phrases like 'write the paper from this outline,' 'compose the full manuscript,' 'execute the outline,' or when users have completed strategic planning (academic-paper-strategist skill) and are ready to write. Takes optimized outline as input; outputs complete manuscript with iterative quality checks.
日本語の概要は準備中です。原文の説明を表示しています。
Multi-perspective academic paper review with dynamic reviewer personas. Runs a 5-seat, role-separated review panel (Journal-Fit Reviewer + 3 peer-review roles + Devil's Advocate) with field-specific expertise; role separation is not a claim of independent error processes. Supports full review, re-review (verification), quick assessment, methodology focus, Socratic guided, and calibration modes. Triggers on: review paper, peer review, manuscript review, referee report, review my paper, critique paper, simulate review, editorial review, calibrate reviewer, reviewer calibration, measure reviewer accuracy, 審查論文, 論文審查, 模擬審查, 同儕審查, 幫我審這篇, 以審查人角度評估, 審查者校準, 논문 심사, 동료 심사, 모의 심사, 심사자 관점에서 평가, 심사자 보정.
日本語の概要は準備中です。原文の説明を表示しています。
Systematic strategic planning framework for philosophy and interdisciplinary academic papers targeting preprint platforms (PhilArchive, arXiv, PhilSci-Archive). Use when users want to: (1) plan a paper on a specific topic, (2) identify research gaps and assess originality, (3) develop optimized paper outlines, (4) prepare for preprint submission, or (5) understand platform requirements and writing standards. Triggered by phrases like 'plan a paper on,' 'help me design a paper about,' 'identify research gaps in,' 'is this idea original,' or when users need structured research planning. The skill guides through three phases: Platform Analysis (identifying target venue and studying sample papers), Theoretical Framework (AI-driven literature search and gap identification), and Outline Optimization (structured design with reviewer-perspective self-assessment). Each phase includes quality evaluation standards and validation checkpoints.
日本語の概要は準備中です。原文の説明を表示しています。