【问题标题】:Cypress Custom TypeScript Command is not a FunctionCypress 自定义 TypeScript 命令不是函数
【发布时间】:2018-08-05 12:15:59
【问题描述】:

我正在 TypeScript 中实现自定义 Cypress 命令:

// support/commands.ts
const login = () => {
    console.log('Logging in...');
};

Cypress.Commands.add('login', login);

declare namespace Cypress {
    interface Chainable {
        login: typeof login;
    }
}

我尝试使用:

describe('Login Scenario', () => {
    it('should allow a user to login', () => {
        cy.visit('/');
        cy.login();
    });
});

但是,命令似乎没有设置:

TypeError: cy.login is not a function

如果我用纯 JavaScript 编写命令(删除命名空间声明并将调用更新为 (cy as any).login();,它可以工作。

我错过了什么?

【问题讨论】:

  • 您的support/commands.js 是否包含在您的support/index.js 中?
  • 有什么适合你的答案吗?
  • 导入'./commands';在 support/index.ts

标签: typescript cypress


【解决方案1】:

我通过在我的命令文件夹中添加 index.d.ts 文件来修复它。在这个文件中,我添加了这样的内容:

import { MyCustomType } from '../Types';

declare global {
  namespace Cypress {
    interface Chainable<Subject = any> {
      login(): Chainable<MyCustomType>;
    }
  }
}

如果您不导入或导出任何内容,只需省略全局命名空间声明:

declare namespace Cypress {
  interface Chainable<Subject = any> {
    login(): Chainable<MyCustomType>;
  }
}

请记住,它不适用于 Typesciprt

【讨论】:

  • 还有什么额外的步骤吗?也许您可以提供有关您的 tsconfig 的见解?
  • 它应该可以立即工作。目前,我不与赛普拉斯合作,所以我不能分享我的 tsconfig。你确定你的文件是以.d.ts后缀命名的吗?
  • 这仅适用于 index.d.ts 文件与规范位于同一文件夹中的情况。
  • 你知道为什么我们在导入某些东西时需要declare global吗?我正在导入 cypress-wait-until
  • 如果没有任何导入/导出,则认为文件在全局命名空间中看这里:github.com/microsoft/TypeScript/issues/38592#issue-619054264,或者这里,点 7 techatbloomberg.com/blog/…
【解决方案2】:

这是我使用的,我不必添加

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

在每个文件的顶部。

我在&lt;projectroot&gt;/cypress/support/index.d.ts 下有我的自定义类型

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

declare namespace Cypress {
  interface Chainable<Subject> {
    getByDataTest(tag: string): Chainable<any>
  }
}

我的&lt;projectroot&gt;/cypress/tsconfig.json 看起来像

{
  "compilerOptions": {
    "strict": true,
    "baseUrl": "../node_modules",
    "target": "es5",
    "lib": ["es5", "dom"],
    "typeRoots": ["./support"]
  },
  "include": ["**/*.ts"]
}

TypeScript 终于开心了

describe('when I want to select by data test tag', () => {
  it('should select by data test tag', () => {
    cy.getByDataTest('yolo').should('exist')
  });
});

【讨论】:

  • 请问getByDataTest方法的实现写在哪里?
  • @RajKon const getDataTag = (tag: string, value: any) => [data-${tag}="${value}"]; const getDataTestTag = (value: any) => getDataTag('test', value); Cypress.Commands.add('getByDataTest', tag => cy.get(getDataTestTag(tag)));
  • 您可以使用typestypeRoots,不能同时使用。见typescriptlang.org/docs/handbook/…
  • 如果我只使用 js 文件,而不使用带有 cypress 的 typescript 怎么办?那么命名空间声明就不能使用了
  • 您可能需要重新启动 VS,以防万一您仍然看到 linter 上的红色曲线。
【解决方案3】:

我遇到了同样的问题,我找到的所有解决方案都不适合我。在这里完成了赛普拉斯官方文档和其他解决方案中的所有内容后,我仍然收到错误 cy.login is not a function

问题是我将每个 .js 文件重命名为 .ts 并且 cypress/support/index.ts 不再加载,因为默认情况下赛普拉斯只加载 JavaScript 文件。要修复它,您需要像这样在cypress.json 中将其更改为.ts(与插件文件相同):

{
  "supportFile": "cypress/support/index.ts",
  "pluginsFile": "cypress/plugins/index.ts"
}

您也可以将带有declare namespace Cypress {... 的部分添加到commands.ts,而不是创建index.d.ts 文件,以使声明和实现在同一个文件中

【讨论】:

  • 您是否还必须更改 tsconfig 文件中的任何内容?我尝试将supportFilepluginsFile 路径设置为.ts 文件,但我收到赛普拉斯错误:“您的pluginsFile 设置为/tests/e2e/plugins/index.ts,但文件丢失,它包含语法错误, 或在需要时抛出错误。pluginsFile 必须是 .js 或 .coffee 文件。”
  • 我的 cypress/tsconfig.json 看起来像这样:{ "compilerOptions": { "strict": true, "baseUrl": "../node_modules", "target": "es6", "module": "commonjs", "lib": ["es5", "dom"], "types": ["cypress"], "esModuleInterop": true, "allowSyntheticDefaultImports": true }, "include": ["**/*.ts"] }。 PS:cmets 不允许正确的块格式化
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-27
  • 2019-11-11
  • 1970-01-01
  • 2019-12-13
相关资源
最近更新 更多