forked from zhongyidian/yx-react-template
fix: 修复课程运行时初始化与拖拽测试
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
d77281ff0d
commit
1e02c7835e
6 files changed
+173
-154
No files matched your search
@@ -1,4 +1,42 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { expect, type Locator, type Page, test } from "@playwright/test";
|
||||
|
||||
async function dragWithPointer(
|
||||
page: Page,
|
||||
source: Locator,
|
||||
target: Locator,
|
||||
): Promise<void> {
|
||||
const sourceBox = await source.boundingBox();
|
||||
const targetBox = await target.boundingBox();
|
||||
|
||||
if (!sourceBox || !targetBox) {
|
||||
throw new Error("Drag source or target is not visible");
|
||||
}
|
||||
|
||||
const sourcePosition = {
|
||||
x: sourceBox.x + sourceBox.width / 2,
|
||||
y: sourceBox.y + sourceBox.height / 2,
|
||||
};
|
||||
const targetPosition = {
|
||||
x: targetBox.x + targetBox.width / 2,
|
||||
y: targetBox.y + targetBox.height / 2,
|
||||
};
|
||||
|
||||
await page.mouse.move(sourcePosition.x, sourcePosition.y);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(sourcePosition.x + 10, sourcePosition.y, { steps: 5 });
|
||||
await page.waitForTimeout(150);
|
||||
await page.mouse.move(targetPosition.x, targetPosition.y, { steps: 20 });
|
||||
await page.waitForTimeout(150);
|
||||
await page.mouse.up();
|
||||
}
|
||||
|
||||
function getResource(page: Page, title: string): Locator {
|
||||
return page.getByRole("button", { name: new RegExp(title) });
|
||||
}
|
||||
|
||||
function getCategory(page: Page, title: string): Locator {
|
||||
return page.getByRole("heading", { name: title, exact: true }).locator("..");
|
||||
}
|
||||
|
||||
test.describe("CourseDemo connected flow", () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -67,104 +105,70 @@ test.describe("CourseDemo connected flow", () => {
|
||||
await expect(page.locator("text=先阅读资源卡片")).not.toBeVisible();
|
||||
});
|
||||
|
||||
// TODO: @dnd-kit drag automation is unreliable in Playwright.
|
||||
// Manual verification confirms drag-drop works correctly in real browsers.
|
||||
// Skip these tests until a stable automation approach is found.
|
||||
test.skip("drag and drop resource classification", async ({ page }) => {
|
||||
// Wait for resources to load
|
||||
await expect(page.locator('[data-guide="course-resources"]')).toBeVisible();
|
||||
test("drag and drop resource classification", async ({ page }) => {
|
||||
const policyResource = getResource(page, "资助政策微课");
|
||||
const policyZone = getCategory(page, "政策学习");
|
||||
|
||||
// Find first resource card (资助政策微课)
|
||||
const policyResource = page
|
||||
.locator('[data-guide="course-resources"]')
|
||||
.locator("text=资助政策微课")
|
||||
.first();
|
||||
await expect(policyResource).toBeVisible();
|
||||
|
||||
// Find the policy-learning drop zone
|
||||
const policyZone = page.locator("text=政策学习").first();
|
||||
await expect(policyZone).toBeVisible();
|
||||
await dragWithPointer(page, policyResource, policyZone);
|
||||
|
||||
// Use Playwright's native dragTo which works better with dnd-kit
|
||||
await policyResource.dragTo(policyZone, {
|
||||
force: true,
|
||||
timeout: 10000,
|
||||
});
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Success toast should appear (exact match with dynamic title)
|
||||
await expect(page.locator("text=/分类正确/")).toBeVisible();
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
// Progress should update
|
||||
const progressText = page.locator("text=/已完成 \\d+\\/6/");
|
||||
await expect(progressText).toBeVisible();
|
||||
await expect(page.getByText("分类正确:资助政策微课")).toBeVisible();
|
||||
await expect(page.getByText("已完成 1/6")).toBeVisible();
|
||||
await expect(policyResource).not.toBeVisible();
|
||||
});
|
||||
|
||||
test.skip("wrong category shows error toast", async ({ page }) => {
|
||||
await expect(page.locator('[data-guide="course-resources"]')).toBeVisible();
|
||||
|
||||
// Try to drop policy resource into practice (wrong category)
|
||||
const policyResource = page
|
||||
.locator('[data-guide="course-resources"]')
|
||||
.locator("text=资助政策微课")
|
||||
.first();
|
||||
const wrongZone = page.locator("text=互动实践").first();
|
||||
test("wrong category shows error toast", async ({ page }) => {
|
||||
const policyResource = getResource(page, "资助政策微课");
|
||||
const wrongZone = getCategory(page, "互动实践");
|
||||
|
||||
await expect(policyResource).toBeVisible();
|
||||
await expect(wrongZone).toBeVisible();
|
||||
await dragWithPointer(page, policyResource, wrongZone);
|
||||
|
||||
// Use Playwright's native dragTo
|
||||
await policyResource.dragTo(wrongZone, {
|
||||
force: true,
|
||||
timeout: 10000,
|
||||
});
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Error toast should appear (exact match with dynamic title)
|
||||
await expect(page.locator("text=/不属于这个分类/")).toBeVisible();
|
||||
await expect(
|
||||
page.getByText("“资助政策微课”不属于这个分类,再想一想。"),
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("已完成 0/6")).toBeVisible();
|
||||
await expect(policyResource).toBeVisible();
|
||||
});
|
||||
|
||||
test("completion overlay appears after all resources placed", async ({
|
||||
page,
|
||||
}) => {
|
||||
// This would require placing all 6 resources correctly, which is slow
|
||||
// Instead we'll just verify the reset button works
|
||||
await page.click("text=重新开始");
|
||||
await page.waitForTimeout(500);
|
||||
const placements = [
|
||||
["资助政策微课", "政策学习"],
|
||||
["申请流程图", "政策学习"],
|
||||
["诚信申请案例", "互动实践"],
|
||||
["材料自查清单", "互动实践"],
|
||||
["常见问题答疑", "学习支持"],
|
||||
["校园咨询渠道", "学习支持"],
|
||||
] as const;
|
||||
|
||||
// Toast should confirm reset
|
||||
await expect(page.locator("text=练习已重置")).toBeVisible();
|
||||
for (const [resourceTitle, categoryTitle] of placements) {
|
||||
await dragWithPointer(
|
||||
page,
|
||||
getResource(page, resourceTitle),
|
||||
getCategory(page, categoryTitle),
|
||||
);
|
||||
}
|
||||
|
||||
await expect(page.getByText("资源地图已建立")).toBeVisible();
|
||||
await expect(page.getByText("已完成 6/6")).toBeVisible();
|
||||
await expect(page.getByText("100%")).toBeVisible();
|
||||
});
|
||||
|
||||
test.skip("persists progress (session fallback)", async ({
|
||||
page,
|
||||
context,
|
||||
}) => {
|
||||
// Place one resource
|
||||
const resource = page
|
||||
.locator('[data-guide="course-resources"]')
|
||||
.locator("text=资助政策微课")
|
||||
.first();
|
||||
const zone = page.locator("text=政策学习").first();
|
||||
test("persists progress with session fallback", async ({ page }) => {
|
||||
await dragWithPointer(
|
||||
page,
|
||||
getResource(page, "资助政策微课"),
|
||||
getCategory(page, "政策学习"),
|
||||
);
|
||||
await expect(page.getByText("已完成 1/6")).toBeVisible();
|
||||
|
||||
await expect(resource).toBeVisible();
|
||||
await expect(zone).toBeVisible();
|
||||
|
||||
// Use Playwright's native dragTo
|
||||
await resource.dragTo(zone, {
|
||||
force: true,
|
||||
timeout: 10000,
|
||||
});
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Reload page
|
||||
await page.reload();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForTimeout(1500);
|
||||
|
||||
// Progress should show 1/6
|
||||
await expect(page.locator("text=已完成 1/6")).toBeVisible();
|
||||
await expect(page.locator("text=进度已恢复")).toBeVisible();
|
||||
await expect(page.getByText("进度已恢复")).toBeVisible();
|
||||
await expect(page.getByText("已完成 1/6")).toBeVisible();
|
||||
await expect(getResource(page, "资助政策微课")).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user