You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Cypress TypeScript下载读取文件及cy.downloadFile报错解决

问题修复与实现方案

cy.downloadFile 是云测试平台封装的自定义命令,出现Property 'downloadFile' does not exist on type 'cy & EventEmitter'报错的核心原因有两个:一是没有给该自定义命令补充TypeScript类型声明,二是该命令仅能在对应云测试环境运行,本地原生Cypress环境没有内置这个方法,补完类型本地调用依然会出运行时错误。

下面提供两种可落地的实现方式,覆盖云环境运行、本地调试兼容的需求,同时包含PDF内容校验的完整逻辑:

方式1:仅在对应云测试环境运行的修复方案

如果你所有测试都在云平台环境执行,只需要补全类型声明即可解决报错:

  1. 在cypress/support目录下新建类型声明文件cypress.d.ts,写入以下内容:
/// <reference types="cypress" />

declare namespace Cypress {
  interface Chainable<Subject = any> {
    downloadFile(fileUrl: string, fileName: string): Chainable<string>
  }
}
  1. 打开项目根目录的tsconfig.json,在include配置项中添加cypress/**/*.ts,确保TS能扫描到上述声明文件即可。

注意:该方案本地调试时downloadFile方法不存在,会直接报运行时错误,需要兼容本地运行的话用下面的通用方案。

方式2:本地+云环境通用方案(无平台依赖,推荐)

不需要依赖平台专属的自定义命令,原生Cypress能力就能实现点击下载PDF、校验内容的需求,环境兼容性更好:

第一步:安装依赖

先安装PDF解析依赖,执行命令:
npm i pdf-parse -D

第二步:修改Cypress配置

打开cypress.config.ts,配置下载目录、注册PDF解析的node任务:

import { defineConfig } from "cypress";
import * as path from "path";

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      // 配置浏览器自动下载,不弹出确认框
      on("before:browser:launch", (browser, launchOptions) => {
        const downloadPath = path.resolve(__dirname, "cypress", "downloads");
        if (browser.family === "chromium") {
          launchOptions.preferences.default["download"] = {
            default_directory: downloadPath,
            prompt_for_download: false,
            directory_upgrade: true,
          };
        }
        if (browser.family === "firefox") {
          launchOptions.preferences["browser.download.dir"] = downloadPath;
          launchOptions.preferences["browser.download.folderList"] = 2;
          launchOptions.preferences["browser.download.manager.showWhenStarting"] = false;
          launchOptions.preferences["browser.helperApps.neverAsk.saveToDisk"] = "application/pdf";
        }
        return launchOptions;
      });

      // 注册PDF解析任务
      on("task", {
        async parseDownloadedPdf(fileName: string) {
          const pdfPath = path.resolve(__dirname, "cypress", "downloads", fileName);
          const pdfParse = (await import("pdf-parse")).default;
          const fs = await import("fs/promises");
          const fileBuffer = await fs.readFile(pdfPath);
          const pdfContent = await pdfParse(fileBuffer);
          // 解析完成后删除临时文件,避免旧文件干扰后续测试
          await fs.unlink(pdfPath);
          return pdfContent.text;
        },
        // 直链场景直接解析buffer,不需要落盘
        async parsePdfFromBuffer(buffer: Buffer) {
          const pdfParse = (await import("pdf-parse")).default;
          const pdfContent = await pdfParse(buffer);
          return pdfContent.text;
        }
      });

      return config;
    },
  },
});

第三步:编写测试用例

/// <reference types="cypress" />

describe("PDF下载校验", () => {
  beforeEach(() => {
    // 每次用例执行前清空下载目录,避免旧文件干扰
    cy.exec("rm -rf cypress/downloads/*", { failOnNonZeroExit: false });
  });

  it("点击页面按钮下载PDF,内容包含预期字段", () => {
    // 替换为实际测试页面地址
    cy.visit("/target-page-path");
    // 替换为实际下载按钮的选择器,点击触发下载
    cy.get("[data-testid=pdf-download-btn]").click();

    // 替换为实际下载的PDF文件名,等待文件下载完成
    const pdfFileName = "test-document.pdf";
    cy.readFile(`cypress/downloads/${pdfFileName}`, { timeout: 20000 }).should("exist");

    // 解析PDF内容做断言
    cy.task("parseDownloadedPdf", pdfFileName).then((pdfText) => {
      // 替换为实际需要校验的预期文本
      expect(pdfText).to.include("预期的文档标题");
      expect(pdfText).to.include("预期的业务字段值");
    });
  });

  // 如果能拿到PDF直链,可以跳过点击下载步骤,效率更高
  it("直链场景直接解析PDF校验", () => {
    cy.request<Buffer>({
      url: "PDF文件的实际访问地址",
      encoding: null
    }).then(res => {
      cy.task("parsePdfFromBuffer", res.body).then(pdfText => {
        expect(pdfText).to.include("预期的文档内容");
      })
    })
  })
});

常见问题说明

  • 如果下载的PDF是扫描件/图片格式,pdf-parse无法提取文本,需要换成OCR相关依赖(比如tesseract.js)做内容识别,逻辑和上述流程一致,只需要替换解析部分的代码即可。
  • 下载等待时间可以根据实际网络情况调整cy.readFile的timeout配置,避免大文件下载超时导致用例失败。

内容的提问来源于stack exchange,提问作者Laxmi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 14:36:27