### CI Setup with paperwright-action Source: https://github.com/drownek/paperwright/blob/master/README.md Example GitHub Actions workflow configuration to set up Continuous Integration for Paperwright tests. Uses the official 'paperwright-action'. ```yaml name: E2E Testson: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: drownek/paperwright-action@v1 ``` -------------------------------- ### Complete Paperwright Configuration Example Source: https://github.com/drownek/paperwright/wiki/Configuration A comprehensive example demonstrating the configuration of the Paperwright Gradle plugin, including server, test, and cleanup settings. ```kotlin paperwright { // Server configuration minecraftVersion.set("1.19.4") runDir.set("run") acceptEula.set(true) // Test configuration testsDir.set(file("src/test/e2e")) // Cleanup configuration cleanExcludePatterns.set(listOf( "server.jar", "cache", "libraries" )) } ``` -------------------------------- ### Complete TypeScript Example with Multiple Tests Source: https://github.com/drownek/paperwright/wiki/TypeScript-Support A comprehensive example demonstrating multiple TypeScript tests, including command handling, player permissions, and configuration reloads. ```typescript import { test, expect } from '@drownek/paper-e2e-runner'; test('plugin loads and handles commands', async ({ player }) => { await player.chat('/staffactivity reload'); await expect(player).toHaveReceivedMessage("You don't have permission"); }); test('op player can reload plugin config', async ({ player, server }) => { await player.makeOp(); await new Promise(r => setTimeout(r, 500)); await player.chat('/staffactivity reload'); await expect(player).toHaveReceivedMessage('Config reloaded'); }); ``` -------------------------------- ### Interact with Shop GUI Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Example of interacting with a shop GUI by opening it, locating an item, and clicking it. Asserts that a purchase message was received. ```javascript test('interact with shop GUI', async ({ player }) => { player.chat('/shop'); // Get a live handle to the GUI const gui = await player.gui({ title: /Shop/ }); // Create a locator for an item const diamondItem = gui.locator(item => item.name.includes('diamond')); // Click the item (with automatic retry) await diamondItem.click(); await expect(player).toHaveReceivedMessage('Purchased'); }); ``` -------------------------------- ### Install Paperwright Source: https://github.com/drownek/paperwright/blob/master/runner-package/README.md Install the @drownek/paperwright package using npm. ```bash npm install @drownek/paperwright ``` -------------------------------- ### Download External Plugins Source: https://github.com/drownek/paperwright/wiki/Configuration Configure the download of external plugins before the server starts. Specify the URLs of the plugin JAR files to download. ```kotlin paperwright { downloadPlugins { url("https://url/to/plugin.jar") } } ``` -------------------------------- ### Initialize Paperwright Test Environment Source: https://github.com/drownek/paperwright/wiki/Getting-Started Run this Gradle task to scaffold your test environment, including package.json, tsconfig.json, and an example test file. ```bash ./gradlew paperwrightInit ``` -------------------------------- ### TypeScript Autocomplete and IntelliSense Example Source: https://github.com/drownek/paperwright/wiki/TypeScript-Support Demonstrates how TypeScript provides autocompletion for test API methods and matchers, enhancing developer productivity. ```typescript test('example', async ({ player }) => { // TypeScript knows all available methods await player.chat('/help'); await player.gui({ title: 'Shop' }); // Autocomplete for matchers await expect(player).toHaveReceivedMessage('text'); await expect(player).toContainItem('diamond'); }); ``` -------------------------------- ### Stage Files into Run Directory Source: https://github.com/drownek/paperwright/wiki/Configuration Stage files into the run directory before the server starts. You can provide inline text content or copy from local files. Paths are relative to the run directory. ```kotlin paperwright { writeFiles { // inline text content file("plugins/SomePlugin/config.yml", """ key: "value" """.trimIndent()) // copy from a local source file file("plugins/MyPlugin/data.json", projectDir.resolve("test-fixtures/data.json")) } } ``` -------------------------------- ### Create TypeScript Configuration Source: https://github.com/drownek/paperwright/wiki/TypeScript-Support Configure the TypeScript compiler for your end-to-end tests. This setup specifies module resolution, target, and output directories. ```json { "compilerOptions": { "target": "ES2020", "module": "ES2020", "moduleResolution": "node", "esModuleInterop": true, "strict": true, "skipLibCheck": true, "outDir": "./dist", "sourceMap": true, "inlineSources": true }, "include": ["*.spec.ts"] } ``` -------------------------------- ### Comprehensive Paperwright Test Example Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference An example demonstrating various Paperwright matchers for testing Minecraft gameplay, including chat messages, inventory items, and standard assertions. Ensure necessary imports are included. ```javascript import { test, expect } from '@drownek/paperwright'; test('comprehensive test example', async ({ player, server }) => { // Minecraft-specific assertions player.chat('/help'); await expect(player).toHaveReceivedMessage('Available'); server.execute(`give ${player.username} diamond 5`); await expect(player).toContainItem('diamond'); // Standard assertions const count = player.inventory.items().length; expect(count).toBeGreaterThan(0); expect(count).toBeLessThanOrEqual(36); const item = player.inventory.items()[0]; expect(item).toBeTruthy(); expect(item.name).toMatch('diamond'); }); ``` -------------------------------- ### Write a Basic TypeScript Test Source: https://github.com/drownek/paperwright/wiki/TypeScript-Support An example of a simple end-to-end test using TypeScript. It imports necessary functions and asserts a player receives a specific chat message. ```typescript import { test, expect } from '@drownek/paper-e2e-runner'; test('player receives welcome message', async ({ player }) => { await player.chat('/help'); await expect(player).toHaveReceivedMessage('Available commands'); }); ``` -------------------------------- ### Get Live GUI Handle by RegExp Title Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Obtains a live handle to a GUI by matching its title using a regular expression. This allows for more flexible title matching, ignoring case. ```javascript // RegEx match const guiRegex = await player.gui({ title: /Staff Activity/i }); ``` -------------------------------- ### Get Live GUI Handle by String Title Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Obtains a live handle to a GUI by matching its title using a string pattern. This is the primary method for accessing dynamic GUI states. ```javascript // String match const guiStr = await player.gui({ title: 'Shop' }); ``` -------------------------------- ### player.gui({ title, timeout? }) Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Gets a live handle to a GUI matching the provided title pattern. This is the primary method for accessing and interacting with in-game graphical user interfaces for testing purposes. ```APIDOC ## player.gui({ title, timeout? }) ### Description Gets a live handle to a GUI matching the title pattern. This method is essential for initiating interactions with any in-game menu or interface. ### Method `player.gui` ### Parameters #### Path Parameters None #### Query Parameters * **title** (string | RegExp) - Required - Pattern to match GUI title. * **timeout** (number) - Optional - Max wait time in ms (default: 5000). ### Request Example ```javascript // String match const guiStr = await player.gui({ title: 'Shop' }); // RegEx match const guiRegex = await player.gui({ title: /Staff Activity/i }); // Custom timeout const guiTimeout = await player.gui({ title: 'Admin', timeout: 10000 }); ``` ### Response #### Success Response (LiveGuiHandle) Returns a `LiveGuiHandle` object representing the GUI. #### Response Example ```json { "title": "Shop Menu", "items": [...] } ``` ``` -------------------------------- ### Run Paperwright Tests Source: https://github.com/drownek/paperwright/wiki/Getting-Started Execute your end-to-end tests using this Gradle task. It handles server setup, plugin building, and test execution. ```bash ./gradlew paperwrightTest ``` -------------------------------- ### Testing Economy: Balance and Purchase Source: https://github.com/drownek/paperwright/wiki/Writing-Tests Covers testing the in-game economy. The first snippet checks the player's starting balance, and the second tests the purchasing of an item after receiving in-game currency. ```javascript test('player starts with default balance', async ({ player }) => { player.chat('/balance'); await expect(player).toHaveReceivedMessage('$1000'); }); test('player can purchase items', async ({ player, server }) => { server.execute(`eco give ${player.username} 500`); player.chat('/buy diamond'); await expect(player).toHaveReceivedMessage('Purchased'); await expect(player).toContainItem('diamond'); }); ``` -------------------------------- ### Assertion Failure Examples Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference These examples show common assertion failures encountered in Paperwright, illustrating the types of messages you might see. ```text AssertionError: Expected 5 to be greater than 10 ``` ```text AssertionError: Expected [1, 2, 3] to contain 4 ``` ```text AssertionError: Expected function to throw an error, but it did not ``` ```text AssertionError: Expected player to receive message "Welcome" within 5000ms ``` -------------------------------- ### Get Live GUI Handle with Custom Timeout Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Obtains a live handle to a GUI with a specified maximum wait time. Use this when GUIs might take longer than the default 5 seconds to appear. ```javascript // Custom timeout const guiTimeout = await player.gui({ title: 'Admin', timeout: 10000 }); ``` -------------------------------- ### Get Current GUI Title Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Retrieves the current title of the GUI associated with a live handle. Returns undefined if the GUI is closed. ```javascript const gui = await player.gui({ title: 'Shop' }); console.log(gui.title); // "Shop Menu" ``` -------------------------------- ### Economy Plugin Testing with Paperwright Source: https://github.com/drownek/paperwright/wiki/Examples Tests player balances and money transfers within an economy plugin. Use these to verify that players start with a default balance and can send money to others. ```javascript test('player starts with default balance', async ({ player }) => { player.chat('/balance'); await expect(player).toHaveReceivedMessage('$1000'); }); test('player can send money', async ({ player, server }) => { server.execute(`eco give ${player.username} 500`); player.chat('/pay Test_xx 100'); await expect(player).toHaveReceivedMessage('Sent $100'); player.chat('/balance'); await expect(player).toHaveReceivedMessage('$1400'); }); test('cannot send more money than balance', async ({ player }) => { player.chat('/pay Test_xx 999999'); await expect(player).toHaveReceivedMessage('insufficient'); }); ``` -------------------------------- ### Assertions API Reference Source: https://github.com/drownek/paperwright/wiki/Writing-Tests Shows examples of assertions for checking chat messages and inventory contents. These assertions include partial matching for messages and a timeout for inventory checks. ```javascript // Chat message (partial match, 5s timeout) await expect(player).toHaveReceivedMessage('text') // Inventory item (5s timeout) await expect(player).toContainItem('item_name') ``` -------------------------------- ### Install TypeScript Dependencies Source: https://github.com/drownek/paperwright/wiki/TypeScript-Support Add TypeScript and its Node types to your project's dev dependencies. Ensure the Paperwright e2e runner is listed as a regular dependency. ```json { "type": "module", "dependencies": { "@drownek/paper-e2e-runner": "^1.3.1" }, "devDependencies": { "typescript": "^5.0.0", "@types/node": "^20.0.0" } } ``` -------------------------------- ### Get Lore Text of Located Item Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Retrieves the lore text of a GUI item identified by a locator. This re-queries the item's lore on each call. ```javascript const item = gui.locator(i => i.name === 'clock'); const lore = item.loreText(); console.log(lore); // "From: 2024-01-01 To: 2024-01-02" ``` -------------------------------- ### TypeScript Type Checking Example Source: https://github.com/drownek/paperwright/wiki/TypeScript-Support Illustrates how TypeScript catches type errors at compile time, preventing invalid usage of methods and incorrect argument types. ```typescript // TypeScript will error on invalid usage await expect(player).toHaveReceivedMessage(123); // Error: Expected string await player.invalidMethod(); // Error: Method doesn't exist ``` -------------------------------- ### Get Display Name of Located Item Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Retrieves the display name of a GUI item identified by a locator. This re-queries the item's name on each call. ```javascript const item = gui.locator(i => i.name === 'paper'); const name = item.displayName(); console.log(name); // "Session Log" ``` -------------------------------- ### Migrate waitForGui to gui() Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Demonstrates migration from the deprecated `player.waitForGui()` to the modern `player.gui()` method for finding GUI elements. ```javascript // Old const oldGui = await player.waitForGui(g => g.title.includes('Shop')); // New const newGui = await player.gui({ title: /Shop/ }); ``` -------------------------------- ### Test Starter Kit Functionality Source: https://github.com/drownek/paperwright/wiki/Examples Tests if the starter kit grants the expected items to a player. Assumes the kit system is set up to provide items upon claiming. ```javascript test('starter kit gives items', async ({ player }) => { player.chat('/kit starter'); await expect(player).toHaveReceivedMessage('Received starter kit'); await expect(player).toContainItem('diamond_sword'); await expect(player).toContainItem('bread'); }); ``` -------------------------------- ### Configure Run Directory Source: https://github.com/drownek/paperwright/wiki/Configuration Set the directory where the test server will be located. The default is 'run'. You can change it to other paths like 'test-server'. ```kotlin runDir.set("run") ``` ```kotlin runDir.set("test-server") ``` -------------------------------- ### Test Shop Opening Source: https://github.com/drownek/paperwright/wiki/Examples Tests if the shop GUI opens correctly with the expected items. Requires a player object with chat and GUI interaction capabilities. ```javascript test('shop opens with correct items', async ({ player }) => { player.chat('/shop'); const gui = await player.gui({ title: 'Shop' }); const diamond = gui.locator(item => item.name === 'diamond'); expect(diamond.displayName()).toContain('Diamond'); }); ``` -------------------------------- ### Define a GUI Locator Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Shows how to create a locator for GUI items based on a predicate function. The locator is a query definition and does not fetch the item immediately. ```javascript const item = gui.locator(i => i.name === 'diamond'); // Locator doesn't fetch immediately - it's a query definition ``` -------------------------------- ### Testing Inventory: Starter Items Source: https://github.com/drownek/paperwright/wiki/Writing-Tests Tests the player's inventory to ensure they receive starter items after using a command. It asserts the presence of specific items like 'diamond_sword' and 'bread'. ```javascript test('player inventory has starter items', async ({ player }) => { player.chat('/starter'); await expect(player).toContainItem('diamond_sword'); await expect(player).toContainItem('bread'); }); ``` -------------------------------- ### Migrate clickItem to locator().click() Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Illustrates migration from the deprecated `gui.clickItem()` to the modern `gui.locator(predicate).click()` for interacting with items in a GUI. ```javascript // Old await gui.clickItem(i => i.name === 'diamond'); // New await gui.locator(i => i.name === 'diamond').click(); ``` -------------------------------- ### Testing Commands: Help and Admin Source: https://github.com/drownek/paperwright/wiki/Writing-Tests Demonstrates how to test chat commands. The first snippet tests the '/help' command for a general response, while the second tests an '/admin' command to verify permission checks. ```javascript test('help command works', async ({ player }) => { player.chat('/help'); await expect(player).toHaveReceivedMessage('Available commands'); }); test('admin command requires permission', async ({ player }) => { player.chat('/admin reload'); await expect(player).toHaveReceivedMessage('No permission'); }); ``` -------------------------------- ### First Test: Player Welcome Message Source: https://github.com/drownek/paperwright/wiki/Writing-Tests A simple test to verify that the player receives a welcome message upon joining. It includes a delay and an assertion to check for the specific message. ```javascript import { test, expect } from '@drownek/paperwright'; test('player receives welcome message', async ({ player }) => { await new Promise(resolve => setTimeout(resolve, 2000)); await expect(player).toHaveReceivedMessage('Welcome'); }); ``` -------------------------------- ### Accept EULA Source: https://github.com/drownek/paperwright/wiki/Configuration Automatically accept the Minecraft EULA by setting this property to true. Ensure you agree to the Minecraft EULA before enabling this. ```kotlin acceptEula.set(true) ``` -------------------------------- ### Player Joins Server Test Source: https://github.com/drownek/paperwright/blob/master/runner-package/README.md A basic test case to verify a player can join the server and receive a message. Assumes the 'player' fixture is available. ```javascript import { test, expect } from '@drownek/paperwright'; test('player can join server', async ({ player }) => { player.chat('/help'); await expect(player).toHaveReceivedMessage('Available commands'); }); ``` -------------------------------- ### Test GUI Pagination Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Navigate through different pages of a paginated GUI and verify item presence on each page. ```javascript test('navigate through pages', async ({ player }) => { player.chat('/warps'); const gui = await player.gui({ title: 'Warps' }); // Check first page const firstItem = gui.locator(i => i.getDisplayName().includes('Spawn')); await firstItem.click(); // Reopen and check next page player.chat('/warps'); const nextButton = gui.locator(i => i.name === 'arrow'); await nextButton.click(); const secondItem = gui.locator(i => i.getDisplayName().includes('Arena')); expect(secondItem.displayName()).toContain('Arena'); }); ``` -------------------------------- ### Migrate findItem to locator() Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Shows migration from the deprecated `gui.findItem()` to the modern `gui.locator()` for finding items within a GUI. ```javascript // Old const oldItem = gui.findItem(i => i.name === 'diamond'); // New const newItem = gui.locator(i => i.name === 'diamond'); ``` -------------------------------- ### Server Operations: Executing Commands Source: https://github.com/drownek/paperwright/wiki/Writing-Tests Demonstrates how to perform server operations within a test, specifically granting an item to the player using the 'server.execute' method after making the player an operator. ```javascript test('server executes commands', async ({ player, server }) => { await player.makeOp(); server.execute(`give ${player.username} diamond 64`); await expect(player).toContainItem('diamond'); }); ``` -------------------------------- ### expect(locator).toHaveLore(text, options?) Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Asserts that a GUI item, identified by a locator, contains specific lore text. This assertion includes automatic retries and configurable timeouts. ```APIDOC ## expect(locator).toHaveLore(text, options?) ### Description Asserts that a locator's item contains specific lore text, with automatic retry. This is used for verifying the content of item descriptions. ### Method `expect(locator).toHaveLore` ### Parameters #### Path Parameters None #### Query Parameters * **text** (string) - Required - The text that should appear in the item's lore. * **options.timeout** (number) - Optional - Maximum time to wait for the lore to appear (default: 5000ms). * **options.pollingRate** (number) - Optional - Interval in milliseconds at which to check for the lore (default: 100ms). ### Request Example ```javascript const item = gui.locator(i => i.name === 'clock'); // Basic assertion await expect(item).toHaveLore('Session'); // With timeout await expect(item).toHaveLore('messages', { timeout: 10000 }); // Negative assertion await expect(item).not.toHaveLore('error'); ``` ### Response #### Success Response (void) Assertion passes if the lore text is found within the specified parameters. #### Response Example ```json // No response body on success ``` ``` -------------------------------- ### Player Interacts with GUI Test Source: https://github.com/drownek/paperwright/blob/master/runner-package/README.md Tests player interaction with a server GUI, including making the player an operator, opening a GUI, locating items within the GUI, and asserting GUI element properties. Assumes the 'player' fixture is available. ```javascript test('player can interact with GUI', async ({ player }) => { await player.makeOp(); player.chat('/staffactivity view'); // Get a live handle to the GUI const gui = await player.gui({ title: /Staff activity/ }); // Create a locator for items const messageItem = gui.locator(i => i.hasLore('messages')); // Expectations automatically retry await expect(messageItem).toHaveLore('messages'); }); ``` -------------------------------- ### Basic Test Structure Source: https://github.com/drownek/paperwright/wiki/Writing-Tests Sets up a basic test using the Paperwright testing API, similar to Jest. Import necessary functions and define a test case with a description and an async callback. ```javascript import { test, expect } from '@drownek/paperwright'; test('test description', async ({ player }) => { // Your test code here }); ``` -------------------------------- ### Test Item on First Join Source: https://github.com/drownek/paperwright/wiki/Examples Verifies that a player receives an item upon their first join to the server. This test assumes the plugin is configured to grant items on initial login. ```javascript test('player receives item on first join', async ({ player }) => { // Assuming plugin gives items on first join await new Promise(resolve => setTimeout(resolve, 2000)); await expect(player).toHaveReceivedMessage('Welcome'); await expect(player).toContainItem('wooden_sword'); }); ``` -------------------------------- ### player.makeOp() Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Grants operator status to the player, allowing them to use administrative commands. ```APIDOC ## player.makeOp() ### Description Grants operator status to the player. ### Method `player.makeOp()` ### Parameters None ### Request Example ```javascript await player.makeOp(); ``` ### Response None (operation is asynchronous) ``` -------------------------------- ### Configure Tests Directory Source: https://github.com/drownek/paperwright/wiki/Configuration Specify the directory containing your test files. The default is 'src/test/e2e'. You can set it to a custom path like 'tests/integration'. ```kotlin testsDir.set(file("src/test/e2e")) ``` ```kotlin testsDir.set(file("tests/integration")) ``` -------------------------------- ### Use External Plugins Only Source: https://github.com/drownek/paperwright/wiki/Configuration Set to true to use only externally downloaded plugins and skip building the project plugin. This is useful for E2E tests with pre-downloaded plugins. ```kotlin useExternalPluginsOnly.set(true) ``` -------------------------------- ### Run Specific Test Cases Source: https://github.com/drownek/paperwright/wiki/Test-Filtering Execute specific test cases within files. Use comma-separated values to include multiple test name patterns. ```bash ./gradlew paperwrightTest -PtestNames="should connect" ``` ```bash ./gradlew paperwrightTest -PtestNames="teleport,spawn" ``` -------------------------------- ### gui.locator(predicate) Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Creates a locator for items within a GUI that match the specified predicate function. Locators are used to define queries for GUI elements that can be interacted with. ```APIDOC ## gui.locator(predicate) ### Description Creates a locator for items matching the predicate. This allows for dynamic querying of GUI elements based on their properties. ### Method `gui.locator` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **predicate** (function) - Required - A function `(item: ItemWrapper) => boolean` that returns true for matching items. ### Request Example ```javascript // By item name const compass = gui.locator(i => i.name === 'compass'); // By display name const itemByName = gui.locator(i => i.getDisplayName().includes('Session')); // By lore const itemByLore = gui.locator(i => i.hasLore('Click to view')); // Multiple conditions const complexItem = gui.locator(i => i.name === 'paper' && i.count > 1 ); ``` ### Response #### Success Response (GuiItemLocator) Returns a `GuiItemLocator` object. #### Response Example ```json { "query": "(item) => item.name === 'compass'" } ``` ``` -------------------------------- ### Player Actions API Reference Source: https://github.com/drownek/paperwright/wiki/Writing-Tests Illustrates common player actions available in the test context, such as sending chat messages, interacting with GUIs, and accessing inventory or the underlying Mineflayer bot. ```javascript player.chat('/command') // Send chat/command player.chat('Hello!') // Send chat message await player.gui({ title: 'Title' }) // Wait for GUI window player.inventory // Access inventory player.bot // Underlying Mineflayer bot ``` -------------------------------- ### Utilities: Sleep and WaitForStable Source: https://github.com/drownek/paperwright/wiki/Writing-Tests Demonstrates the use of utility functions for advanced waiting. Includes 'sleep' for pausing execution and 'waitForStable' for waiting until a condition remains true for a specified duration. ```javascript import { test, sleep, poll, waitForAssertion, waitUntil, waitForStable } from '@drownek/paperwright'; test('advanced waiting', async ({ player }) => { // Sleep for 1 second await sleep(1000); // Wait until a condition remains continuously true for 2 seconds await waitForStable(() => player.bot.health === 20, { duration: 2000, timeout: 5000 }); }); ``` -------------------------------- ### Basic Paperwright Configuration Source: https://github.com/drownek/paperwright/wiki/Configuration Configure the Paperwright plugin in your build.gradle.kts file. This includes setting the Minecraft version, run directory, test directory, EULA acceptance, and downloading plugins. ```kotlin paperwright { minecraftVersion.set("1.19.4") runDir.set("run") testsDir.set(file("src/test/e2e")) acceptEula.set(true) downloadPlugins { url("https://url.to/plugin.jar") } } ``` -------------------------------- ### Run Specific Test Files Source: https://github.com/drownek/paperwright/wiki/Test-Filtering Execute tests located in specific files. Use comma-separated values to include multiple files. ```bash ./gradlew paperwrightTest -PtestFiles="basic" ``` ```bash ./gradlew paperwrightTest -PtestFiles="basic,commands" ``` -------------------------------- ### Test Warp GUI Listing and Interaction Source: https://github.com/drownek/paperwright/wiki/Examples Tests the '/warps' command which opens a GUI listing available warps. It verifies that a specific warp ('Spawn') is listed and that interacting with a warp item (compass) triggers teleportation. ```javascript test('warp GUI lists available warps', async ({ player }) => { player.chat('/warps'); const gui = await player.gui({ title: 'Warps' }); const spawn = gui.locator(item => item.getDisplayName().includes('Spawn') ); expect(spawn).toBeTruthy(); await gui.locator(item => item.name === 'compass').click(); // Assuming compass is spawn warp await expect(player).toHaveReceivedMessage('Teleported'); }); ``` -------------------------------- ### Test Command Permissions Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Verify that a command requires specific permissions and that an admin can execute it. ```javascript test('command requires permission', async ({ player }) => { player.chat('/admin'); await expect(player).toHaveReceivedMessage('You don\'t have permission'); }); test('admin can open admin panel', async ({ player }) => { await player.makeOp(); player.chat('/admin'); const gui = await player.gui({ title: 'Admin' }); expect(gui.title).toContain('Admin'); }); ``` -------------------------------- ### Basic Command Testing with Paperwright Source: https://github.com/drownek/paperwright/wiki/Examples Tests basic command interactions, including help messages, unknown commands, and permission restrictions. Use these to verify command functionality and access control. ```javascript import { test, expect } from '@drownek/paperwright'; test('help command shows available commands', async ({ player }) => { player.chat('/help'); await expect(player).toHaveReceivedMessage('Help: Index'); }); test('unknown command shows error', async ({ player }) => { player.chat('/nonexistent'); await expect(player).toHaveReceivedMessage('Unknown command'); }); test('permission-restricted command', async ({ player }) => { player.chat('/admin reload'); await expect(player).toHaveReceivedMessage('no permission'); }); test('admin can use restricted command', async ({ player }) => { await player.makeOp(); player.chat('/admin reload'); await expect(player).toHaveReceivedMessage('Reloaded'); }); ``` -------------------------------- ### Locate Item by Exact Name Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Creates a locator for a GUI item that matches a specific item name exactly. This is a common way to find specific items within a GUI. ```javascript // By item name const compass = gui.locator(i => i.name === 'compass'); ``` -------------------------------- ### locator.click(options?) Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Clicks the GUI item identified by the locator. This action includes automatic retries to ensure the click is successful. ```APIDOC ## locator.click(options?) ### Description Clicks the located item with automatic retry. This is a fundamental interaction method for GUI elements. ### Method `locator.click` ### Parameters #### Path Parameters None #### Query Parameters * **timeout** (number) - Optional - Max wait time for the item to be clickable (default: 5000ms). ### Request Example ```javascript const item = gui.locator(i => i.name === 'diamond'); await item.click(); // Custom timeout await item.click({ timeout: 10000 }); ``` ### Response #### Success Response (void) This method does not return a value upon successful execution. #### Response Example ```json // No response body on success ``` ``` -------------------------------- ### Less Than Number Comparisons Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Use `toBeLessThan` and `toBeLessThanOrEqual` for numerical comparisons. ```javascript expect(5).toBeLessThan(10); expect(10).toBeLessThanOrEqual(10); const health = player.bot.health; expect(health).toBeLessThanOrEqual(20); ``` -------------------------------- ### Test Dynamic Lore Updates Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Verify that the activity log displays correct data and that lore updates as expected. ```javascript test('activity log shows correct data', async ({ player }) => { await player.makeOp(); player.chat('/staffactivity view'); const gui = await player.gui({ title: /Staff activity/ }); // Locator for message counter const messageItem = gui.locator(i => i.hasLore('messages')); // Wait for lore to update await expect(messageItem).toHaveLore('messages'); // Verify lore contains expected data const lore = messageItem.loreText(); expect(lore).toContain('Session'); }); ``` -------------------------------- ### Basic Command Test Source: https://github.com/drownek/paperwright/blob/master/README.md Tests if the '/help' command displays the expected message. Requires the 'expect' and 'test' functions from '@drownek/paperwright'. ```typescript import { expect, test } from '@drownek/paperwright'; test('help displays message', async ({ player }) => { player.chat('/help'); await expect(player).toHaveReceivedMessage('Help'); }); ``` -------------------------------- ### Locate Item by Multiple Conditions Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Creates a locator for a GUI item that satisfies multiple conditions simultaneously, such as matching the name and having a count greater than one. ```javascript // Multiple conditions const complexItem = gui.locator(i => i.name === 'paper' && i.count > 1 ); ``` -------------------------------- ### Set Minecraft Version Source: https://github.com/drownek/paperwright/wiki/Configuration Specify the Minecraft version for testing. This can be set to different versions like '1.19.4' or '1.20.1'. ```kotlin minecraftVersion.set("1.19.4") ``` ```kotlin minecraftVersion.set("1.20.1") ``` -------------------------------- ### player.giveItem(item, count?) Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Gives a specified quantity of an item to the player. ```APIDOC ## player.giveItem(item, count?) ### Description Gives items to the player. ### Method `player.giveItem(item, count?)` ### Parameters #### Path Parameters - **item** (string) - Required - The name of the item to give. - **count** (number) - Optional - The number of items to give. Defaults to 1 if not specified. ### Request Example ```javascript await player.giveItem('diamond', 64); ``` ### Response None (operation is asynchronous) ``` -------------------------------- ### locator.loreText() Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Retrieves the lore text associated with the GUI item identified by the locator. The lore is re-queried on each invocation. ```APIDOC ## locator.loreText() ### Description Gets the lore text of the located item. This method re-queries the item's lore each time it is called. ### Method `locator.loreText` ### Parameters None ### Request Example ```javascript const item = gui.locator(i => i.name === 'clock'); const lore = item.loreText(); console.log(lore); // "From: 2024-01-01 To: 2024-01-02" ``` ### Response #### Success Response (string) Returns the lore text of the item. #### Response Example ```json { "loreText": "From: 2024-01-01 To: 2024-01-02" } ``` ``` -------------------------------- ### Test Joining Full Arena Source: https://github.com/drownek/paperwright/wiki/Examples Checks the behavior when a player attempts to join an arena that is already full. This test fills the arena with fake players first. ```javascript test('cannot join full arena', async ({ player, server }) => { // Fill arena with fake players for (let i = 0; i < 10; i++) { server.execute(`arena addplayer Player${i}`); } player.chat('/arena join'); await expect(player).toHaveReceivedMessage('Arena is full'); }); ``` -------------------------------- ### gui.title Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Provides access to the current title of the GUI represented by the `LiveGuiHandle`. This property can be used to dynamically check or log the active GUI's title. ```APIDOC ## gui.title ### Description Gets the current GUI title. This property reflects the title of the live GUI handle, returning undefined if the GUI is closed. ### Method `gui.title` (getter) ### Parameters None ### Request Example ```javascript const gui = await player.gui({ title: 'Shop' }); console.log(gui.title); // "Shop Menu" ``` ### Response #### Success Response (string | undefined) Returns the GUI's title as a string, or undefined if the GUI is not open. #### Response Example ```json { "title": "Shop Menu" } ``` ``` -------------------------------- ### Test Joining and Leaving Arena Game Source: https://github.com/drownek/paperwright/wiki/Examples Simulates a player joining and then leaving an arena game. This test verifies the messages received upon successful join and leave actions. ```javascript test('join arena game', async ({ player }) => { player.chat('/arena join'); await expect(player).toHaveReceivedMessage('Joined arena'); player.chat('/arena leave'); await expect(player).toHaveReceivedMessage('Left arena'); }); ``` -------------------------------- ### toHaveLore Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Asserts that a GUI item locator contains specific lore text, with automatic retry. Supports timeout and polling rate configuration, and negation. ```APIDOC ## toHaveLore(text, options?) ### Description Asserts that a GUI item locator contains specific lore text, with automatic retry. ### Method `expect(item).toHaveLore(text, options?)` ### Parameters #### Parameters - **text** (string) - Text that should appear in lore - **options.timeout** (number) - Max wait time in ms (default: 5000) - **options.pollingRate** (number) - Check interval in ms (default: 100) ### Request Example ```javascript const gui = await player.gui({ title: /Activity/ }); const item = gui.locator(i => i.name === 'clock'); await expect(item).toHaveLore('Session'); await expect(item).toHaveLore('messages', { timeout: 10000 }); await expect(item).not.toHaveLore('error'); ``` ``` -------------------------------- ### Test Purchasing Item from Shop Source: https://github.com/drownek/paperwright/wiki/Examples Tests the functionality of purchasing an item from the shop. Requires the player to have sufficient currency (emeralds) and verifies the purchase confirmation message and item possession. ```javascript test('purchase item from shop', async ({ player }) => { await player.giveItem('emerald', 64); // Give currency player.chat('/shop'); const gui = await player.gui({ title: 'Shop' }); await gui.locator(item => item.name === 'diamond').click(); await expect(player).toHaveReceivedMessage('Purchased'); await expect(player).toContainItem('diamond'); }); ``` -------------------------------- ### Add Paperwright Gradle Plugin and Configuration Source: https://github.com/drownek/paperwright/wiki/Getting-Started Configure the Paperwright plugin in your build.gradle.kts file, specifying the Minecraft version and other essential settings. ```kotlin plugins { id("io.github.drownek.paperwright") version "1.3.2" } paperwright { minecraftVersion.set("1.19.4") runDir.set("run") testsDir.set(file("src/test/e2e")) acceptEula.set(true) } ``` -------------------------------- ### Combine File and Test Name Filters Source: https://github.com/drownek/paperwright/wiki/Test-Filtering Execute tests that satisfy both file name and test name criteria simultaneously. ```bash ./gradlew paperwrightTest -PtestFiles="shop" -PtestNames="purchase" ``` -------------------------------- ### Test GUI Item Click Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Ensure that clicking a specific item within a GUI triggers the expected callback message. ```javascript test('clicking GUI item triggers callback', async ({ player }) => { await player.makeOp(); player.chat('/example gui-settings'); const gui = await player.gui({ title: 'guiSettings' }); const item = gui.locator(item => item.getDisplayName().includes('guiItemInfo')); await item.click(); await expect(player).toHaveReceivedMessage('You clicked on item'); }); ``` -------------------------------- ### toContainItem Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Waits for the player's inventory to contain an item with the specified name. Supports negation. ```APIDOC ## toContainItem(itemName) ### Description Waits for the player's inventory to contain an item with the specified name. ### Method `expect(player).toContainItem(itemName)` ### Parameters #### Parameters - **itemName** (string) - Minecraft item name (e.g., 'diamond', 'stone_sword') ### Timeout 5 seconds ### Request Example ```javascript await expect(player).toContainItem('diamond'); await expect(player).toContainItem('wooden_sword'); // Negation await expect(player).not.toContainItem('bedrock'); ``` ``` -------------------------------- ### Give Items to Player Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Use `player.giveItem(item, count?)` to provide items to the player. The `count` parameter is optional. ```javascript await player.giveItem('diamond', 64); ``` -------------------------------- ### Click Located Item with Custom Timeout Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Clicks the GUI item identified by a locator with a specified maximum wait time. Use this for items that might take longer to become clickable. ```javascript // Custom timeout await item.click({ timeout: 10000 }); ``` -------------------------------- ### Teleport Player to Coordinates Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Use `player.teleport(x, y, z)` to move the player to specific coordinates in the game world. ```javascript await player.teleport(0, 100, 0); ``` -------------------------------- ### Test VIP Kit Permissions Source: https://github.com/drownek/paperwright/wiki/Examples Ensures that a VIP kit requires specific permissions to be claimed. This test checks for the appropriate permission error message. ```javascript test('VIP kit requires permission', async ({ player }) => { player.chat('/kit vip'); await expect(player).toHaveReceivedMessage('no permission'); }); ``` -------------------------------- ### Locate Item by Lore Text Inclusion Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Creates a locator for a GUI item that has specific text within its lore. This is useful for identifying items based on their descriptive text. ```javascript // By lore const itemByLore = gui.locator(i => i.hasLore('Click to view')); ``` -------------------------------- ### Locate Item by Display Name Inclusion Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Creates a locator for a GUI item based on whether its display name includes a specific substring. Useful for items with dynamic or descriptive names. ```javascript // By display name const itemByName = gui.locator(i => i.getDisplayName().includes('Session')); ``` -------------------------------- ### player.setGameMode(mode) Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Changes the player's current game mode to one of the available options. ```APIDOC ## player.setGameMode(mode) ### Description Changes the player's game mode. ### Method `player.setGameMode(mode)` ### Parameters #### Path Parameters - **mode** (string) - Required - The desired game mode. Accepted values: 'survival', 'creative', 'adventure', 'spectator'. ### Request Example ```javascript await player.setGameMode('creative'); ``` ### Response None (operation is asynchronous) ``` -------------------------------- ### Null and Undefined Checks Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Use `toBeNull`, `toBeUndefined`, and `toBeDefined` to specifically check for null, undefined, or the presence of a value. ```javascript expect(null).toBeNull(); expect(undefined).toBeUndefined(); expect(0).toBeDefined(); expect(null).toBeDefined(); // Passes, as null is not undefined ``` -------------------------------- ### GUI Interaction Test Source: https://github.com/drownek/paperwright/blob/master/README.md Tests if an admin player can interact with a GUI, click on a specific item, and receive a confirmation message. The player must be made an operator first. ```typescript test('admin can interact with gui', async ({ player }) => { await player.makeOp(); player.chat('/example gui-settings'); const gui = await player.gui({ title: 'guiSettings' }); await gui.locator(item => item.getDisplayName().includes('guiItemInfo')).click(); await expect(player).toHaveReceivedMessage('You clicked on item'); }); ``` -------------------------------- ### Player Give Item Action Source: https://github.com/drownek/paperwright/blob/master/README.md Tests the 'giveItem' action, verifying that the player receives the specified item with the correct count using 'toContainItem'. ```typescript test('give item to player', async ({ player }) => { await player.giveItem('emerald', 5); await expect(player).toContainItem('emerald', { count: 5 }); }); ``` -------------------------------- ### Player Teleport Action Source: https://github.com/drownek/paperwright/blob/master/README.md Tests the 'teleport' action for a player, verifying the bot's entity position after the teleportation. ```typescript test('teleport player', async ({ player }) => { await player.teleport(123, 100, 321); expect(player.bot.entity.position).toMatchObject({ x: 123.5, z: 321.5 }); }); ``` -------------------------------- ### Asserting GUI Item Lore Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Use `toHaveLore` to check if a GUI item has specific text in its lore. This matcher automatically retries and allows specifying a custom timeout. ```javascript const gui = await player.gui({ title: /Activity/ }); const item = gui.locator(i => i.name === 'clock'); await expect(item).toHaveLore('Session'); ``` ```javascript await expect(item).toHaveLore('messages', { timeout: 10000 }); ``` ```javascript await expect(item).not.toHaveLore('error'); ``` -------------------------------- ### locator.displayName() Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Retrieves the display name of the GUI item targeted by the locator. The name is re-queried on each call to reflect the current state. ```APIDOC ## locator.displayName() ### Description Gets the display name of the located item. This method re-queries the item's name each time it is called to ensure accuracy. ### Method `locator.displayName` ### Parameters None ### Request Example ```javascript const item = gui.locator(i => i.name === 'paper'); const name = item.displayName(); console.log(name); // "Session Log" ``` ### Response #### Success Response (string) Returns the display name of the item. #### Response Example ```json { "displayName": "Session Log" } ``` ``` -------------------------------- ### Greater Than Number Comparisons Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Use `toBeGreaterThan` and `toBeGreaterThanOrEqual` for numerical comparisons. ```javascript expect(10).toBeGreaterThan(5); expect(10).toBeGreaterThanOrEqual(10); const inventory = player.inventory.items(); expect(inventory.length).toBeGreaterThan(0); ``` -------------------------------- ### Checking Player Inventory Items Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Use `toContainItem` to verify if a player's inventory contains a specific item. This matcher supports negation to check for the absence of an item. ```javascript await expect(player).toContainItem('diamond'); ``` ```javascript await expect(player).toContainItem('wooden_sword'); ``` ```javascript await expect(player).not.toContainItem('bedrock'); ``` -------------------------------- ### player.teleport(x, y, z) Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Teleports the player to the specified three-dimensional coordinates in the game world. ```APIDOC ## player.teleport(x, y, z) ### Description Teleports the player to coordinates. ### Method `player.teleport(x, y, z)` ### Parameters #### Path Parameters - **x** (number) - Required - The X-coordinate. - **y** (number) - Required - The Y-coordinate. - **z** (number) - Required - The Z-coordinate. ### Request Example ```javascript await player.teleport(0, 100, 0); ``` ### Response None (operation is asynchronous) ``` -------------------------------- ### Compile TypeScript Tests Source: https://github.com/drownek/paperwright/wiki/TypeScript-Support Command to trigger the end-to-end test compilation and execution. Compiled JavaScript output is placed in the 'dist' directory. ```bash ./gradlew testE2E ``` -------------------------------- ### Click Located Item Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Clicks the GUI item identified by a locator. The click action includes automatic retry, ensuring the item is clickable. ```javascript const item = gui.locator(i => i.name === 'diamond'); await item.click(); ``` -------------------------------- ### toHaveReceivedMessage Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Waits for the bot to receive a message containing (or exactly matching) the text or RegExp. Supports partial and exact matches, scoped searches, and negation. ```APIDOC ## toHaveReceivedMessage(message, options?) ### Description Waits for the bot to receive a message containing (or exactly matching) the text or RegExp. ### Method `expect(player).toHaveReceivedMessage(message, options?)` ### Parameters #### Parameters - **message** (string | RegExp) - Text or pattern to search for - **options.strict** (boolean) - Require exact match (default: false) - **options.since** (number) - Buffer index to search from - **options.timeout** (number) - Max wait time in ms ### Request Example ```javascript // Partial match (default) await expect(player).toHaveReceivedMessage('Welcome'); // RegEx match await expect(player).toHaveReceivedMessage(/Welcome/i); // Exact match await expect(player).toHaveReceivedMessage('Welcome to the server!', { strict: true }); // Scoped to messages received after a specific point const marker = player.getMessageBufferIndex(); player.chat('/action'); await expect(player).toHaveReceivedMessage('Success', { since: marker }); // Negation await expect(player).not.toHaveReceivedMessage('Error'); ``` ``` -------------------------------- ### Test Kit Cooldown Source: https://github.com/drownek/paperwright/wiki/Examples Verifies that a kit cannot be claimed again before its cooldown period expires. This test simulates claiming a kit twice in quick succession. ```javascript test('kit has cooldown', async ({ player }) => { player.chat('/kit starter'); await new Promise(resolve => setTimeout(resolve, 1000)); player.chat('/kit starter'); await expect(player).toHaveReceivedMessage('cooldown'); }); ``` -------------------------------- ### Array and String Length Check with toHaveLength Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Use toHaveLength to assert the number of elements in an array or characters in a string. ```javascript expect([1, 2, 3]).toHaveLength(3); expect('hello').toHaveLength(5); ``` -------------------------------- ### Change Player Game Mode Source: https://github.com/drownek/paperwright/wiki/GUI-Testing Use `player.setGameMode(mode)` to change the player's game mode. Supported modes include 'survival', 'creative', 'adventure', and 'spectator'. ```javascript await player.setGameMode('creative'); ``` -------------------------------- ### String Matching with toMatch Source: https://github.com/drownek/paperwright/wiki/Matchers-Reference Use toMatch to assert that a string matches a regular expression or contains a specific substring. ```javascript expect('Hello World').toMatch(/World/); expect('Hello World').toMatch('World'); expect(player.bot.username).toMatch(/Test_\d+/); ```