如何在Cypress UI自动化测试的子类中继承父类字典的指定键?
Problem Statement
I'm writing Cypress UI test automation code and encapsulating UI elements for each webpage in corresponding classes. I have two classes for different webpages:
class WebPage1 { elements = { e1: () => console.log('return e1'), // Will be `cy.get('...')` in actual Cypress code e2: () => console.log('return e2'), e3: () => console.log('return e3') } } class WebPage2 { elements = { e1: () => console.log('return e1'), e2: () => console.log('return e2'), e4: () => console.log('return e4') } }
Both classes share the e1 and e2 keys in their elements objects (since both pages have identical elements), and they're specialized implementations of the same concept. I want to create a parent class containing e1 and e2 so WebPage1 and WebPage2 can inherit these keys. I tried this implementation but I'm unsure if it's correct or if there's a better approach:
class ParentPage { e1() { console.log('return e1') // Will be `return cy.get('...')` in actual code } e2() { console.log('return e2') } } class WebPage1 extends ParentPage { elements = { e1: () => this.e1, e2: () => this.e2, e3: () => console.log('return e3') } } class WebPage2 extends ParentPage { elements = { e1: () => this.e1, e2: () => this.e2, e4: () => console.log('return e4') } }
Answer
Great question! Let's break this down step by step:
First: Your current implementation has a small issue
Right now, when you define e1: () => this.e1, you're returning a reference to the parent class's e1 function—not executing it. If you tried to call new WebPage1().elements.e1(), it would just return the function itself instead of running console.log('return e1'). To fix this, you'd need to invoke the function:
e1: () => this.e1(), e2: () => this.e2(),
That said, this approach is still redundant because you're manually mapping each parent method to the elements object. There are cleaner ways to handle inheritance for your Page Object Model (POM).
Better Approach: Inherit and extend the elements object directly
Instead of splitting elements into class methods and then remapping them, keep the elements object pattern consistent across parent and child classes. You can use object spreading to merge the parent's elements with the child's unique elements—this follows the DRY (Don't Repeat Yourself) principle and keeps your code clean.
Here's how it works:
class ParentPage { // Parent class holds shared elements elements = { e1: () => console.log('return e1'), // Replace with `cy.get('...')` in Cypress e2: () => console.log('return e2') } } class WebPage1 extends ParentPage { // Merge parent elements with child-specific ones elements = { ...this.elements, // Spread parent's elements first e3: () => console.log('return e3') // Add unique element } } class WebPage2 extends ParentPage { elements = { ...this.elements, e4: () => console.log('return e4') } }
Why this works:
- When you extend
ParentPage, the child class inherits theelementsproperty. Using...this.elementsspreads all key-value pairs from the parent'selementsinto the child's newelementsobject. - You don't have to manually redefine
e1ande2in each child class—they're automatically included. - Calling elements works exactly like your original code:
new WebPage1().elements.e1()will execute the shared element logic.
Bonus: Using getters for dynamic element objects
If you need more flexibility (e.g., dynamic elements that change based on page state), you can use class getters to generate the merged elements object on-the-fly:
class ParentPage { get baseElements() { return { e1: () => console.log('return e1'), e2: () => console.log('return e2') } } } class WebPage1 extends ParentPage { get elements() { return { ...this.baseElements, e3: () => console.log('return e3') } } } class WebPage2 extends ParentPage { get elements() { return { ...this.baseElements, e4: () => console.log('return e4') } } }
This ensures that every time you access elements, you get a fresh merged object—useful if your parent's elements need to be updated dynamically.
内容的提问来源于stack exchange,提问作者Rnj

