从 MS Playwright 中的定位器页面对象获取 CSS 字符串值

问题描述 投票:0回答:2

假设我有一个包含页面对象的类。如果我在测试中实例化该类,那么我可以像通常使用剧作家一样使用页面对象。我想从这些页面对象之一获取 css 值作为字符串,以便我可以在自定义函数中使用它。

这应该让你明白我的意思

    export class PageObjects{
        constructor(page){
            this.obj1 = page.locator('#table tbody tr')
        }
    }

    test('Get Values and header names from a table', async({page})=> {
        // Page objects
        const pageObjects = new PageObjects(page)

        // I want the css from the page object?? in other words  
        // how do I pull out the '#table tbody tr' css value as a string?
        // in other words I want cssString value to be #table tbody tr
        // I have tried _selector but it just returns an empty string
        cssString = pageObjects.obj1.??????


    })

有没有办法从定位器中获取 css 值?

css playwright pageobjects
2个回答
0
投票

总的来说这不是一个好方法。

测试不应直接暴露在定位器上。

使用页面对象模型这是一个软件设计模式更好的代码抽象,可重用性和长期维护。

页面对象模型中,所有应用程序功能都以页面对象方法的形式捕获为黑框,它还封装了 UI 对象(CSS/Xpath),以便可以从单个引用位置添加或更新它们- DRY原则。

完整代码示例:

页面对象:

// playwright-dev-page.js
const { expect } = require('@playwright/test');

exports.PlaywrightDevPage = class PlaywrightDevPage {

  /**
   * @param {import('@playwright/test').Page} page
   */
  constructor(page) {
    this.page = page;
    this.getStartedLink = page.locator('a', { hasText: 'Get started' });
    this.gettingStartedHeader = page.locator('h1', { hasText: 'Installation' });
    this.pomLink = page.locator('li', { hasText: 'Guides' }).locator('a', { hasText: 'Page Object Model' });
    this.tocList = page.locator('article div.markdown ul > li > a');
  }

  async goto() {
    await this.page.goto('https://playwright.dev');
  }

  async getStarted() {
    await this.getStartedLink.first().click();
    await expect(this.gettingStartedHeader).toBeVisible();
  }

  async pageObjectModel() {
    await this.getStarted();
    await this.pomLink.click();
  }
}

测试:

    // example.spec.js
const { test, expect } = require('@playwright/test');
const { PlaywrightDevPage } = require('./playwright-dev-page');

test('getting started should contain table of contents', async ({ page }) => {
  const playwrightDev = new PlaywrightDevPage(page);
  await playwrightDev.goto();
  await playwrightDev.getStarted();
  await expect(playwrightDev.tocList).toHaveText([
    `How to install Playwright`,
    `What's Installed`,
    `How to run the example test`,
    `How to open the HTML test report`,
    `Write tests using web first assertions, page fixtures and locators`,
    `Run single test, multiple tests, headed mode`,
    `Generate tests with Codegen`,
    `See a trace of your tests`
  ]);
});

test('should show Page Object Model article', async ({ page }) => {
  const playwrightDev = new PlaywrightDevPage(page);
  await playwrightDev.goto();
  await playwrightDev.pageObjectModel();
  await expect(page.locator('article')).toContainText('Page Object Model is a common pattern');
});

0
投票

我不确定我是否遵循了这种模式的动机(剧作家已经有了一个

Page
抽象——你为什么要用另一个来包装它?)它闻起来像一个潜在的xy问题,但我不不明白为什么你不能在你的实例上将该参数设置为变量:

export class PageObject {
  constructor(page) {
    this.selector = '#table tbody tr';
    this.locator = page.locator(this.selector);
  }
}

// ...

const pageObject = new PageObject();
consolelog(pageObject.selector);

我冒昧地重命名了几个变量:复数通常是指集合,如数组和对象,所以

PageObjects
会被键入
PageObject[]
,而
obj1
是一个不清楚的名字。我不喜欢在每个类名后加上“对象”,但我不太确定它应该做什么,所以我不知道一个更好的名字。

硬编码那个选择器有点奇怪。这有效地使该类仅用于单一用途,因此您可以考虑将其作为参数,具体取决于您的用例。

我建议退后一步,从上到下重新设计您的设计。从您的目标出发,询问这是否真的是实现这些目标的正确抽象。通常,如果事情看起来很难做,并且你发现你在与你的设计或语言作斗争,这可能不是正确的方法。


如果我理解错了,你想获取元素的CSS样式,你可以使用

getComputedStyle

await page.locator("#table tbody tr")
  .evaluateAll(els => els.map(e => getComputedStyle(e));
© www.soinside.com 2019 - 2024. All rights reserved.