diff --git a/README.md b/README.md
index 10e968d76..f00df731b 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@ Recipe | Description
[Wrapping Cypress module API](./examples/fundamentals__module-api-wrap) | Writing a wrapper around "cypress run" command line parsing
[Custom browsers](./examples/fundamentals__custom-browsers) | Control which browsers the project can use, or even add a custom browser into the list
[Use Chrome Remote Interface](./examples/fundamentals__chrome-remote-debugging) | Use Chrome debugger protocol to trigger hover state and print media style
+[Out-of-the-box TypeScript](./examples/fundamentals__typescript) | Write tests in TypeScript without setting up preprocessors
[Per-test timeout](./examples/fundamentals__timeout) | Fail a test if it runs longer than the specified time limit
## Testing the DOM
diff --git a/circle.yml b/circle.yml
index 814318e6a..3e21e8fdb 100644
--- a/circle.yml
+++ b/circle.yml
@@ -291,6 +291,8 @@ jobs:
<<: *defaults
fundamentals__chrome-remote-debugging:
<<: *defaults
+ fundamentals__typescript:
+ <<: *defaults
# list all jobs to run and their dependencies here
# and then use this list from workflow definition
@@ -522,6 +524,9 @@ all_jobs: &all_jobs
requires:
- build
test-command: npm run test:ci
+ - fundamentals__typescript:
+ requires:
+ - build
# to avoid constantly tweaking required jobs on CircleCI
# we can have a single job wait on all other test jobs here.
@@ -554,6 +559,7 @@ all_jobs: &all_jobs
- fundamentals__module-api-wrap
- fundamentals__add-custom-command
- fundamentals__add-custom-command-ts
+ - fundamentals__typescript
- logging-in__csrf-tokens
- logging-in__html-web-forms
- logging-in__single-sign-on
diff --git a/examples/fundamentals__typescript/README.Md b/examples/fundamentals__typescript/README.Md
new file mode 100644
index 000000000..b5df6eb00
--- /dev/null
+++ b/examples/fundamentals__typescript/README.Md
@@ -0,0 +1,10 @@
+# Out-of-the-box TypeScript
+> Write tests in TypeScript without setting up preprocessors
+
+From Cypress 4.4.0, you can write tests in TypeScript without setting up preprocessors. See [the official doc](https://on.cypress.io/typescript-support) for more details.
+
+- Use out-of-the-box TypeScript.
+- Write spec, plugin, support files in TypeScript.
+- Define type for the custom commands.
+- Check types in the spec files.
+- Show difference between Test Runner `window` and `AUTWindow` types. And how to extend `AUTWindow` type.
diff --git a/examples/fundamentals__typescript/cypress.json b/examples/fundamentals__typescript/cypress.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/examples/fundamentals__typescript/cypress.json
@@ -0,0 +1 @@
+{}
diff --git a/examples/fundamentals__typescript/cypress/fixtures/test.html b/examples/fundamentals__typescript/cypress/fixtures/test.html
new file mode 100644
index 000000000..9a4bc48f0
--- /dev/null
+++ b/examples/fundamentals__typescript/cypress/fixtures/test.html
@@ -0,0 +1,12 @@
+
+
+
+ Test
+
+
+ click me
+
+
+
diff --git a/examples/fundamentals__typescript/cypress/integration/tests.spec.ts b/examples/fundamentals__typescript/cypress/integration/tests.spec.ts
new file mode 100644
index 000000000..db5f99b00
--- /dev/null
+++ b/examples/fundamentals__typescript/cypress/integration/tests.spec.ts
@@ -0,0 +1,22 @@
+/* global window */
+///
+
+describe('tests', () => {
+ it('test custom command', () => {
+ cy.visit('cypress/fixtures/test.html')
+ cy.clickLink('click me')
+ })
+
+ it('test extending AUTWindow', () => {
+ // Test Runner window object doesn't have add() function.
+ // So, it should fail the type check.
+ // @ts-expect-error
+ window.add = (a, b) => a + b
+
+ cy.window().then((win) => {
+ // AUT add() is defined in the fixture, test.html.
+ // So, it should pass the type check.
+ return win.add(2, 3)
+ })
+ })
+})
diff --git a/examples/fundamentals__typescript/cypress/plugins/index.ts b/examples/fundamentals__typescript/cypress/plugins/index.ts
new file mode 100644
index 000000000..aba156038
--- /dev/null
+++ b/examples/fundamentals__typescript/cypress/plugins/index.ts
@@ -0,0 +1,5 @@
+///
+
+export default (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => {
+
+}
diff --git a/examples/fundamentals__typescript/cypress/support/commands.ts b/examples/fundamentals__typescript/cypress/support/commands.ts
new file mode 100644
index 000000000..176bf4143
--- /dev/null
+++ b/examples/fundamentals__typescript/cypress/support/commands.ts
@@ -0,0 +1,6 @@
+///
+
+// Copied an example command from https://on.cypress.io/custom-commands
+Cypress.Commands.add('clickLink', (label: string | number | RegExp) => {
+ cy.get('a').contains(label).click()
+})
diff --git a/examples/fundamentals__typescript/cypress/support/index.ts b/examples/fundamentals__typescript/cypress/support/index.ts
new file mode 100644
index 000000000..d68db96df
--- /dev/null
+++ b/examples/fundamentals__typescript/cypress/support/index.ts
@@ -0,0 +1,20 @@
+// ***********************************************************
+// This example support/index.js is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands'
+
+// Alternatively you can use CommonJS syntax:
+// require('./commands')
diff --git a/examples/fundamentals__typescript/cypress/types.d.ts b/examples/fundamentals__typescript/cypress/types.d.ts
new file mode 100644
index 000000000..c3e43e81a
--- /dev/null
+++ b/examples/fundamentals__typescript/cypress/types.d.ts
@@ -0,0 +1,28 @@
+// reference code is written like below to avoid the clash in mocha types.
+// in most of the cases, simple will do.
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+
+declare namespace Cypress {
+ // add custom Cypress command to the interface Chainable
+ interface Chainable {
+ // let TS know we have a custom command cy.clickLink(...)
+ clickLink(label: string | number | RegExp): void
+ }
+
+ // add properties the application adds to its "window" object
+ // by adding them to the interface ApplicationWindow
+ interface ApplicationWindow {
+ // let TS know the application's code will add
+ // method window.add with the following signature
+ add(a: number, b: number): number
+ }
+}
diff --git a/examples/fundamentals__typescript/package.json b/examples/fundamentals__typescript/package.json
new file mode 100644
index 000000000..cc93f318e
--- /dev/null
+++ b/examples/fundamentals__typescript/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "with-typescript",
+ "version": "1.0.0",
+ "description": "Use out-of-the-box TypeScript with TypeScript",
+ "scripts": {
+ "cypress:open": "../../node_modules/.bin/cypress open",
+ "precypress:run": "npm run lint",
+ "cypress:run": "../../node_modules/.bin/cypress run",
+ "lint": "../../node_modules/.bin/tslint --project ./tsconfig.json",
+ "postlint": "npm run tsc",
+ "test:ci": "../../node_modules/.bin/cypress run",
+ "test:ci:windows": "bin-up cypress run",
+ "tsc": "../../node_modules/.bin/tsc --pretty --noEmit"
+ }
+}
diff --git a/examples/fundamentals__typescript/tsconfig.json b/examples/fundamentals__typescript/tsconfig.json
new file mode 100644
index 000000000..698a066e7
--- /dev/null
+++ b/examples/fundamentals__typescript/tsconfig.json
@@ -0,0 +1,7 @@
+// This file is required to make `npm run tsc` work.
+{
+ "include": [
+ "cypress/integration/*.ts",
+ "cypress/integration/**/*.ts",
+ ]
+}
diff --git a/package-lock.json b/package-lock.json
index ada1283ec..c5e40589d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30297,9 +30297,9 @@
}
},
"typescript": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3.tgz",
- "integrity": "sha512-Y21Xqe54TBVp+VDSNbuDYdGw0BpoR/Q6wo/+35M8PAU0vipahnyduJWirxxdxjsAkS7hue53x2zp8gz7F05u0A==",
+ "version": "3.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
+ "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==",
"dev": true
},
"ua-parser-js": {
diff --git a/package.json b/package.json
index 36ecd1235..e8e2f12be 100644
--- a/package.json
+++ b/package.json
@@ -134,7 +134,7 @@
"stop-only": "3.0.1",
"terminal-banner": "1.1.0",
"tslint": "5.9.1",
- "typescript": "3.3.3",
+ "typescript": "3.9.5",
"vue-loader": "14.2.4",
"vue-template-compiler": "2.6.10",
"wait-on": "3.2.0",