npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

resumewright

v0.6.0

Published

A resumable Playwright execution framework for multi-role workflow automation

Readme

ResumeWright

npm version

一个面向 Playwright 的可恢复执行框架,支持多角色 Workflow 自动化、步骤级断点续跑、DSL 脚本驱动、并行调度。


特性

| 特性 | 说明 | |---|---| | 🔄 断点续跑 | 从上次失败的步骤继续,不从头重跑 | | 🔀 跨角色变量 | URL、表单值在多角色步骤间自动流转 | | 🛡️ 防重复提交 | 已成功的非幂等 API 崩溃重启后自动命中缓存 | | ⚡ 并行执行 | 最多 N 个 Case 同时运行,可控并发 | | 📝 DSL 脚本 | 接近自然语言的关键字风格编写测试步骤 | | 🎭 角色复用 | Session 缓存,角色切换秒级完成 |


快速开始

安装

pnpm install
pnpm exec playwright install chromium

编写 Case

# cases/my-workflow.yaml
name: "我的工作流"
roles:
  user: { username: "[email protected]", password: "pass" }

steps:
  - id: step1
    role: user
    script: |
      open "https://app.example.com"
      tap "role:button[开始]"
      $url = current_url
      assert_exists "成功" 10s
      screenshot

运行

# 运行所有 Case(并发 5)
pnpm tsx run.ts run

# 运行指定 Case
pnpm tsx run.ts run cases/my-workflow.yaml

# 有头模式(调试)
pnpm tsx run.ts run --headed cases/my-workflow.yaml

# 并发 10
pnpm tsx run.ts run --concurrency 10

# 仅运行上次失败的 Case(续跑)
pnpm tsx run.ts run --only-failed

# 查看状态
pnpm tsx run.ts status

# 清除指定 Checkpoint
pnpm tsx run.ts reset cases/my-workflow.yaml

# 清除所有 Checkpoint
pnpm tsx run.ts reset --all

# 校验 YAML 语法
pnpm tsx run.ts validate

# 列出所有 Case
pnpm tsx run.ts list

DSL 语法速览

# 导航
open "https://app.example.com"
open "$workflow_url"                        # 使用变量

# 点击
tap "提交申请"                              # 文字匹配
tap "role:button[确认]"                     # ARIA role
tap "label:申请标题"                        # label 关联
tap "testid:btn-approve"                    # data-testid
tap "*采购*"                                # 包含匹配
tap "审批通过"/0                            # 第 0 个
? tap "跳过引导"                            # 非阻塞

# 输入
input "Q3 采购" to "label:申请标题"
input "$res.data.title" to "label:标题"    # 变量插值
input "" to "label:备注"                    # 清空

# 断言
assert_exists "提交成功" 10s
assert_exists "审批人"/>2                   # 出现多于 2 次
assert_not_exists "加载中" 5s
assert_text_equal "$status" "已完成"

# 变量捕获
$workflow_url = current_url
$workflow_id  = url_match "/workflow/([\w-]+)"
$doc_no       = "testid:doc-number"        # 从元素提取文字
$res          = do_get "https://api.co.com/workflow/$workflow_id"
assert_text_equal "$res.data.status" "pending"

# 其他
screenshot
wait 2s
check "同意服务条款"
upload "./fixtures/file.pdf"
keyboard "ENTER"
macro login "[email protected]" "password"       # 调用宏

目录结构

resume-wright/
├── src/
│   ├── engine/          # 六大核心引擎
│   ├── dsl/             # DSL 解析器与执行器
│   ├── adapters/        # YAML / CSV 加载
│   └── types/           # TypeScript 类型
├── cases/               # Case YAML 文件
├── macros/              # 可复用宏文件(.macro)
├── config/
│   └── elements.csv     # DOM 元素别名
├── fixtures/            # 测试附件
├── .resumewright/       # 运行时状态(加入 .gitignore)
│   ├── checkpoints/     # Step 级 Checkpoint
│   ├── sub-steps/       # SubStep 状态 + API 缓存
│   ├── states/          # 角色 Session 缓存
│   └── screenshots/     # 失败截图
└── run.ts               # CLI 入口

架构图

Case YAML + DSL Script
        ↓
  并行调度器(p-limit)
        ↓
  Workflow Engine
  ┌─────────────┬──────────────┬─────────────────┐
  │ Checkpoint  │ ContextStore │  SubStep Store  │
  └─────────────┴──────────────┴─────────────────┘
        ↓
  三层防御体系
  ┌───────────────────────────────────────────┐
  │ Network Interceptor (API 缓存)            │
  │ DOM Snapshot (页面快照恢复)               │
  │ Role Pool (Session 复用)                  │
  └───────────────────────────────────────────┘
        ↓
  Playwright Browsers

配置 elements.csv

将复杂定位器统一维护在 config/elements.csv

"name","locator"
"关闭弹窗","xpath://div[starts-with(@class,'modal-close')]//button"
"首行审批按钮","css:.task-table tbody tr:first-child .btn-approve"

在 DSL 中用 @别名 引用:

tap "@关闭弹窗"
tap "@首行审批按钮"

宏(Macro)

# macros/login.macro
open "https://app.example.com/login"
input "$1" to "label:邮箱账号"
input "$2" to "label:密码"
tap "role:button[登录]"
assert_exists "工作台" 10s
# 在 Case script 中调用
macro login "[email protected]" "password123"

内置宏:

macro rw:login "$role_name"        # 使用 Role Pool 登录
macro rw:goto_workflow             # open "$workflow_url"
macro rw:wait_status "已完成" 30s # 等待状态文字出现