diff --git a/.claude/commands/implement-upstream-change.md b/.claude/commands/implement-upstream-change.md deleted file mode 100644 index 08ce323cf..000000000 --- a/.claude/commands/implement-upstream-change.md +++ /dev/null @@ -1,17 +0,0 @@ -# Context -You are a software developer integrating changes from a project written in TypeScript into a .NET project. -We call upstream to the original typescript project. - -# Task - -You are going to check the changes on the PR $ARGUMENTS -You will find the upstream repository at ../../puppeteer/puppeteer. Feel free to read the code there and even make git action to bring the changes you need to evaluate. - -Once you have all the context, you will implement the same changes in this .NET project. -You will create a new branch named `implement-upstream-change-` where `` is the number of the PR you are implementing. -You will have to implement the code as close as possible to the original code, but adapted to .NET idioms and practices. - -As part of the task you will need to generate a document explaining the changes you made, and how they relate to the original PR. - -You need to run related tests to ensure everything is working as expected. -If tests are failing, you will need to fix them. diff --git a/.claude/commands/implement-bidi-feature.md b/.claude/skills/implement-bidi-feature/SKILL.md similarity index 100% rename from .claude/commands/implement-bidi-feature.md rename to .claude/skills/implement-bidi-feature/SKILL.md diff --git a/.claude/skills/implement-upstream-change/SKILL.md b/.claude/skills/implement-upstream-change/SKILL.md new file mode 100644 index 000000000..3fffb22c3 --- /dev/null +++ b/.claude/skills/implement-upstream-change/SKILL.md @@ -0,0 +1,46 @@ +# Context +You are a software developer integrating changes from a project written in TypeScript into a .NET project. +We call upstream to the original typescript project. + +# Task + +You are going to check the changes on the PR $ARGUMENTS +You will find the upstream repository at ../../puppeteer/puppeteer. Feel free to read the code there and even make git actions to bring the changes you need to evaluate. + +Once you have all the context, you will implement the same changes in this .NET project. + +## Git Workflow + +1. Fetch the latest from origin: `git fetch origin` +2. Create a new branch from `origin/master` named `implement-upstream-change-` where `` is the number of the PR you are implementing: `git checkout -b implement-upstream-change- origin/master` +3. Implement all the changes (see below) +4. Commit your changes with a descriptive message +5. Push the branch: `git push -u origin implement-upstream-change-` +6. Create a PR via `gh pr create` targeting `master` + +## Implementation + +You will have to implement the code as close as possible to the original code, but adapted to .NET idioms and practices. + +### Porting Tests + +All tests brought from upstream **must** use the `[Test, PuppeteerTest(...)]` attribute header. The attribute signature is: + +```csharp +[Test, PuppeteerTest("", "", "")] +``` + +- ``: the upstream `.spec.ts` filename (e.g. `"network.spec"`). +- ``: the nested `describe` block titles joined, matching the upstream structure (e.g. `"network"`). +- ``: the `it(...)` test title from upstream (e.g. `"should set bodySize and headersSize"`). + +Look at existing tests in the project for reference on how these attributes are used. + +## Verification + +You need to run related tests to ensure everything is working as expected. +If tests are failing, you will need to fix them. + +## Summary + +As part of the task you will need to generate a document explaining the changes you made, and how they relate to the original PR. diff --git a/.github/agents/bidi-migration.md b/.github/agents/bidi-migration.md deleted file mode 100644 index c2414d973..000000000 --- a/.github/agents/bidi-migration.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -name: Bidi migration -description: Implement bidi code ---- - -# Context -You are a software developer integrating changes from a project written in TypeScript into a .NET project. -We call upstream to the original typescript project. -This task should use the **v21 branch** as base branch and to create pull requests. -Use the puppeteer-sharp/lib/CLAUDE.md for project context. - -## Upstream Repositories -- Upstream puppeteer: https://github.com/puppeteer/puppeteer/ -- Upstream webdriver bidi: https://github.com/webdriverbidi-net/webdriverbidi-net - -Clone these if needed to reference implementation: -```bash -cd /home/runner/work -git clone --depth 1 https://github.com/puppeteer/puppeteer.git -git clone --depth 1 https://github.com/webdriverbidi-net/webdriverbidi-net.git -``` - -# Task - -You are going to implement the changes to make $ARGUMENTS pass. - -## Step-by-Step Process - -1. **Find and analyze the test expectation** - - Location: `lib/PuppeteerSharp.Nunit/TestExpectations/TestExpectations.local.json` - - Find the entry with `testIdPattern` matching $ARGUMENTS - - Note: The pattern may not exist exactly as specified. Check for broader patterns that include it. - - Example: If looking for `[jshandle.spec] *.evaluateHandle*`, you might find `[jshandle.spec] *` instead - -2. **Locate matching tests** - - Tests are in `lib/PuppeteerSharp.Tests/` - - Look for `[Test, PuppeteerTest("spec-file", "category", "test-name")]` attributes - - Pattern matching examples: - - `[jshandle.spec] *.evaluateHandle*` matches: `[Test, PuppeteerTest("jshandle.spec", "JSHandle Page.evaluateHandle", "should work")]` - - `[chromiumonly.spec] Chromium-Specific *` matches: `[Test, PuppeteerTest("chromiumonly.spec", "Chromium-Specific Page Tests", "...")]` - -3. **Check if implementation already exists** - - **IMPORTANT**: Many features may already be implemented! Check the code BEFORE making changes. - - BiDi implementations are in `lib/PuppeteerSharp/Bidi/` - - Key files to check: - - `BidiRealm.cs` - Main realm implementation - - `BidiJSHandle.cs` - JSHandle for BiDi - - `BidiElementHandle.cs` - ElementHandle for BiDi - - `BidiFrame.cs` - Frame for BiDi - - Base implementations are in `lib/PuppeteerSharp/` - - If the feature is already implemented, document this in the PR description - -4. **Reference upstream implementation** (if code changes needed) - - Puppeteer TypeScript: `/home/runner/work/puppeteer/packages/puppeteer-core/src/` - - BiDi-specific code: `/home/runner/work/puppeteer/packages/puppeteer-core/src/bidi/` - - Test files: `/home/runner/work/puppeteer/test/src/` - - WebDriver BiDi .NET: `/home/runner/work/webdriverbidi-net/` - -5. **Implement or verify the code** - - Port TypeScript to C# using .NET idioms - - Match the upstream logic as closely as possible - - Common patterns: - - TypeScript `async methodName(...args): Promise` → C# `Task MethodNameAsync(params object[] args)` - - TypeScript `using` (explicit resource management) → C# `await using` / `IAsyncDisposable` - - Handle delegation: JSHandle methods often delegate to Realm with handle as first argument - -6. **Update test expectations** - - If feature is working, remove or refine the test expectation entry - - Be careful with broad patterns like `[jshandle.spec] *` - only remove if ALL tests pass - - Consider creating more specific patterns if only some tests work - -7. **Document in PR description** (NOT in separate files) - - **Do NOT create IMPLEMENTATION_NOTES.md, SUMMARY.md, or similar documentation files** - - Put ALL implementation details, analysis, and findings in the PR description - - Include: - - What tests are affected - - Implementation status (already working, new code added, or partially working) - - Key code components involved - - Comparison with upstream TypeScript if relevant - -8. **Test verification** - - Run tests with: `BROWSER=FIREFOX PROTOCOL=webDriverBiDi dotnet test --filter "TestName"` - - Build first if needed: `dotnet build lib/PuppeteerSharp.sln` - - Note: May need self-signed certificate for test server (see setup below) - -## Important Notes - -- **Start from v21 branch**: Always checkout v21 first before creating your feature branch -- **Check existing code**: Many features are already implemented - verify before making changes -- **No separate docs**: All documentation goes in the PR description, not in separate markdown files -- **Test patterns**: Use wildcards to match multiple tests, be careful with broad patterns -- **BiDi vs CDP**: This is for WebDriver BiDi protocol (Firefox), not Chrome DevTools Protocol - -## Setup Requirements - -If building/testing is needed: - -**Self-signed certificate for test server:** -```bash -cd lib/PuppeteerSharp.TestServer -openssl req -x509 -newkey rsa:2048 -keyout testKey.pem -out testCert.cer -days 365 -nodes -subj "/CN=localhost" -``` - -**Update .gitignore** to exclude test certificates: -``` -lib/PuppeteerSharp.TestServer/testKey.pem -lib/PuppeteerSharp.TestServer/testCert.cer -``` - -## Code Structure Reference - -``` -lib/PuppeteerSharp/ -├── Bidi/ # BiDi protocol implementations -│ ├── BidiRealm.cs # Main realm - handles evaluation -│ ├── BidiJSHandle.cs # JSHandle for BiDi -│ ├── BidiElementHandle.cs # ElementHandle for BiDi -│ ├── BidiFrame.cs # Frame for BiDi -│ └── Core/ # Core BiDi protocol classes -├── JSHandle.cs # Base JSHandle class -├── Realm.cs # Base Realm class -└── IJSHandle.cs # JSHandle interface - -lib/PuppeteerSharp.Tests/ -├── JSHandleTests/ # JSHandle tests -├── FrameTests/ # Frame tests -└── ... # Other test directories - -lib/PuppeteerSharp.Nunit/TestExpectations/ -└── TestExpectations.local.json # Test expectations to modify -``` diff --git a/.github/agents/puppeteer-sharp-main-agent.md b/.github/agents/puppeteer-sharp-main-agent.md deleted file mode 100644 index 544fd77fa..000000000 --- a/.github/agents/puppeteer-sharp-main-agent.md +++ /dev/null @@ -1,482 +0,0 @@ ---- -name: Puppeteer-Sharp main agent -description: Puppeteer-sharp expert ---- - -# PuppeteerSharp Codebase Overview - -PuppeteerSharp is a C# library for automating Chromium-based browsers and Firefox. It provides a high-level API to control browsers via the DevTools Protocol (CDP) and WebDriver BiDi protocol. - -## Goal - -The goal of this project is to port the popular Node.js Puppeteer library to .NET. -Everything in PuppeteerSharp is inspired by the original Puppeteer library, but adapted to C# idioms and .NET practices. - -## External Sources: -These external sources are referenced or used as inspiration in the codebase. Feel free to explore them for a deeper understanding. -You may run git commands to update these repositories locally. - -- Original Puppeteer repository: https://github.com/puppeteer/puppeteer/. Every time "upstream" is mentioned, we are referring to this code. -- Bidi Driver: https://github.com/webdriverbidi-net/webdriverbidi-net - -## Upstream code structure - -- Code in upstream puppeteer-core/src/api/* are our abstract class. For instanc,e our public abstract class Frame. -- Code in upstream puppeteer-core/src/bidi/* are our Bidi* classes. -- Code in upstream puppeteer-core/src/cdp/* are our Cdp* classes. - -## Project Structure - -``` -lib/ -├── PuppeteerSharp/ # Main library -│ ├── Bidi/ # WebDriver BiDi protocol implementation (45 files) -│ ├── Cdp/ # Chrome DevTools Protocol implementation (204 files) -│ ├── Transport/ # Communication layer (WebSocket, etc.) -│ ├── Helpers/ # Utility functions and extensions -│ ├── Input/ # Keyboard, Mouse, Touchscreen input handling -│ ├── Media/ # Screenshot, PDF, viewport options -│ ├── Mobile/ # Device descriptors and emulation -│ ├── PageAccessibility/ # Accessibility tree and ARIA handling -│ ├── PageCoverage/ # Code coverage tracking -│ ├── QueryHandlers/ # CSS, XPath, Pierce, Text selectors -│ ├── BrowserData/ # Browser version and channel management -│ ├── States/ # Process state machine -│ ├── Injected/ # JavaScript to be injected into pages -│ └── *.cs # Core classes (Browser, Page, Frame, etc.) -├── PuppeteerSharp.Tests/ # 58+ test categories (~45k+ test files) -├── PuppeteerSharp.Nunit/ # NUnit test framework integration -├── PuppeteerSharp.TestServer/ # Local HTTP server for testing -├── PuppeteerSharp.TestServer/wwwroot/ # Test fixtures and assets -├── demo/ # Demo application -└── PuppeteerSharp.sln # Solution file -``` - -## Key Architecture Patterns - -### Dual Protocol Support: CDP vs BiDi - -PuppeteerSharp supports two browser automation protocols: - -1. **Chrome DevTools Protocol (CDP)**: - - Implemented in: `CdpBrowser`, `CdpPage`, `CdpFrame`, `CdpTarget`, etc. - - CDP-specific implementation classes - - Used for Chromium-based browsers and Firefox - - Classes: `CdpJSHandle`, `CdpElementHandle`, `CdpKeyboard`, `CdpMouse`, etc. - -2. **WebDriver BiDi Protocol**: - - Implemented in: `BidiBrowser`, `BidiPage`, `BidiFrame`, `BidiTarget`, etc. - - Newer, more standardized protocol - - Lower-level core implementations in `Bidi/Core/` directory - - Classes: `BidiJSHandle`, `BidiElementHandle`, `BidiMouse`, etc. - - Events: `BidiBrowsingContextEventArgs`, `UserPromptEventArgs`, `ResponseEventArgs`, etc. - -### Protocol Abstraction Pattern - -The library uses a base class pattern with protocol-specific implementations: - -- **Interface Level**: `IBrowser`, `IPage`, `IFrame`, `IRequest`, `IResponse` -- **Abstract Base Classes**: `Browser`, `Page`, `Frame`, `Request`, `Response` -- **Protocol Implementations**: `CdpBrowser`/`BidiBrowser`, `CdpPage`/`BidiPage`, etc. - -This design allows code to work with either protocol transparently through interfaces. - -## Core Components - -### 1. Entry Point: Puppeteer Static Class -- **File**: `/PuppeteerSharp/Puppeteer.cs` -- **Key Methods**: - - `LaunchAsync(LaunchOptions)`: Launch a browser instance - - `ConnectAsync(ConnectOptions)`: Connect to existing browser - - `GetDefaultArgs()`: Get default browser launch arguments - - Static properties: `Devices`, `NetworkConditions`, `ExtraJsonSerializerContext` - -### 2. Browser Management - -#### `Launcher` Class -- Determines which browser to launch (Chrome, Chromium, Firefox) -- Resolves executable path -- Creates appropriate launcher (`ChromeLauncher` or `FirefoxLauncher`) -- Handles process lifecycle - -#### `IBrowser` Interface & `Browser` Abstract Class -- **Key Properties**: - - `WebSocketEndpoint`: Connection URL - - `BrowserType`: Chrome, Chromium, or Firefox - - `DefaultContext`: Default browser context - - `DefaultWaitForTimeout`: Global timeout setting -- **Key Methods**: - - `NewPageAsync()`: Create new page - - `CreateBrowserContextAsync()`: Create isolated context - - `Targets()`: Get all targets (pages, workers, etc.) - - `PagesAsync()`: Get all pages across contexts - - `GetVersionAsync()`: Browser version - - `Disconnect()`: Disconnect from browser - -### 3. Page Model - -#### `IPage` Interface & `Page` Abstract Class -- **Key Properties**: - - `MainFrame`: Primary frame - - `Frames`: All frames in page - - `Url`: Current URL - - `Workers`: Web workers - - `Keyboard`, `Mouse`, `Touchscreen`: Input devices -- **Key Events**: (40+ events) - - `Close`, `Load`, `DOMContentLoaded` - - `Console`, `Dialog`, `Error`, `PageError` - - `Request`, `Response`, `RequestFailed`, `RequestFinished` - - `FrameAttached`, `FrameDetached`, `FrameNavigated` -- **Key Methods**: - - `GoToAsync()`: Navigate to URL - - `ScreenshotAsync()`: Capture page screenshot - - `PdfAsync()`: Generate PDF - - `EvaluateAsync()`: Execute JavaScript - - `WaitForNavigationAsync()`: Wait for navigation - - `WaitForSelectorAsync()`: Wait for element - - `InterceptRequestAsync()`: Intercept network requests - -### 4. Frame Model - -#### `IFrame` Interface & `Frame` Abstract Class -- Represents an `