Send With Confidence
Partner with the email service trusted by developers and marketers for time-savings, scalability, and delivery expertise.
Time to read: 7 minutes
plugins/index.js
. For the Twilio SendGrid team, there were some gotchas with certain files needing to be JavaScript files in the plugins
and support
folders and hard-to-debug Cypress errors would surface. Once you get something working it should look something like this.
plugins/index.js
file with an index.ts
file, tinker a bit with our Cypress folder’s tsconfig.json
, and finally, using TS files in our Cypress folder (like some_page.spec.ts
, index.d.ts
, or page_object.ts
)--no more Webpack preprocessor config and it just worked! We were pleased at how much cleaner and nicer it was to not manage your own Webpack preprocessor config and to have better TypeScript coverage over our files as shown below.
cy.task(“pluginName”, { … })
and Cypress.env(“someEnvVar”)
function calls for better chaining and type intellisense support when updating files. We also dug through their accompanying TypeScript documentation. This taught us how to type things like our cy.login()
custom command and how to set up a tsconfig.json
configuration file. The example application also has a tsconfig.json
for you to reference, which can provide you a great base TypeScript configuration for you to customize to your preferences. We recommend for you to stay up to date with the latest Cypress versions, dive into the official Cypress resources, and experiment with your type definition files.
cy.login()
to handle logging in through the API so it can be reused throughout all of our spec files. Here is an example of how you can type your own login custom command given user credentials and returning an auth token.
Cypress.env()
calls to better type out functions and other objects that rely on using those environment variable values like this.
cy.task()
plugin functions to handle things from API calls, polling for services, and checking for matching emails in test email inboxes. Previously when chaining any of these function calls like cy.task().then((data) => {})
, the chained data subject would be typed as any
or unknown
, which was not great for our TypeScript files. We discovered through the Cypress examples how to better type out the plugins based on the plugin name and the arguments passed through in the function calls. This allowed our TypeScript files to detect what the chained data type would be.
.then()
type and the cy.task()
argument object in your editor to double check the types are matching up correctly. At times, if you were using a chained subject from another Cypress function such as cy.getCookie(“auth_token”).its(“value”).then((token) => { })
or cy.wrap(data).then((data) => {})
, you need to type those chained data arguments too before passing it in as a cy.task(..., { token, data })
function argument or else you will still see the cy.task(...).then((data) => { })
data part typed as any
or unknown
. It’s better for you to be more explicit in a lot of the chained Cypress function types such as .its(“value”).then((token: string) => {})
or cy.wrap(data).then((data: DataType) => {})
before passing them in as part of the cy.task()
arguments object to be sure the types are working again.
plugins/index.ts
. As the number of plugins grows, we recommend for you to organize these plugin function implementations by page or feature to keep your plugins/index.ts
file small. You should make it easier to read at a glance where you define all of your cy.task(...)
functions in your plugins/index.ts
file. You can finally type out these task functions in your index.d.ts
in the following way:
index.d.ts
file in the support
folder. We recommend for you to place all of your Cypress types as well in a main TypeScript definition file to keep things organized. For bypassing missing types in external dependencies used in your Cypress test code, you may also define module files like “some-lib.d.ts”, which would include declare module ‘some-lib’
, to workaround the library’s TypeScript warnings. You can even use TypeScript’s import types feature to bring in types/interfaces defined inside your other plugins/utils files to avoid duplicating your type definitions in multiple files. You can add these types within a Cypress namespace and organize them in the following way:
cy.request()
call may need to be typed with as
such as response.body as SomeType
. Overall, your editor such as VSCode can auto-detect the chained types of your cy.task()
or cy.customCommand()
calls without you needing to add more types in your spec files to compensate for any TypeScript warnings.
cy.task()
, Cypress.env()
, and cy.customCommand()
function calls, we can get better type checking on the function arguments and outputs as well as take advantage of code completion in our IDE such as VSCode.
index.d.ts
file in which you can override or extend the “Cypress” and “Chainable” interfaces based on the custom commands, environment variables, and task plugin functions you are using. In your page object and spec TypeScript files, you can then utilize those Cypress functions and hover over or follow the definition of expected input and output types.
Partner with the email service trusted by developers and marketers for time-savings, scalability, and delivery expertise.