bagisto-playwright-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePlaywright Testing
Playwright 测试
Bagisto's end-to-end suites live in two independent Playwright projects, one
per package, each with its own config, fixtures and page objects:
packages/Webkul/{Admin,Shop}/tests/e2e-pw/
├── playwright.config.ts # testDir ./tests, workers 1, retries 0
├── setup.ts # adminPage / shopPage fixtures
├── pages/ # page objects (BasePage subclasses)
├── tests/ # *.spec.ts, grouped by admin menu section
├── utils/ # faker.ts, admin.ts (login)
└── data/ # fixture files for uploadsRun from the package directory, never the repo root:
bash
cd packages/Webkul/Admin
npm install && npx playwright install --with-deps chromium
npx playwright test --config=tests/e2e-pw/playwright.config.ts
npx playwright test --config=tests/e2e-pw/playwright.config.ts -g "create a category"Bagisto的端到端测试套件位于两个独立的Playwright项目中,每个包对应一个项目,各自拥有独立的配置、测试夹具和页面对象:
packages/Webkul/{Admin,Shop}/tests/e2e-pw/
├── playwright.config.ts # testDir ./tests, workers 1, retries 0
├── setup.ts # adminPage / shopPage fixtures
├── pages/ # page objects (BasePage subclasses)
├── tests/ # *.spec.ts, grouped by admin menu section
├── utils/ # faker.ts, admin.ts (login)
└── data/ # fixture files for uploads需从包目录运行,切勿从仓库根目录运行:
bash
cd packages/Webkul/Admin
npm install && npx playwright install --with-deps chromium
npx playwright test --config=tests/e2e-pw/playwright.config.ts
npx playwright test --config=tests/e2e-pw/playwright.config.ts -g "create a category"The base URL comes from .env
, not BASE_URL
.envBASE_URL基础URL来自.env
,而非BASE_URL
.envBASE_URLplaywright.config.ts.envAPP_URLts
baseURL: `${process.env.APP_URL}/`.replace(/\/+$/, "/")Nothing in either project reads . The CI workflows set a
env var and it is ignored — they work because the same step rewrites
in with . Passing on the command line does
nothing; to point a run at another host, change .
BASE_URLBASE_URLAPP_URL.envsedBASE_URL=…APP_URLplaywright.config.ts.envAPP_URLts
baseURL: `${process.env.APP_URL}/`.replace(/\/+$/, "/")两个项目中都不会读取。CI工作流会设置环境变量,但该变量会被忽略——CI能正常运行是因为同一步骤会用重写中的。在命令行传入不会产生任何效果;若要指向其他主机,需修改。
BASE_URLBASE_URLsed.envAPP_URLBASE_URL=…APP_URLReference files
参考文件
| File | Load when |
|---|---|
| authoring.md | Writing a new spec or page object — structure, fixtures, ACL tests, naming |
| troubleshooting.md | A test fails, hangs, or passes when it should not |
| 文件 | 加载时机 |
|---|---|
| authoring.md | 编写新测试用例或页面对象时——涉及结构、测试夹具、ACL测试、命名规范 |
| troubleshooting.md | 测试失败、挂起或出现误通过情况时 |
Non-negotiables
不可妥协的规则
- The suite shares one database and does not roll back. Unlike Pest, an E2E run leaves every record it creates. Write assertions that survive that: scope to the row you created, never to a global count or a list position.
- ,
workers: 1,retries: 0. Specs run in file order within a shard, so a spec that leaves the app in a changed state (a reordered list, a disabled record) affects the next one. Put the state back or assert only on what you made.fullyParallel: false - CI shards each project 10 ways (). A spec may not depend on another spec having run — shards split by file.
--shard=i/10 - Admin auth is cached to by the
.state/admin-auth.jsonfixture and reused across specs. Do not log in by hand in a spec.adminPage - Rebuild assets before running after any frontend change, or the browser loads the previous bundle and the failure will look like a test bug.
- 测试套件共享一个数据库且不会回滚。 与Pest不同,E2E测试运行后会保留所有创建的记录。因此编写断言时需确保能适应这种情况:断言范围限定在你创建的行,切勿依赖全局计数或列表位置。
- 、
workers: 1、retries: 0。 测试用例在分片内按文件顺序运行,因此若某个测试用例导致应用状态改变(如列表重排、记录禁用),会影响后续测试用例。需恢复状态或仅断言你创建的内容。fullyParallel: false - CI将每个项目拆分为10个分片()。测试用例不得依赖其他测试用例的运行——分片是按文件拆分的。
--shard=i/10 - 管理员认证信息会被缓存到,由
.state/admin-auth.json测试夹具管理,并在所有测试用例中复用。切勿在测试用例中手动登录。adminPage - 前端变更后需重新构建资源再运行测试,否则浏览器会加载旧的资源包,导致失败看起来像是测试问题。
Writing a test — the shape
测试编写规范
ts
import { test } from "../../setup";
import { CategoryPage } from "../../pages/admin/catalog/CategoryPage";
test.describe("category management", () => {
test("should create a category", async ({ adminPage }) => {
const categoryPage = new CategoryPage(adminPage);
await categoryPage.createCategory();
});
});The spec names the intent; the page object owns every locator. A spec that
contains a CSS selector belongs in a page object instead — see
authoring.md.
ts
import { test } from "../../setup";
import { CategoryPage } from "../../pages/admin/catalog/CategoryPage";
test.describe("category management", () => {
test("should create a category", async ({ adminPage }) => {
const categoryPage = new CategoryPage(adminPage);
await categoryPage.createCategory();
});
});测试用例需明确意图;所有定位器都应由页面对象管理。若测试用例中包含CSS选择器,应将其移至页面对象中——详见authoring.md。
Common mistakes
常见错误
- Asserting a global count. , "the first row", "3 sections" — all break as soon as another spec adds a record. Assert on the named thing you created.
meta.total - An unscoped locator that matches many rows. Every row of a list carries the
same action markup, so resolves to N elements and fails strict mode. Scope to the row first.
getByText("Delete") - Trusting a green new test. After writing a regression test, revert the fix and confirm it fails. On seeded data many assertions hold either way.
- Assuming a Vue tile's accessible name is its label. Icon-font glyphs land
in the accessible name, so can match nothing. Target the label element.
getByRole("button", { name: "Static Content" }) - Forgetting an open drawer or modal covers the page. Clicks on the list behind it are intercepted; close it first.
REQUIRED SUB-SKILL: Use bagisto-change-verification before calling any change done.
- 断言全局计数。 、“第一行”、“3个板块”——只要有其他测试用例添加记录,这些断言就会失效。应断言你创建的具体对象。
meta.total - 使用未限定范围的定位器,匹配多行记录。 列表中的每一行都带有相同的操作标记,因此会匹配N个元素,导致严格模式下失败。需先限定行范围。
getByText("Delete") - 轻信新测试显示的绿灯。 编写回归测试后,需还原修复内容并确认测试会失败。在有预置数据的情况下,很多断言无论是否修复都会成立。
- 假设Vue磁贴的可访问名称就是其标签。 图标字体符号会被包含在可访问名称中,因此可能无法匹配任何元素。应直接定位标签元素。
getByRole("button", { name: "Static Content" }) - 忘记打开的抽屉或模态框会遮挡页面。 点击其后方的列表会被拦截;需先关闭它。
必备子技能: 在确认任何变更完成前,需使用bagisto-change-verification。