Skip to content

Commit

Permalink
Merge branch '10.0-release' into tgriesser/chore/UNIFY-1256-auto-merg…
Browse files Browse the repository at this point in the history
…e-config

* 10.0-release:
  chore: Move component-index generation to scaffold-config package (#21090)
  fix: label text should be clickable to toggle snapshot highlight (#21122)
  feat: add next preset to webpack-dev-server-fresh (#21069)
  chore: add dev-servers as deps to server to be included in the binary (#21142)
  fix: do not highlight preExtension if selected option is renameFolder (#21121)
  fix(unify): Remove 'Reconfigure' dropdown from Testing Type chooser (#21063)
  feat(unify): launchpad header breadcrumbs and reusable tooltip component (#20648)
  test: add windows-test-kitchensink job (#20847)
  fix: aut centering and height calculation (#21019)
  chore: fix tests that fail on windows (#21055)
  fix: running a new test after already having run tests (#21087)
  fix: ct project setup framework keys for next and nuxt (#21116)
  fix: remove MountReturn from scaffolded ct support file (#21119)
  fix: do not scaffold fixtures if folder exist (#21078)
  fix: revert "fix: types for Cypress.Commands.add (#20376)" (#21104)
  chore: Update Chrome (stable) to 100.0.4896.127 and Chrome (beta) to 101.0.4951.34 (#21083)
  fix: types for Cypress.Commands.add (#20376) (#20377)
  • Loading branch information
tgriesser committed Apr 20, 2022
2 parents d2e1124 + 10dfccc commit 2c8a7b3
Show file tree
Hide file tree
Showing 141 changed files with 8,034 additions and 1,084 deletions.
4 changes: 2 additions & 2 deletions browser-versions.json
@@ -1,4 +1,4 @@
{
"chrome:beta": "101.0.4951.26",
"chrome:stable": "100.0.4896.88"
"chrome:beta": "101.0.4951.34",
"chrome:stable": "100.0.4896.127"
}
64 changes: 40 additions & 24 deletions circle.yml
Expand Up @@ -29,7 +29,7 @@ mainBuildFilters: &mainBuildFilters
only:
- develop
- 10.0-release
- unify-1449-check-path-length-in-build
- zachw/add-dev-server-deps

# uncomment & add to the branch conditions below to disable the main linux
# flow if we don't want to test it for a certain branch
Expand All @@ -47,7 +47,7 @@ macWorkflowFilters: &mac-workflow-filters
or:
- equal: [ develop, << pipeline.git.branch >> ]
- equal: [ '10.0-release', << pipeline.git.branch >> ]
- equal: [ unify-1449-check-path-length-in-build, << pipeline.git.branch >> ]
- equal: [ zachw/add-dev-server-deps, << pipeline.git.branch >> ]
- matches:
pattern: "-release$"
value: << pipeline.git.branch >>
Expand All @@ -57,7 +57,7 @@ windowsWorkflowFilters: &windows-workflow-filters
or:
- equal: [ develop, << pipeline.git.branch >> ]
- equal: [ '10.0-release', << pipeline.git.branch >> ]
- equal: [ 'tgriesser/chore/fix-windows-build', << pipeline.git.branch >> ]
- equal: [ zachw/add-dev-server-deps, << pipeline.git.branch >> ]
- matches:
pattern: "-release$"
value: << pipeline.git.branch >>
Expand Down Expand Up @@ -452,6 +452,20 @@ commands:
path: /tmp/artifacts
- store-npm-logs

windows-install-chrome:
parameters:
browser:
description: browser shortname to target
type: string
steps:
- run:
# TODO: How can we have preinstalled browsers on CircleCI?
name: 'Install Chrome on Windows'
command: |
# install with `--ignore-checksums` to avoid checksum error
# https://www.gep13.co.uk/blog/chocolatey-error-hashes-do-not-match
[[ $PLATFORM == 'windows' && '<<parameters.browser>>' == 'chrome' ]] && choco install googlechrome --ignore-checksums || [[ $PLATFORM != 'windows' ]]
run-new-ui-tests:
parameters:
package:
Expand All @@ -475,13 +489,8 @@ commands:
default: ''
steps:
- restore_cached_workspace
- run:
# TODO: How can we have preinstalled browsers on CircleCI?
name: 'Install Chrome on Windows'
command: |
# install with `--ignore-checksums` to avoid checksum error
# https://www.gep13.co.uk/blog/chocolatey-error-hashes-do-not-match
[[ $PLATFORM == 'windows' && '<<parameters.browser>>' == 'chrome' ]] && choco install googlechrome --ignore-checksums || [[ $PLATFORM != 'windows' ]]
- windows-install-chrome:
browser: <<parameters.browser>>
- run:
command: |
cmd=$([[ <<parameters.percy>> == 'true' ]] && echo 'yarn percy exec --parallel -- --') || true
Expand Down Expand Up @@ -589,24 +598,26 @@ commands:
- restore_cached_binary
- run:
name: "Cloning test project and checking out release branch: <<parameters.repo>>"
working_directory: ~/
working_directory: /tmp/<<parameters.repo>>
command: |
git clone --depth 1 --no-single-branch https://github.com/cypress-io/<<parameters.repo>>.git /tmp/<<parameters.repo>>
git clone --depth 1 --no-single-branch https://github.com/cypress-io/<<parameters.repo>>.git .
cd ~/cypress/..
# install some deps for get-next-version
npm i semver@7.3.2 conventional-recommended-bump@6.1.0 conventional-changelog-angular@5.0.12
NEXT_VERSION=$(node ./cypress/scripts/get-next-version.js)
cd -
cd /tmp/<<parameters.repo>> && (git checkout $NEXT_VERSION || true)
git checkout $NEXT_VERSION || true
- when:
condition: <<parameters.pull_request_id>>
steps:
- run:
name: Check out PR <<parameters.pull_request_id>>
working_directory: /tmp/<<parameters.repo>>
command: |
git fetch origin pull/<<parameters.pull_request_id>>/head:pr-<<parameters.pull_request_id>>
git checkout pr-<<parameters.pull_request_id>>
condition: <<parameters.pull_request_id>>
steps:
- run:
name: Check out PR <<parameters.pull_request_id>>
working_directory: /tmp/<<parameters.repo>>
command: |
git fetch origin pull/<<parameters.pull_request_id>>/head:pr-<<parameters.pull_request_id>>
git checkout pr-<<parameters.pull_request_id>>
test-binary-against-rwa:
description: |
Expand Down Expand Up @@ -821,6 +832,8 @@ commands:
condition: <<parameters.wait-on>>
name: "Waiting on server to boot: <<parameters.wait-on>>"
command: "npx wait-on <<parameters.wait-on>> --timeout 120000"
- windows-install-chrome:
browser: <<parameters.browser>>
- when:
condition: <<parameters.folder>>
steps:
Expand Down Expand Up @@ -1714,7 +1727,7 @@ jobs:
- run:
name: Check current branch to persist artifacts
command: |
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "unify-1449-check-path-length-in-build" && "$CIRCLE_BRANCH" != "10.0-release" ]]; then
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "zachw/add-dev-server-deps" && "$CIRCLE_BRANCH" != "10.0-release" ]]; then
echo "Not uploading artifacts or posting install comment for this branch."
circleci-agent step halt
fi
Expand Down Expand Up @@ -2466,8 +2479,6 @@ mac-workflow: &mac-workflow
requires:
- darwin-build

# maybe run all unit tests?

- create-build-artifacts:
name: darwin-create-build-artifacts
context:
Expand Down Expand Up @@ -2539,6 +2550,11 @@ windows-workflow: &windows-workflow
- test-runner:commit-status-checks
requires:
- windows-build
- test-binary-against-kitchensink-chrome:
name: windows-test-binary-against-kitchensink-chrome
executor: windows
requires:
- windows-create-build-artifacts

workflows:
linux:
Expand Down
7 changes: 6 additions & 1 deletion cli/package.json
Expand Up @@ -8,7 +8,7 @@
"prebuild": "yarn postinstall && node ./scripts/start-build.js",
"build": "node ./scripts/build.js",
"dtslint": "dtslint types",
"postinstall": "node ./scripts/post-install.js",
"postinstall": "patch-package && node ./scripts/post-install.js",
"size": "t=\"cypress-v0.0.0.tgz\"; yarn pack --filename \"${t}\"; wc -c \"${t}\"; tar tvf \"${t}\"; rm \"${t}\";",
"test": "yarn test-unit",
"test-debug": "node --inspect-brk $(yarn bin mocha)",
Expand Down Expand Up @@ -140,5 +140,10 @@
"./mount-utils": {
"require": "./mount-utils/dist/index.js"
}
},
"workspaces": {
"nohoist": [
"@types/*"
]
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 0 additions & 2 deletions cli/scripts/post-install.js
Expand Up @@ -25,8 +25,6 @@ fs.ensureDirSync(join(__dirname, '..', 'types'))
includeTypes.forEach((folder) => {
const source = resolvePkg(`@types/${folder}`, { cwd: __dirname })

console.log(`copying ${folder} from ${source}`)

fs.copySync(source, join(__dirname, '..', 'types', folder))
})

Expand Down
1 change: 1 addition & 0 deletions guides/README.md
Expand Up @@ -13,6 +13,7 @@ For general contributor information, check out [`CONTRIBUTING.md`](../CONTRIBUTI
* [Building release artifacts](./building-release-artifacts.md)
* [Code signing](./code-signing.md)
* [Determining the next version of Cypress to be released](./next-version.md)
* [Remaining Platform Agnostic](./remaining-platform-agnostic.md)
* [Error handling](./error-handling.md)
* [Patching packages](./patch-package.md)
* [Release process](./release-process.md)
Expand Down
85 changes: 85 additions & 0 deletions guides/writing-cross-platform-javascript.md
@@ -0,0 +1,85 @@
# Writing Cross-Platform JavaScript

Cypress works on Linux, macOS and Windows. This includes both installing from npm, as well as for local development. Code should be written in a platform agnostic style.

## Handling File Paths

Throughout the code base, we access the file system in various ways, and need to be conscious of how we do so to ensure Cypress can be used and developed seamlessly on multiple platforms. One thing to keep in mind is file paths and file separators. macOS and Linux systems use `/`, and Windows uses `\`.


As a general rule, we want to use **native paths** where possible. There are a few reasons for this. Whereever we display a file path, we want to use the native file separator, since that is what the user will expect on their platform. In general, we can use the Node.js `path` module to handle this:

```js
// on linux-like systems
path.join('cypress', 'e2e') //=> `cypress/e2e`

// on Windows
path.join('cypress', 'e2e') //=> `cypress\e2e`
```

There are some exceptions to this, namely the [`globby`](https://www.npmjs.com/package/globby) module, which only supports `/` (see [here](https://github.com/sindresorhus/globby#api)) when writing glob patterns. In these cases, where an API is posix only, you can use `path.posix.join`, which will always use `/`, even on a Windows system:

```js
// don't do
const files = await globby('my-project\cypress\e2e\**\*')

// do
const files = await globby('my-project/cypress/e2e/**/*')

// or you can convert it by splitting by path.sep
// and joining with `path.posix.join`
const glob = path.posix.join('my-project/cypress/e2e/**/*'.split(path.sep))
```

The general rule of using `path` where possible applies to moving around the file system, too:

```js
path.resolve('../', '/../', '../')
// '/home' on Linux
// '/Users' on OSX
// 'C:\\Users' on Windows
```

In general, you want to avoid writing file system code using `/` and `\`, and use Node.js APIs where possible - those are cross platform and guarenteed to work.

## Use Node.js Scripts

For many developers, it's tempting to write a quick bash script to automate tasks. Maybe you'd like to delete all `.js` files, so you add a script to `package.json`:

```json
{
"scripts": {
"clean": "rm -rf **/*.js"
}
}
```

This will stop developers on Windows from running `yarn clean` unless they are specifically using a POSIX shell (like Git Bash). Instead, opt for a Node.js script where possible, or use a cross-platform Node.js module. In this case, we could use the [`rimraf`](https://www.npmjs.com/package/rimraf) module:

```json
{
"devDependencies": {
"rimraf": "3.0.2",
},
"scripts": {
"clean": "rimraf '**/*.js'"
}
}
```

Now your script is cross-platform.

## Use the os Module

You can use the `os` module to handle platform differences. One such example is line endings; `\n` on linux systems, and `\r\n` on Windows. Instead. use `os.EOL`. To check the current platform, use `os.arch()`:

```ts
import os from 'os'

os.EOL // \n on linux, \r\n on windows

os.platform()
// 'linux' on Linux
// 'win32' on Windows (32-bit / 64-bit)
// 'darwin' on OSX
```
13 changes: 8 additions & 5 deletions npm/vite-dev-server-fresh/src/devServer.ts
@@ -1,6 +1,6 @@
import debugFn from 'debug'
import getPort from 'get-port'
import { createServer as viteCreateServer } from 'vite'
import { getVite, Vite } from './getVite'
import { createViteDevServerConfig } from './resolveConfig'

const debug = debugFn('cypress:vite-dev-server:devServer')
Expand All @@ -17,8 +17,11 @@ export type ViteDevServerConfig = {
}

export async function devServer (config: ViteDevServerConfig): Promise<Cypress.ResolvedDevServerConfig> {
// This has to be the first thing we do as we need to source vite from their project's dependencies
const vite = getVite(config)

debug('Creating Vite Server')
const server = await devServer.create(config) as import('vite').ViteDevServer
const server = await devServer.create(config, vite)

debug('Vite server created')
const port = await getPort({ port: 3000 })
Expand All @@ -36,11 +39,11 @@ export async function devServer (config: ViteDevServerConfig): Promise<Cypress.R
}
}

devServer.create = async function createDevServer (devServerConfig: ViteDevServerConfig) {
devServer.create = async function createDevServer (devServerConfig: ViteDevServerConfig, vite: Vite) {
try {
const config = await createViteDevServerConfig(devServerConfig)
const config = await createViteDevServerConfig(devServerConfig, vite)

return await viteCreateServer(config)
return await vite.createServer(config)
} catch (err) {
if (err instanceof Error) {
throw err
Expand Down
21 changes: 21 additions & 0 deletions npm/vite-dev-server-fresh/src/getVite.ts
@@ -0,0 +1,21 @@
import debugFn from 'debug'
import type { ViteDevServerConfig } from './devServer'

const debug = debugFn('cypress:vite-dev-server:getVite')

export type Vite = typeof import('vite')

// "vite-dev-server" is bundled in the binary, so we need to require.resolve "vite"
// from root of the active project since we don't bundle vite internally but rather
// use the version the user has installed
export function getVite (config: ViteDevServerConfig): Vite {
try {
const viteImportPath = require.resolve('vite', { paths: [config.cypressConfig.projectRoot] })

debug('resolved viteImportPath as %s', viteImportPath)

return require(viteImportPath)
} catch (err) {
throw new Error(`Could not find "vite" in your project's dependencies. Please install "vite" to fix this error.\n\n${err}`)
}
}
5 changes: 3 additions & 2 deletions npm/vite-dev-server-fresh/src/plugins/cypress.ts
@@ -1,7 +1,7 @@
import debugFn from 'debug'
import { resolve } from 'pathe'
import type { ModuleNode, Plugin, ViteDevServer } from 'vite'
import { normalizePath } from 'vite'
import type { Vite } from '../getVite'
import fs from 'fs'

import type { ViteDevServerConfig } from '../devServer'
Expand All @@ -26,6 +26,7 @@ function getSpecsPathsSet (specs: Spec[]) {

export const Cypress = (
options: ViteDevServerConfig,
vite: Vite,
): Plugin => {
let base = '/'

Expand Down Expand Up @@ -82,7 +83,7 @@ export const Cypress = (
debug('handleHotUpdate - file', file)

// If the user provided IndexHtml is changed, do a full-reload
if (normalizePath(file) === resolve(projectRoot, indexHtmlFile)) {
if (vite.normalizePath(file) === resolve(projectRoot, indexHtmlFile)) {
server.ws.send({
type: 'full-reload',
})
Expand Down
7 changes: 5 additions & 2 deletions npm/vite-dev-server-fresh/src/plugins/inspect.ts
@@ -1,9 +1,10 @@
import debugFn from 'debug'
import type { PluginOption } from 'vite'
import type { ViteDevServerConfig } from '../devServer'

const debug = debugFn('cypress:vite-dev-server:plugins:inspect')

export const CypressInspect = async (): Promise<PluginOption | null> => {
export const CypressInspect = (config: ViteDevServerConfig): PluginOption | null => {
if (!process.env.CYPRESS_INTERNAL_VITE_INSPECT) {
debug('skipping vite inspect because CYPRESS_INTERNAL_VITE_INSPECT is not set')

Expand All @@ -13,7 +14,9 @@ export const CypressInspect = async (): Promise<PluginOption | null> => {
let Inspect

try {
Inspect = (await import('vite-plugin-inspect')).default
const inspectPluginPath = require.resolve('vite-plugin-inspect', { paths: [config.cypressConfig.projectRoot] })

Inspect = require(inspectPluginPath).default
debug('inspect was found', Inspect)
} catch (err) {
debug(`Tried to import the inspect plugin 'vite-plugin-inspect'. It's an optional peerDependency so install it if you'd like.`)
Expand Down

0 comments on commit 2c8a7b3

Please sign in to comment.