Refactor Page Object: Test Pattern Refactoring
Instruction Claude
Refactors Vue component tests to use the Page Object Pattern for better maintainability and readability
- 💡 Use Case:
- Improving test maintainability by abstracting UI interactions into reusable page objects
- 📤 Expected Output:
- Test file refactored with page object factory containing getters and action methods
Prompt Content
description: Refactor a Vue component test to use the Page Object Pattern argument-hint: [test-file-path]
Page Object Pattern Refactoring
Refactor the test file located at @$1 to use the Page Object Pattern.
Context
Analyze the component import in @$1 to understand the component being tested. You need to abstract all UI interactions into a helper function.
Refactoring Rules
-
Create the Page Object Factory:
- Define an async function
create<ComponentName>Page()at the bottom of the test file. - Move the
renderAppor component rendering logic inside this function. - Return an object containing getters and action methods.
- Define an async function
-
Encapsulate Elements:
- Create getters (e.g.,
getSubmitButton,getSearchInput). - Use semantic queries:
getByRole,getByLabelText,getByPlaceholderText. - Strict rule: Do not expose
screenoruserEventdirectly in the test body; they must be accessed via the page object.
- Create getters (e.g.,
-
Define Actions:
- Create semantic action methods (e.g.,
searchFor(term),submitForm()). - Return promises for all actions.
- Create semantic action methods (e.g.,
-
Test Body Cleanup:
- Instantiate the page object at the start of each test:
const page = await createXyzPage();. - Replace all
await user.type(...)andscreen.getBy...calls with methods frompage.
- Instantiate the page object at the start of each test:
Target Code Style
Use this example as the ground truth for the desired output structure:
// BEFORE:
// const searchInput = screen.getByPlaceholderText('Search...');
// await user.type(searchInput, 'test');
// AFTER:
// const page = await createMyComponentPage();
// await page.searchFor('test');
// Page Object Structure (at bottom of file):
async function createMyComponentPage() {
await renderApp(MyComponent, {}, '/my-route');
return {
// Getters
getSearchInput: () => screen.getByPlaceholderText('Search...'),
getSubmitButton: () => screen.getByRole('button', { name: 'Submit' }),
// Actions
searchFor: async (term: string) => {
await user.type(screen.getByPlaceholderText('Search...'), term);
await user.click(screen.getByRole('button', { name: 'Submit' }));
}
};
}